CoreUpdateCheckerpublic class CoreUpdateChecker extends Object implements UpdatableComponent, Plugin
Fields Summary |
---|
public static final String | LATEST_VERSION_PROPERTY | public static final String | MESSAGE_PROPERTY | public static final int | RD_GET_DETAILS_RETRIES | public static final int | RD_GET_MIRRORS_RETRIES | public static final int | RD_SIZE_RETRIES | public static final int | RD_SIZE_TIMEOUT | protected static CoreUpdateChecker | singleton | protected PluginInterface | plugin_interface | protected ResourceDownloaderFactory | rdf | protected LoggerChannel | log | protected ResourceDownloaderListener | rd_logger | protected boolean | first_check |
Constructors Summary |
---|
public CoreUpdateChecker()
singleton = this;
|
Methods Summary |
---|
public void | checkForUpdate(UpdateChecker checker)
try{
String current_version = plugin_interface.getAzureusVersion();
log.log( "Update check starts: current = " + current_version );
Map decoded = VersionCheckClient.getSingleton().getVersionCheckInfo(
first_check?VersionCheckClient.REASON_UPDATE_CHECK_START:VersionCheckClient.REASON_UPDATE_CHECK_PERIODIC);
displayUserMessage( decoded );
String latest_version;
String latest_file_name;
byte[] b_version = (byte[])decoded.get("version");
if ( b_version != null ){
latest_version = new String( b_version );
plugin_interface.getPluginProperties().setProperty( LATEST_VERSION_PROPERTY, latest_version );
}else{
throw( new Exception( "No version found in reply" ));
}
byte[] b_filename = (byte[]) decoded.get("filename");
if ( b_filename != null ){
latest_file_name = new String( b_filename );
}else{
throw( new Exception( "No update file details in reply" ));
}
//latest_version = "3.0.0.3";
//latest_file_name = "http://torrents.aelitis.com:88/torrents/Azureus2.5.0.0.jar.torrent";
//latest_file_name = "Azureus2.5.0.0.jar.torrent";
String msg = "Core: latest_version = '" + latest_version + "', file = '" + latest_file_name + "'";
URL full_download_url;
// since 2501 we support a full download URL, falling back to SF mirrors if this
// fails.
if ( latest_file_name.startsWith( "http" )){
try{
full_download_url = new URL( latest_file_name );
}catch( Throwable e ){
full_download_url = null;
log.log( e );
}
int pos = latest_file_name.lastIndexOf( '/" );
latest_file_name = latest_file_name.substring( pos+1 );
}else{
full_download_url = null;
}
checker.reportProgress( msg );
log.log( msg );
if ( !shouldUpdate( current_version, latest_version )){
return;
}
final String f_latest_version = latest_version;
final String f_latest_file_name = latest_file_name;
ResourceDownloader top_downloader;
if ( full_download_url == null ){
ResourceDownloader[] primary_mirrors;
primary_mirrors = getPrimaryDownloaders( latest_file_name );
// the download hierarchy is primary mirrors first (randomised alternate)
// then backup mirrors (randomised alternate)
// we don't want to load the backup mirrors until the primary mirrors fail
ResourceDownloader random_primary_mirrors = rdf.getRandomDownloader( primary_mirrors );
ResourceDownloader backup_downloader =
rdf.create(
new ResourceDownloaderDelayedFactory()
{
public ResourceDownloader
create()
{
ResourceDownloader[] backup_mirrors = getBackupDownloaders( f_latest_file_name );
return( rdf.getRandomDownloader( backup_mirrors ));
}
});
top_downloader =
rdf.getAlternateDownloader(
new ResourceDownloader[]
{
random_primary_mirrors,
backup_downloader,
});
}else{
ResourceDownloader full_rd = rdf.create( full_download_url );
full_rd = rdf.getSuffixBasedDownloader( full_rd );
ResourceDownloader primary_downloader =
rdf.create(
new ResourceDownloaderDelayedFactory()
{
public ResourceDownloader
create()
{
ResourceDownloader[] primary_mirrors = getPrimaryDownloaders( f_latest_file_name );
return( rdf.getRandomDownloader( primary_mirrors ));
}
});
ResourceDownloader backup_downloader =
rdf.create(
new ResourceDownloaderDelayedFactory()
{
public ResourceDownloader
create()
{
ResourceDownloader[] backup_mirrors = getBackupDownloaders( f_latest_file_name );
return( rdf.getRandomDownloader( backup_mirrors ));
}
});
top_downloader =
rdf.getAlternateDownloader(
new ResourceDownloader[]
{
full_rd,
primary_downloader,
backup_downloader,
});
}
top_downloader.addListener( rd_logger );
// get size so it is cached
top_downloader.getSize();
byte[] info_b = (byte[])decoded.get( "info" );
String info = null;
if ( info_b != null ){
try{
info = new String( info_b );
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
byte[] info_url_bytes = (byte[])decoded.get("info_url");
String info_url = null;
if ( info_url_bytes != null ){
try{
info_url = new String( info_url_bytes );
}catch( Exception e ){
Debug.out(e);
}
}
if ( info != null || info_url != null ){
String check;
if ( info == null ){
check = info_url;
}else if ( info_url == null ){
check = info;
}else{
check = info + "|" + info_url;
}
byte[] sig = (byte[])decoded.get( "info_sig" );
boolean ok = false;
if ( sig == null ){
Logger.log( new LogEvent( LogIDs.LOGGER, "info signature check failed - missing signature" ));
}else{
try{
AEVerifier.verifyData( check, sig );
ok = true;
}catch( Throwable e ){
Logger.log( new LogEvent( LogIDs.LOGGER, "info signature check failed", e ));
}
}
if ( !ok ){
info = null;
info_url = null;
}
}
String[] desc;
if ( info == null ){
desc = new String[]{"Core Azureus Version" };
}else{
desc = new String[]{"Core Azureus Version", info };
}
final Update update =
checker.addUpdate(
"Core Azureus Version",
desc,
latest_version,
top_downloader,
Update.RESTART_REQUIRED_YES );
if ( info_url != null ){
update.setDescriptionURL(info_url);
}
top_downloader.addListener(
new ResourceDownloaderAdapter()
{
public boolean
completed(
final ResourceDownloader downloader,
InputStream data )
{
installUpdate( checker, update, downloader, f_latest_version, data );
return( true );
}
});
}catch( Throwable e ){
log.log( e );
Debug.printStackTrace( e );
checker.failed();
}finally{
checker.completed();
first_check = false;
}
| private void | displayUserMessage(java.util.Map reply)Log and display a user message if contained within reply.
// pick up any user message in the reply
try{
Iterator it = reply.keySet().iterator();
while( it.hasNext()){
String key = (String)it.next();
// support message + message_sig
// message_1 + message_sig_1 etc
if ( key.startsWith( "message_sig" ) || !key.startsWith( "message" )){
continue;
}
byte[] message_bytes = (byte[])reply.get( key );
if ( message_bytes != null && message_bytes.length > 0 ){
String message = new String(message_bytes);
String sig_key;
int pos = key.indexOf('_");
if ( pos == -1 ){
sig_key = "message_sig";
}else{
sig_key = "message_sig" + key.substring( pos );
}
String last_message_key = "CoreUpdateChecker.last" + key;
String last = COConfigurationManager.getStringParameter( last_message_key, "" );
if ( !message.equals( last )){
byte[] signature = (byte[])reply.get( sig_key );
if ( signature == null ){
Logger.log( new LogEvent( LogIDs.LOGGER, "Signature missing from message" ));
return;
}
try{
AEVerifier.verifyData( message, signature );
}catch( Throwable e ){
Logger.log( new LogEvent( LogIDs.LOGGER, "Message signature check failed", e ));
return;
}
boolean completed = false;
if ( message.startsWith( "x:" )){
// emergency patch application
try{
URL jar_url = new URL( message.substring(2));
Logger.log( new LogEvent( LogIDs.LOGGER, "Patch application requsted: url=" + jar_url ));
File temp_dir = AETemporaryFileHandler.createTempDir();
File jar_file = new File( temp_dir, "patch.jar" );
InputStream is = rdf.create( jar_url ).download();
try{
FileUtil.copyFile( is, jar_file );
is = null;
AEVerifier.verifyData( jar_file );
ClassLoader cl = CoreUpdateChecker.class.getClassLoader();
if ( cl instanceof URLClassLoader ){
URL[] old = ((URLClassLoader)cl).getURLs();
URL[] new_urls = new URL[old.length+1];
System.arraycopy( old, 0, new_urls, 1, old.length );
new_urls[0]= jar_file.toURL();
cl = new URLClassLoader( new_urls, cl );
}else{
cl = new URLClassLoader( new URL[]{jar_file.toURL()}, cl );
}
Class cla = cl.loadClass( "org.gudy.azureus2.update.version.Patch" );
cla.newInstance();
completed = true;
}finally{
if ( is != null ){
is.close();
}
}
}catch( Throwable e ){
Logger.log( new LogEvent( LogIDs.LOGGER, "Patch application failed", e ));
}
} else if ( message.startsWith("u:") && message.length() > 4 ) {
try {
String type = message.substring(2, 3);
String url = message.substring(4);
UIFunctions uif = UIFunctionsManager.getUIFunctions();
if (uif != null) {
uif.viewURL(url, null, 0.9, 0.9, true, type.equals("1"));
}
} catch (Throwable t) {
Logger.log( new LogEvent( LogIDs.LOGGER, "URL message failed", t ));
}
// mark as complete even if errored
completed = true;
}else{
int alert_type = LogAlert.AT_WARNING;
String alert_text = message;
if ( alert_text.startsWith("i:" )){
alert_type = LogAlert.AT_INFORMATION;
alert_text = alert_text.substring(2);
}
plugin_interface.getPluginProperties().setProperty( MESSAGE_PROPERTY, alert_text );
Logger.log(new LogAlert(LogAlert.UNREPEATABLE, alert_type, alert_text));
completed = true;
}
if ( completed ){
COConfigurationManager.setParameter( last_message_key, message );
COConfigurationManager.save();
}
}
}
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}
| public static void | doUsageStats()
singleton.doUsageStatsSupport();
| protected void | doUsageStatsSupport()
try{
Map decoded = VersionCheckClient.getSingleton().getVersionCheckInfo(
first_check?VersionCheckClient.REASON_UPDATE_CHECK_START:VersionCheckClient.REASON_UPDATE_CHECK_PERIODIC);
displayUserMessage( decoded );
}finally{
first_check = false;
}
| protected ResourceDownloader[] | getBackupDownloaders(java.lang.String latest_file_name)
List res = new ArrayList();
try{
if ( latest_file_name != null ){
log.log( "Downloading backup mirrors" );
URL mirrors_url = new URL("http://azureus.sourceforge.net/mirrors.php");
ResourceDownloader rd = rdf.create( mirrors_url );
rd = rdf.getRetryDownloader( rd, RD_GET_MIRRORS_RETRIES );
rd.addListener( rd_logger );
BufferedInputStream data = new BufferedInputStream(rd.download());
Map decoded = BDecoder.decode(data);
data.close();
List mirrors = (List)decoded.get("mirrors");
for (int i=0;i<mirrors.size();i++){
String mirror = new String( (byte[])mirrors.get(i));
try{
res.add( new URL( mirror + latest_file_name ));
// res.add( new URL( "http://torrents.aelitis.com:88/torrents/Azureus2.4.0.2_signed.jar.torrent" ));
}catch(Throwable e){
log.log( "Invalid URL read:" + mirror, e );
}
}
}
}catch( Throwable e ){
log.log( "Failed to read backup mirror list", e );
}
ResourceDownloader[] dls = new ResourceDownloader[res.size()];
for (int i=0;i<res.size();i++){
URL url =(URL)res.get(i);
log.log( " Backup mirror:" +url.toString());
ResourceDownloader dl = rdf.create( url );
// add in .torrent decoder if appropriate
dl = rdf.getSuffixBasedDownloader( dl );
dls[i] = dl;
}
return( dls );
| public int | getMaximumCheckTime()
return( ( RD_SIZE_RETRIES * RD_SIZE_TIMEOUT )/1000);
| public java.lang.String | getName()
return( "Azureus Core" );
| protected ResourceDownloader[] | getPrimaryDownloaders(java.lang.String latest_file_name)
log.log( "Downloading primary mirrors" );
List res = new ArrayList();
try{
if ( latest_file_name == null ){
// very old method, non-mirror based
res.add( new URL( Constants.SF_WEB_SITE + "Azureus2.jar" ));
}else{
URL mirrors_url = new URL("http://prdownloads.sourceforge.net/azureus/" + latest_file_name + "?download");
ResourceDownloader rd = rdf.create( mirrors_url );
rd = rdf.getRetryDownloader( rd, RD_GET_MIRRORS_RETRIES );
rd.addListener( rd_logger );
String page = HTMLPageFactory.loadPage( rd.download()).getContent();
String pattern = "/azureus/" + latest_file_name + "?use_mirror=";
int position = page.indexOf(pattern);
while ( position > 0 ){
int end = page.indexOf(">", position);
if (end < 0) {
position = -1;
}else{
String mirror = page.substring(position, end);
if ( mirror.endsWith("\"")){
mirror = mirror.substring(0,mirror.length()-1);
}
try{
res.add( new URL( "http://prdownloads.sourceforge.net" + mirror ));
}catch( Throwable e ){
log.log( "Invalid URL read:" + mirror, e );
}
position = page.indexOf(pattern, position + 1);
}
}
}
}catch( Throwable e ){
log.log( "Failed to read primary mirror list", e );
}
ResourceDownloader[] dls = new ResourceDownloader[res.size()];
for (int i=0;i<res.size();i++){
URL url =(URL)res.get(i);
log.log( " Primary mirror:" +url.toString());
ResourceDownloader dl = rdf.create( url );
dl = rdf.getMetaRefreshDownloader( dl );
// add in a layer to do torrent based downloads if url ends with .torrent
dl = rdf.getSuffixBasedDownloader( dl );
dls[i] = dl;
}
return( dls );
| public void | initialize(PluginInterface _plugin_interface)
plugin_interface = _plugin_interface;
plugin_interface.getPluginProperties().setProperty( "plugin.name", "Core Updater" );
log = plugin_interface.getLogger().getChannel("CoreUpdater");
rd_logger =
new ResourceDownloaderAdapter()
{
public void
reportActivity(
ResourceDownloader downloader,
String activity )
{
log.log( activity );
}
};
Properties props = plugin_interface.getPluginProperties();
props.setProperty( "plugin.version", plugin_interface.getAzureusVersion());
rdf = plugin_interface.getUtilities().getResourceDownloaderFactory();
plugin_interface.getUpdateManager().registerUpdatableComponent( this, true );
| protected void | installUpdate(UpdateChecker checker, Update update, ResourceDownloader rd, java.lang.String version, java.io.InputStream data)
try{
data = update.verifyData( data, true );
rd.reportActivity( "Data verified successfully" );
String temp_jar_name = "Azureus2_" + version + ".jar";
String target_jar_name = "Azureus2.jar";
UpdateInstaller installer = checker.createInstaller();
installer.addResource( temp_jar_name, data );
if ( Constants.isOSX ){
installer.addMoveAction(
temp_jar_name,
installer.getInstallDir() + "/" + SystemProperties.getApplicationName() + ".app/Contents/Resources/Java/" + target_jar_name );
}else{
installer.addMoveAction(
temp_jar_name,
installer.getInstallDir() + File.separator + target_jar_name );
}
}catch( Throwable e ){
rd.reportActivity("Update install failed:" + e.getMessage());
}
| public static void | main(java.lang.String[] args)
String[][] tests = {
{ "2.4.0.0", "2.4.0.2", "true" },
{ "2.4.0.1_CVS", "2.4.0.2", "true" },
{ "2.4.0.1_B12", "2.4.0.2", "true" },
{ "2.4.0.1_B12", "2.4.0.1_B34", "true" },
{ "2.4.0.1_B12", "2.4.0.1_B6", "false" },
{ "2.4.0.0", "2.4.0.1_CVS", "false" },
{ "2.4.0.0", "2.4.0.1_B12", "false" },
{ "2.4.0.0", "2.4.0.0" , "false" },
{ "2.4.0.1_CVS", "2.4.0.1_CVS", "false" },
{ "2.4.0.1_B2", "2.4.0.1_B2", "false" },
{ "2.4.0.1_CVS", "2.4.0.1_B2", "false" },
{ "2.4.0.1_B2", "2.4.0.1_CVS", "false" },
};
for (int i=0;i<tests.length;i++){
System.out.println( shouldUpdate(tests[i][0],tests[i][1]) + " / " + tests[i][2] );
}
/*
AEDiagnostics.startup();
CoreUpdateChecker checker = new CoreUpdateChecker();
checker.log = new LoggerImpl(null).getTimeStampedChannel("");
checker.rdf = new ResourceDownloaderFactoryImpl();
checker.rd_logger =
new ResourceDownloaderAdapter()
{
public void
reportActivity(
ResourceDownloader downloader,
String activity )
{
System.out.println( activity );
}
public void
reportPercentComplete(
ResourceDownloader downloader,
int percentage )
{
System.out.println( " % = " + percentage );
}
};
ResourceDownloader[] primaries = checker.getPrimaryDownloaders( "Azureus-2.0.3.0.jar" );
for (int i=0;i<primaries.length;i++){
System.out.println( "primary: " + primaries[i].getName());
}
try{
ResourceDownloader rd = primaries[0];
rd.addListener( checker.rd_logger );
rd.download();
System.out.println( "done" );
}catch( Throwable e ){
e.printStackTrace();
}
*/
| protected static boolean | shouldUpdate(java.lang.String current_version, java.lang.String latest_version)
String current_base = Constants.getBaseVersion( current_version );
int current_inc = Constants.getIncrementalBuild( current_version );
String latest_base = Constants.getBaseVersion( latest_version );
int latest_inc = Constants.getIncrementalBuild( latest_version );
// currently we upgrade from, for example
// 1) 2.4.0.0 -> 2.4.0.2
// 2) 2.4.0.1_CVS -> 2.4.0.2
// 3) 2.4.0.1_B12 -> 2.4.0.2 and 2.4.0.1_B14
// but NOT
// 1) 2.4.0.0 -> 2.4.0.1_CVS or 2.4.0.1_B23
// 2) 2.4.0.1_CVS -> 2.4.0.1_B23
// for inc values: 0 = not CVS, -1 = _CVS, > 0 = Bnn
int major_comp = Constants.compareVersions( current_base, latest_base );
if ( major_comp < 0 && latest_inc == 0 ){
return( true ); // latest is higher version and not CVS
}
// same version, both are B versions and latest B is more recent
return( major_comp == 0 && current_inc > 0 && latest_inc > 0 && latest_inc > current_inc );
|
|