/* * Created on 13-Jul-2004 * Created by Paul Gardner * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. * */ package com.aelitis.azureus.core.impl; import java.io.File; import java.net.InetAddress; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator; import org.gudy.azureus2.core3.disk.DiskManager; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerState; import org.gudy.azureus2.core3.global.GlobalManager; import org.gudy.azureus2.core3.global.GlobalManagerAdapter; import org.gudy.azureus2.core3.global.GlobalManagerFactory; import org.gudy.azureus2.core3.global.GlobalManagerStats; import org.gudy.azureus2.core3.global.GlobalMangerProgressListener; import org.gudy.azureus2.core3.internat.*; import org.gudy.azureus2.core3.ipfilter.IpFilterManager; import org.gudy.azureus2.core3.logging.*; import org.gudy.azureus2.core3.ipfilter.*; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPeerSource; import org.gudy.azureus2.core3.security.SESecurityManager; import org.gudy.azureus2.core3.torrent.TOTorrent; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.core3.tracker.host.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.platform.PlatformManager; import org.gudy.azureus2.platform.PlatformManagerCapabilities; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.platform.PlatformManagerListener; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.torrent.Torrent; import org.gudy.azureus2.plugins.torrent.TorrentDownloader; import org.gudy.azureus2.plugins.utils.DelayedTask; import org.gudy.azureus2.plugins.utils.PowerManagementListener; import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils; import org.gudy.azureus2.pluginsimpl.local.PluginInitializer; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.backup.BackupManagerFactory; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.dht.DHT; import com.aelitis.azureus.core.dht.DHTListener; import com.aelitis.azureus.core.dht.speed.DHTSpeedTester; import com.aelitis.azureus.core.instancemanager.AZInstanceManager; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerAdapter; import com.aelitis.azureus.core.instancemanager.AZInstanceManagerFactory; import com.aelitis.azureus.core.instancemanager.AZInstanceTracked; import com.aelitis.azureus.core.nat.NATTraverser; import com.aelitis.azureus.core.networkmanager.NetworkManager; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterface; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterfaceAddress; import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminPropertyChangeListener; import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager; import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager; import com.aelitis.azureus.core.pairing.PairingManagerFactory; import com.aelitis.azureus.core.peermanager.PeerManager; import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser; import com.aelitis.azureus.core.proxy.AEProxySelectorFactory; import com.aelitis.azureus.plugins.clientid.ClientIDPlugin; import com.aelitis.azureus.core.security.CryptoManager; import com.aelitis.azureus.core.security.CryptoManagerFactory; import com.aelitis.azureus.core.speedmanager.SpeedLimitHandler; import com.aelitis.azureus.core.speedmanager.SpeedManager; import com.aelitis.azureus.core.speedmanager.SpeedManagerAdapter; import com.aelitis.azureus.core.speedmanager.SpeedManagerFactory; import com.aelitis.azureus.core.update.AzureusRestarterFactory; import com.aelitis.azureus.core.util.CopyOnWriteList; import com.aelitis.azureus.core.versioncheck.VersionCheckClient; import com.aelitis.azureus.core.vuzefile.VuzeFile; import com.aelitis.azureus.core.vuzefile.VuzeFileComponent; import com.aelitis.azureus.core.vuzefile.VuzeFileHandler; import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor; import com.aelitis.azureus.launcher.classloading.PrimaryClassloader; import com.aelitis.azureus.plugins.dht.DHTPlugin; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.DefaultRankCalculator; import com.aelitis.azureus.plugins.startstoprules.defaultplugin.StartStopRulesDefaultPlugin; import com.aelitis.azureus.plugins.tracker.dht.DHTTrackerPlugin; import com.aelitis.azureus.plugins.upnp.UPnPPlugin; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.util.MapUtils; /** * @author parg * */ public class AzureusCoreImpl implements AzureusCore { private final static LogIDs LOGID = LogIDs.CORE; protected static AzureusCore singleton; protected static AEMonitor class_mon = new AEMonitor( "AzureusCore:class" ); private static final String DM_ANNOUNCE_KEY = "AzureusCore:announce_key"; private static final boolean LOAD_PLUGINS_IN_OTHER_THREAD = true; /** * Listeners that will be fired after core has completed initialization */ static List<AzureusCoreRunningListener> coreRunningListeners = new ArrayList<AzureusCoreRunningListener>(1); static AEMonitor mon_coreRunningListeners = new AEMonitor("CoreCreationListeners"); public static AzureusCore create() throws AzureusCoreException { try{ class_mon.enter(); if ( singleton != null ){ throw( new AzureusCoreException( "Azureus core already instantiated" )); } singleton = new AzureusCoreImpl(); return( singleton ); }finally{ class_mon.exit(); } } public static boolean isCoreAvailable() { return( singleton != null ); } public static boolean isCoreRunning() { return( singleton != null && singleton.isStarted() ); } public static AzureusCore getSingleton() throws AzureusCoreException { if ( singleton == null ){ throw( new AzureusCoreException( "core not instantiated")); } return( singleton ); } private PluginInitializer pi; private GlobalManager global_manager; private AZInstanceManager instance_manager; private SpeedManager speed_manager; private CryptoManager crypto_manager; private NATTraverser nat_traverser; private final long create_time; private volatile boolean started; private volatile boolean stopped; private volatile boolean restarting; private CopyOnWriteList listeners = new CopyOnWriteList(); private CopyOnWriteList lifecycle_listeners = new CopyOnWriteList(); private List operation_listeners = new ArrayList(); private CopyOnWriteList<PowerManagementListener> power_listeners = new CopyOnWriteList<PowerManagementListener>(); private AESemaphore stopping_sem = new AESemaphore( "AzureusCore::stopping" ); private AEMonitor this_mon = new AEMonitor( "AzureusCore" ); private AzureusCoreOperation initialisation_op = createOperation( AzureusCoreOperation.OP_INITIALISATION ); public static boolean SUPPRESS_CLASSLOADER_ERRORS = false; private boolean ca_shutdown_computer_after_stop = false; private long ca_last_time_downloading = -1; private long ca_last_time_seeding = -1; private boolean prevent_sleep_remove_trigger = false; protected AzureusCoreImpl() { create_time = SystemTime.getCurrentTime(); //if(!SUPPRESS_CLASSLOADER_ERRORS && !(this.getClass().getClassLoader() instanceof PrimaryClassloader)) // System.out.println("###\nWarning: Core not instantiated through a PrimaryClassloader, this can lead to restricted functionality or bugs in future versions\n###"); COConfigurationManager.initialise(); MessageText.loadBundle(); AEDiagnostics.startup( COConfigurationManager.getBooleanParameter( "diags.enable.pending.writes", false )); COConfigurationManager.setParameter( "diags.enable.pending.writes", false ); AEDiagnostics.markDirty(); AETemporaryFileHandler.startup(); AEThread2.setOurThread(); // set up a backwards pointer from config -> app dir so we can derive one from the other. It'll get saved on closedown, no need to do so now COConfigurationManager.setParameter( "azureus.application.directory", new File( SystemProperties.getApplicationPath()).getAbsolutePath()); COConfigurationManager.setParameter( "azureus.user.directory", new File( SystemProperties.getUserPath()).getAbsolutePath()); crypto_manager = CryptoManagerFactory.getSingleton(); PlatformManagerFactory.getPlatformManager().addListener( new PlatformManagerListener() { public int eventOccurred( int type ) { if ( type == ET_SHUTDOWN ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested shutdown")); } COConfigurationManager.save(); requestStop(); return( 0 ); }else if ( type == ET_SUSPEND ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested suspend")); } COConfigurationManager.save(); }else if ( type == ET_RESUME ){ if (Logger.isEnabled()){ Logger.log(new LogEvent(LOGID, "Platform manager requested resume")); } announceAll( true ); } return( -1 ); } }); //ensure early initialization CustomizationManagerFactory.getSingleton().initialize(); AEProxySelectorFactory.getSelector(); NetworkManager.getSingleton(); PeerManager.getSingleton(); // Used to be a plugin, but not any more... ClientIDPlugin.initialize(); pi = PluginInitializer.getSingleton( this, initialisation_op ); instance_manager = AZInstanceManagerFactory.getSingleton( new AZInstanceManagerAdapter() { public String getID() { return( COConfigurationManager.getStringParameter( "ID", "" )); } public InetAddress getPublicAddress() { return( PluginInitializer.getDefaultInterface().getUtilities().getPublicAddress()); } public int[] getPorts() { return( new int[]{ TCPNetworkManager.getSingleton().getTCPListeningPortNumber(), UDPNetworkManager.getSingleton().getUDPListeningPortNumber(), UDPNetworkManager.getSingleton().getUDPNonDataListeningPortNumber()}); } public VCPublicAddress getVCPublicAddress() { return( new VCPublicAddress() { private VersionCheckClient vcc = VersionCheckClient.getSingleton(); public String getAddress() { return( vcc.getExternalIpAddress( true, false )); } public long getCacheTime() { return( vcc.getSingleton().getCacheTime( false )); } }); } public AZInstanceTracked.TrackTarget track( byte[] hash ) { List dms = getGlobalManager().getDownloadManagers(); Iterator it = dms.iterator(); DownloadManager matching_dm = null; try{ while( it.hasNext()){ DownloadManager dm = (DownloadManager)it.next(); TOTorrent torrent = dm.getTorrent(); if ( torrent == null ){ continue; } byte[] sha1_hash = (byte[])dm.getData( "AZInstanceManager::sha1_hash" ); if ( sha1_hash == null ){ sha1_hash = new SHA1Simple().calculateHash( torrent.getHash()); dm.setData( "AZInstanceManager::sha1_hash", sha1_hash ); } if ( Arrays.equals( hash, sha1_hash )){ matching_dm = dm; break; } } }catch( Throwable e ){ Debug.printStackTrace(e); } if ( matching_dm == null ){ return( null ); } if ( !matching_dm.getDownloadState().isPeerSourceEnabled( PEPeerSource.PS_PLUGIN )){ return( null ); } int dm_state = matching_dm.getState(); if ( dm_state == DownloadManager.STATE_ERROR || dm_state == DownloadManager.STATE_STOPPED ){ return( null ); } try{ final Object target = DownloadManagerImpl.getDownloadStatic( matching_dm ); final boolean is_seed = matching_dm.isDownloadComplete(true); return( new AZInstanceTracked.TrackTarget() { public Object getTarget() { return( target ); } public boolean isSeed() { return( is_seed ); } }); }catch( Throwable e ){ return( null ); } } public DHTPlugin getDHTPlugin() { PluginInterface pi = getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( pi != null ){ return( (DHTPlugin)pi.getPlugin()); } return( null ); } public UPnPPlugin getUPnPPlugin() { PluginInterface pi = getPluginManager().getPluginInterfaceByClass( UPnPPlugin.class ); if ( pi != null ){ return((UPnPPlugin)pi.getPlugin()); } return( null ); } public void addListener( final StateListener listener) { AzureusCoreImpl.this.addLifecycleListener( new AzureusCoreLifecycleAdapter() { public void started( AzureusCore core) { listener.started(); } public void stopping( AzureusCore core ) { listener.stopped(); } }); } }); if ( COConfigurationManager.getBooleanParameter( "speedmanager.enable", true )){ speed_manager = SpeedManagerFactory.createSpeedManager( this, new SpeedManagerAdapter() { private static final int UPLOAD_SPEED_ADJUST_MIN_KB_SEC = 10; private static final int DOWNLOAD_SPEED_ADJUST_MIN_KB_SEC = 300; private boolean setting_limits; public int getCurrentProtocolUploadSpeed( int average_period ) { if ( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return( stats.getProtocolSendRateNoLAN( average_period )); }else{ return(0); } } public int getCurrentDataUploadSpeed( int average_period ) { if ( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return( stats.getDataSendRateNoLAN( average_period )); }else{ return(0); } } public int getCurrentProtocolDownloadSpeed( int average_period ) { if( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return (stats.getProtocolReceiveRateNoLAN( average_period ) ); }else{ return(0); } } public int getCurrentDataDownloadSpeed( int average_period ) { if( global_manager != null ){ GlobalManagerStats stats = global_manager.getStats(); return (stats.getDataReceiveRateNoLAN( average_period ) ); }else{ return(0); } } public int getCurrentUploadLimit() { String key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); int k_per_second = COConfigurationManager.getIntParameter( key ); int bytes_per_second; if ( k_per_second == 0 ){ bytes_per_second = Integer.MAX_VALUE; }else{ bytes_per_second = k_per_second*1024; } return( bytes_per_second ); } public void setCurrentUploadLimit( int bytes_per_second ) { if ( bytes_per_second != getCurrentUploadLimit()){ String key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); int k_per_second; if ( bytes_per_second == Integer.MAX_VALUE ){ k_per_second = 0; }else{ k_per_second = (bytes_per_second+1023)/1024; } if ( k_per_second > 0 ){ k_per_second = Math.max( k_per_second, UPLOAD_SPEED_ADJUST_MIN_KB_SEC ); } COConfigurationManager.setParameter( key, k_per_second ); } } public int getCurrentDownloadLimit() { return( TransferSpeedValidator.getGlobalDownloadRateLimitBytesPerSecond()); } public void setCurrentDownloadLimit( int bytes_per_second ) { if ( bytes_per_second == Integer.MAX_VALUE ){ bytes_per_second = 0; } if ( bytes_per_second > 0 ){ bytes_per_second = Math.max( bytes_per_second, DOWNLOAD_SPEED_ADJUST_MIN_KB_SEC*1024 ); } TransferSpeedValidator.setGlobalDownloadRateLimitBytesPerSecond( bytes_per_second ); } public Object getLimits() { String up_key = TransferSpeedValidator.getActiveUploadParameter( global_manager ); String down_key = TransferSpeedValidator.getDownloadParameter(); return( new Object[]{ up_key, new Integer( COConfigurationManager.getIntParameter( up_key )), down_key, new Integer( COConfigurationManager.getIntParameter( down_key )), }); } public void setLimits( Object limits, boolean do_up, boolean do_down ) { if ( limits == null ){ return; } try{ if ( setting_limits ){ return; } setting_limits = true; Object[] bits = (Object[])limits; if ( do_up ){ COConfigurationManager.setParameter((String)bits[0], ((Integer)bits[1]).intValue()); } if ( do_down ){ COConfigurationManager.setParameter((String)bits[2], ((Integer)bits[3]).intValue()); } }finally{ setting_limits = false; } } }); } nat_traverser = new NATTraverser( this ); PeerNATTraverser.initialise( this ); BackupManagerFactory.getManager( this ); // one off explicit GC to clear up initialisation mem SimpleTimer.addEvent( "AzureusCore:gc", SystemTime.getOffsetTime(60*1000), new TimerEventPerformer() { public void perform( TimerEvent event) { System.gc(); } }); } public long getCreateTime() { return( create_time ); } protected void announceAll( boolean force ) { Logger.log( new LogEvent(LOGID, "Updating trackers" )); GlobalManager gm = getGlobalManager(); if ( gm != null ){ List downloads = gm.getDownloadManagers(); long now = SystemTime.getCurrentTime(); for (int i=0;i<downloads.size();i++){ DownloadManager dm = (DownloadManager)downloads.get(i); Long last_announce_l = (Long)dm.getUserData( DM_ANNOUNCE_KEY ); long last_announce = last_announce_l==null?create_time:last_announce_l.longValue(); TRTrackerAnnouncer an = dm.getTrackerClient(); if ( an != null ){ TRTrackerAnnouncerResponse last_announce_response = an.getLastResponse(); if ( now - last_announce > 15*60*1000 || last_announce_response == null || last_announce_response.getStatus() == TRTrackerAnnouncerResponse.ST_OFFLINE || force ){ dm.setUserData( DM_ANNOUNCE_KEY, new Long( now )); Logger.log( new LogEvent(LOGID, " updating tracker for " + dm.getDisplayName())); dm.requestTrackerAnnounce( true ); } } } } PluginInterface dht_tracker_pi = getPluginManager().getPluginInterfaceByClass( DHTTrackerPlugin.class ); if ( dht_tracker_pi != null ){ ((DHTTrackerPlugin)dht_tracker_pi.getPlugin()).announceAll(); } } public LocaleUtil getLocaleUtil() { return( LocaleUtil.getSingleton()); } public void start() throws AzureusCoreException { AEThread2.setOurThread(); try{ this_mon.enter(); if ( started ){ throw( new AzureusCoreException( "Core: already started" )); } if ( stopped ){ throw( new AzureusCoreException( "Core: already stopped" )); } started = true; }finally{ this_mon.exit(); } // If a user sets this property, it is an alias for the following settings. if ("1".equals(System.getProperty("azureus.safemode"))) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Safe mode enabled")); Constants.isSafeMode = true; System.setProperty("azureus.loadplugins", "0"); System.setProperty("azureus.disabledownloads", "1"); System.setProperty("azureus.skipSWTcheck", "1"); // Not using localised text - not sure it's safe to this early. Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogEvent.LT_WARNING, "You are running " + Constants.APP_NAME + " in safe mode - you " + "can change your configuration, but any downloads added will " + "not be remembered when you close " + Constants.APP_NAME + "." )); } /** * test to see if UI plays nicely with a really slow initialization */ String sDelayCore = System.getProperty("delay.core", null); if (sDelayCore != null) { try { long delayCore = Long.parseLong(sDelayCore); Thread.sleep(delayCore); } catch (Exception e) { e.printStackTrace(); } } // run plugin loading in parallel to the global manager loading AEThread2 pluginload = new AEThread2("PluginLoader",true) { public void run() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Loading of Plugins starts")); pi.loadPlugins(AzureusCoreImpl.this, false, !"0".equals(System.getProperty("azureus.loadplugins")), true, true); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Loading of Plugins complete")); } }; if (LOAD_PLUGINS_IN_OTHER_THREAD) { pluginload.start(); } else { pluginload.run(); } // Disable async loading of existing torrents, because there are many things // (like hosting) that require all the torrents to be loaded. While we // can write code for each of these cases to wait until the torrents are // loaded, it's a pretty big job to find them all and fix all their quirks. // Too big of a job for this late in the release stage. // Other example is the tracker plugin that is coded in a way where it must // always publish a complete rss feed global_manager = GlobalManagerFactory.create( this, new GlobalMangerProgressListener() { public void reportCurrentTask( String currentTask ) { initialisation_op.reportCurrentTask( currentTask ); } public void reportPercent( int percent ) { initialisation_op.reportPercent( percent ); } }, 0); if (stopped) { System.err.println("Core stopped while starting"); return; } // wait until plugin loading is done if (LOAD_PLUGINS_IN_OTHER_THREAD) { pluginload.join(); } if (stopped) { System.err.println("Core stopped while starting"); return; } VuzeFileHandler.getSingleton().addProcessor( new VuzeFileProcessor() { public void process( VuzeFile[] files, int expected_types ) { for (int i=0;i<files.length;i++){ VuzeFile vf = files[i]; VuzeFileComponent[] comps = vf.getComponents(); for (int j=0;j<comps.length;j++){ VuzeFileComponent comp = comps[j]; int comp_type = comp.getType(); if ( comp_type == VuzeFileComponent.COMP_TYPE_ADD_TORRENT ){ PluginInterface default_pi = getPluginManager().getDefaultPluginInterface(); Map map = comp.getContent(); try{ Torrent torrent; String url = MapUtils.getMapString(map, "torrent_url", null ); if ( url != null ){ TorrentDownloader dl = default_pi.getTorrentManager().getURLDownloader( new URL( url )); torrent = dl.download(); }else{ String tf = MapUtils.getMapString(map, "torrent_file", null ); if ( tf != null ){ File file = new File( tf ); if ( !file.canRead() || file.isDirectory()){ throw( new Exception( "torrent_file '" + tf + "' is invalid" )); } torrent = default_pi.getTorrentManager().createFromBEncodedFile(file); }else{ throw( new Exception( "torrent_url or torrent_file must be specified" )); } } File dest = null; String save_folder = MapUtils.getMapString(map, "save_folder", null ); if ( save_folder != null ){ dest = new File( save_folder, torrent.getName()); }else{ String save_file = MapUtils.getMapString(map, "save_file", null ); if ( save_file != null ){ dest = new File( save_file ); } } if ( dest != null ){ dest.getParentFile().mkdirs(); } default_pi.getDownloadManager().addDownload( torrent, null, dest ); }catch( Throwable e ){ Debug.out( e ); } comp.setProcessed(); } } } } }); triggerLifeCycleComponentCreated(global_manager); pi.initialisePlugins(); if (stopped) { System.err.println("Core stopped while starting"); return; } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Initializing Plugins complete")); try{ PluginInterface dht_pi = getPluginManager().getPluginInterfaceByClass( DHTPlugin.class ); if ( dht_pi != null ){ dht_pi.addEventListener( new PluginEventListener() { private boolean first_dht = true; public void handleEvent( PluginEvent ev ) { if ( ev.getType() == DHTPlugin.EVENT_DHT_AVAILABLE ){ if ( first_dht ){ first_dht = false; DHT dht = (DHT)ev.getValue(); dht.addListener( new DHTListener() { public void speedTesterAvailable( DHTSpeedTester tester ) { if ( speed_manager != null ){ speed_manager.setSpeedTester( tester ); } } }); global_manager.addListener( new GlobalManagerAdapter() { public void seedingStatusChanged( boolean seeding_only_mode, boolean b ) { checkConfig(); } }); COConfigurationManager.addAndFireParameterListeners( new String[]{ TransferSpeedValidator.AUTO_UPLOAD_ENABLED_CONFIGKEY, TransferSpeedValidator.AUTO_UPLOAD_SEEDING_ENABLED_CONFIGKEY }, new ParameterListener() { public void parameterChanged( String parameterName ) { checkConfig(); } }); } } } protected void checkConfig() { if ( speed_manager != null ){ speed_manager.setEnabled( TransferSpeedValidator.isAutoSpeedActive(global_manager) ); } } }); } }catch( Throwable e ){ } if ( COConfigurationManager.getBooleanParameter( "Resume Downloads On Start" )){ global_manager.resumeDownloads(); } VersionCheckClient.getSingleton().initialise(); instance_manager.initialize(); NetworkManager.getSingleton().initialize(this); SpeedLimitHandler.getSingleton( this ); Runtime.getRuntime().addShutdownHook( new AEThread("Shutdown Hook") { public void runSupport() { Logger.log(new LogEvent(LOGID, "Shutdown hook triggered" )); AzureusCoreImpl.this.stop(); } }); DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Core", new Runnable() { public void run() { new AEThread2( "core:delayTask", true ) { public void run() { AEDiagnostics.checkDumpsAndNatives(); COConfigurationManager.setParameter( "diags.enable.pending.writes", true ); AEDiagnostics.flushPendingLogs(); NetworkAdmin na = NetworkAdmin.getSingleton(); na.runInitialChecks(AzureusCoreImpl.this); na.addPropertyChangeListener( new NetworkAdminPropertyChangeListener() { private String last_as; public void propertyChanged( String property ) { NetworkAdmin na = NetworkAdmin.getSingleton(); if ( property.equals( NetworkAdmin.PR_NETWORK_INTERFACES )){ boolean found_usable = false; NetworkAdminNetworkInterface[] intf = na.getInterfaces(); for (int i=0;i<intf.length;i++){ NetworkAdminNetworkInterfaceAddress[] addresses = intf[i].getAddresses(); for (int j=0;j<addresses.length;j++){ if ( !addresses[j].isLoopback()){ found_usable = true; } } } // ignore event if nothing usable if ( !found_usable ){ return; } Logger.log( new LogEvent(LOGID, "Network interfaces have changed (new=" + na.getNetworkInterfacesAsString() + ")")); announceAll( false ); }else if ( property.equals( NetworkAdmin.PR_AS )){ String as = na.getCurrentASN().getAS(); if ( last_as == null ){ last_as = as; }else if ( !as.equals( last_as )){ Logger.log( new LogEvent(LOGID, "AS has changed (new=" + as + ")" )); last_as = as; announceAll( false ); } } } }); setupSleepAndCloseActions(); } }.start(); } }); delayed_task.queue(); if (stopped) { System.err.println("Core stopped while starting"); return; } PairingManagerFactory.getSingleton(); AzureusCoreRunningListener[] runningListeners; mon_coreRunningListeners.enter(); try { if (coreRunningListeners == null) { runningListeners = new AzureusCoreRunningListener[0]; } else { runningListeners = coreRunningListeners.toArray(new AzureusCoreRunningListener[0]); coreRunningListeners = null; } } finally { mon_coreRunningListeners.exit(); } // Trigger Listeners now that core is started new AEThread2("Plugin Init Complete", false ) { public void run() { try{ PlatformManagerFactory.getPlatformManager().startup( AzureusCoreImpl.this ); }catch( Throwable e ){ Debug.out( "PlatformManager: init failed", e ); } Iterator it = lifecycle_listeners.iterator(); while( it.hasNext()){ try{ AzureusCoreLifecycleListener listener = (AzureusCoreLifecycleListener)it.next(); if ( !listener.requiresPluginInitCompleteBeforeStartedEvent()){ listener.started( AzureusCoreImpl.this ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } pi.initialisationComplete(); it = lifecycle_listeners.iterator(); while( it.hasNext()){ try{ AzureusCoreLifecycleListener listener = (AzureusCoreLifecycleListener)it.next(); if ( listener.requiresPluginInitCompleteBeforeStartedEvent()){ listener.started( AzureusCoreImpl.this ); } }catch( Throwable e ){ Debug.printStackTrace(e); } } } }.start(); // Typicially there are many runningListeners, most with quick execution, and // a few longer ones. Let 3 run at a time, queue the rest. Without // a ThreadPool, the slow ones would delay the startup processes that run // after this start() method ThreadPool tp = new ThreadPool("Trigger AzureusCoreRunning Listeners", 3); for (final AzureusCoreRunningListener l : runningListeners) { try { tp.run(new AERunnable() { public void runSupport() { l.azureusCoreRunning(AzureusCoreImpl.this); } }); } catch (Throwable t) { Debug.out(t); } } // Debug.out("Core Start Complete"); } public boolean isInitThread() { return( AEThread2.isOurThread( Thread.currentThread())); } public boolean isStarted() { mon_coreRunningListeners.enter(); try { return( started && coreRunningListeners == null ); } finally { mon_coreRunningListeners.exit(); } } public void triggerLifeCycleComponentCreated( AzureusCoreComponent component ) { Iterator it = lifecycle_listeners.iterator(); while( it.hasNext()){ try{ ((AzureusCoreLifecycleListener)it.next()).componentCreated(this, component); }catch( Throwable e ){ Debug.printStackTrace(e); } } } private void runNonDaemon( final Runnable r ) throws AzureusCoreException { if ( !Thread.currentThread().isDaemon()){ r.run(); }else{ final AESemaphore sem = new AESemaphore( "AzureusCore:runNonDaemon" ); final Throwable[] error = {null}; new AEThread2( "AzureusCore:runNonDaemon", false ) { public void run() { try{ r.run(); }catch( Throwable e ){ error[0] = e; }finally{ sem.release(); } } }.start(); sem.reserve(); if ( error[0] != null ){ if ( error[0] instanceof AzureusCoreException ){ throw((AzureusCoreException)error[0]); }else{ throw( new AzureusCoreException( "Operation failed", error[0] )); } } } } public void stop() throws AzureusCoreException { runNonDaemon(new AERunnable() { public void runSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Stop operation starts")); stopSupport(true); } }); } private void stopSupport( boolean apply_updates ) throws AzureusCoreException { AEDiagnostics.flushPendingLogs(); boolean wait_and_return = false; try{ this_mon.enter(); if ( stopped ){ // ensure config is saved as there may be pending changes to persist and we've got here // via a shutdown hook COConfigurationManager.save(); wait_and_return = true; }else{ stopped = true; if ( !started ){ Logger.log(new LogEvent(LOGID, "Core not started")); // might have been marked dirty due to core being created to allow functions to be used but never started... if ( AEDiagnostics.isDirty()){ AEDiagnostics.markClean(); } stopping_sem.releaseForever(); return; } } }finally{ this_mon.exit(); } if ( wait_and_return ){ Logger.log(new LogEvent(LOGID, "Waiting for stop to complete")); stopping_sem.reserve(); return; } SimpleTimer.addEvent( "ShutFail", SystemTime.getOffsetTime( 30*1000 ), new TimerEventPerformer() { boolean die_die_die; public void perform( TimerEvent event ) { AEDiagnostics.dumpThreads(); if ( die_die_die ){ Debug.out( "Shutdown blocked, force exiting" ); SESecurityManager.exitVM(0); } die_die_die = true; SimpleTimer.addEvent( "ShutFail", SystemTime.getOffsetTime( 30*1000 ), this ); } }); List sync_listeners = new ArrayList(); List async_listeners = new ArrayList(); Iterator it = lifecycle_listeners.iterator(); while( it.hasNext()){ AzureusCoreLifecycleListener l = (AzureusCoreLifecycleListener)it.next(); if ( l.syncInvokeRequired()){ sync_listeners.add( l ); }else{ async_listeners.add( l ); } } try{ if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Invoking synchronous 'stopping' listeners")); for (int i=0;i<sync_listeners.size();i++){ try{ ((AzureusCoreLifecycleListener)sync_listeners.get(i)).stopping( this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Invoking asynchronous 'stopping' listeners")); // in case something hangs during listener notification (e.g. version check server is down // and the instance manager tries to obtain external address) we limit overall dispatch // time to 10 seconds ListenerManager.dispatchWithTimeout( async_listeners, new ListenerManagerDispatcher() { public void dispatch( Object listener, int type, Object value ) { ((AzureusCoreLifecycleListener)listener).stopping( AzureusCoreImpl.this ); } }, 10*1000 ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Stopping global manager")); if (global_manager != null) { global_manager.stopGlobalManager(); } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Invoking synchronous 'stopped' listeners")); for (int i=0;i<sync_listeners.size();i++){ try{ ((AzureusCoreLifecycleListener)sync_listeners.get(i)).stopped( this ); }catch( Throwable e ){ Debug.printStackTrace(e); } } if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Invoking asynchronous 'stopped' listeners")); ListenerManager.dispatchWithTimeout( async_listeners, new ListenerManagerDispatcher() { public void dispatch( Object listener, int type, Object value ) { ((AzureusCoreLifecycleListener)listener).stopped( AzureusCoreImpl.this ); } }, 10*1000 ); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Waiting for quiescence")); NonDaemonTaskRunner.waitUntilIdle(); // shut down diags - this marks the shutdown as tidy and saves the config AEDiagnostics.markClean(); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Stop operation completes")); // if any installers exist then we need to closedown via the updater if ( apply_updates && getPluginManager().getDefaultPluginInterface().getUpdateManager().getInstallers().length > 0 ){ AzureusRestarterFactory.create( this ).restart( true ); } try { Class c = Class.forName( "sun.awt.AWTAutoShutdown" ); if (c != null) { c.getMethod( "notifyToolkitThreadFree", new Class[]{} ).invoke( null, new Object[]{} ); } } catch (Throwable t) { } if ( ca_shutdown_computer_after_stop ){ if ( apply_updates ){ // best we can do here is wait a while for updates to be applied try{ Thread.sleep( 10*1000 ); }catch( Throwable e ){ } } try{ PlatformManagerFactory.getPlatformManager().shutdown( PlatformManager.SD_SHUTDOWN ); }catch( Throwable e ){ Debug.out( "PlatformManager: shutdown failed", e ); } } try{ ThreadGroup tg = Thread.currentThread().getThreadGroup(); while( tg.getParent() != null ){ tg = tg.getParent(); } Thread[] threads = new Thread[tg.activeCount()+1024]; tg.enumerate( threads, true ); boolean bad_found = false; for (int i=0;i<threads.length;i++){ Thread t = threads[i]; if ( t != null && t.isAlive() && t != Thread.currentThread() && !t.isDaemon() && !AEThread2.isOurThread( t )){ bad_found = true; break; } } if ( bad_found ){ new AEThread2( "VMKiller", true ) { public void run() { try{ Thread.sleep(10*1000); ThreadGroup tg = Thread.currentThread().getThreadGroup(); Thread[] threads = new Thread[tg.activeCount()+1024]; tg.enumerate( threads, true ); String bad_found = ""; for (int i=0;i<threads.length;i++){ Thread t = threads[i]; if ( t != null && t.isAlive() && !t.isDaemon() && !AEThread2.isOurThread( t )){ String details = t.getName(); StackTraceElement[] trace = t.getStackTrace(); if ( trace.length > 0 ){ details += "["; for ( int j=0;j<trace.length;j++ ){ details += (j==0?"":",") + trace[j]; } details += "]"; } bad_found += (bad_found.length()==0?"":", ") + details; } } Debug.out( "Non-daemon thread(s) found: '" + bad_found + "' - force closing VM" ); SESecurityManager.exitVM(0); }catch( Throwable e ){ } } }.start(); } }catch( Throwable e ){ } }finally{ stopping_sem.releaseForever(); } } public void requestStop() throws AzureusCoreException { if (stopped) return; runNonDaemon(new AERunnable() { public void runSupport() { Iterator it = lifecycle_listeners.iterator(); while( it.hasNext()){ if (!((AzureusCoreLifecycleListener)it.next()) .stopRequested(AzureusCoreImpl.this)) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Request to stop the core has been denied")); return; } } stop(); } }); } public void restart() throws AzureusCoreException { runNonDaemon(new AERunnable() { public void runSupport() { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Restart operation starts")); checkRestartSupported(); restarting = true; stopSupport(false); if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, "Restart operation: stop complete," + "restart initiated")); AzureusRestarterFactory.create(AzureusCoreImpl.this).restart(false); } }); } public void requestRestart() throws AzureusCoreException { runNonDaemon(new AERunnable() { public void runSupport() { checkRestartSupported(); Iterator it = lifecycle_listeners.iterator(); while( it.hasNext()){ AzureusCoreLifecycleListener l = (AzureusCoreLifecycleListener)it.next(); if (!l.restartRequested(AzureusCoreImpl.this)) { if (Logger.isEnabled()) Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Request to restart the core" + " has been denied")); return; } } restart(); } }); } public boolean isRestarting() { return( restarting ); } public void checkRestartSupported() throws AzureusCoreException { if ( getPluginManager().getPluginInterfaceByClass( "org.gudy.azureus2.update.UpdaterPatcher") == null ){ Logger.log(new LogAlert(LogAlert.REPEATABLE, LogAlert.AT_ERROR, "Can't restart without the 'azupdater' plugin installed")); throw( new AzureusCoreException("Can't restart without the 'azupdater' plugin installed")); } } public void saveState() { GlobalManager gm = global_manager; if ( gm != null ){ gm.saveState(); } COConfigurationManager.save(); } public GlobalManager getGlobalManager() throws AzureusCoreException { if ( global_manager == null ){ throw( new AzureusCoreException( "Core not running" )); } return( global_manager ); } public TRHost getTrackerHost() throws AzureusCoreException { return( TRHostFactory.getSingleton()); } public PluginManagerDefaults getPluginManagerDefaults() throws AzureusCoreException { return( PluginManager.getDefaults()); } public PluginManager getPluginManager() throws AzureusCoreException { // don't test for running here, the restart process calls this after terminating the core... return( PluginInitializer.getDefaultInterface().getPluginManager()); } public IpFilterManager getIpFilterManager() throws AzureusCoreException { return( IpFilterManagerFactory.getSingleton()); } public AZInstanceManager getInstanceManager() { return( instance_manager ); } public SpeedManager getSpeedManager() { return( speed_manager ); } public CryptoManager getCryptoManager() { return( crypto_manager ); } public NATTraverser getNATTraverser() { return( nat_traverser ); } private void setupSleepAndCloseActions() { if ( PlatformManagerFactory.getPlatformManager().hasCapability( PlatformManagerCapabilities.PreventComputerSleep )){ COConfigurationManager.addAndFireParameterListeners( new String[]{ "Prevent Sleep Downloading", "Prevent Sleep FP Seeding", }, new ParameterListener() { private TimerEventPeriodic timer_event; public void parameterChanged( String parameterName ) { synchronized( this ){ boolean dl = COConfigurationManager.getBooleanParameter( "Prevent Sleep Downloading" ); boolean se = COConfigurationManager.getBooleanParameter( "Prevent Sleep FP Seeding" ); boolean active = dl || se; try{ setPreventComputerSleep( PlatformManagerFactory.getPlatformManager(), active, "config change" ); }catch( Throwable e ){ Debug.out( e ); } if ( !active ){ if ( timer_event != null ){ timer_event.cancel(); timer_event = null; } }else{ if ( timer_event == null ){ timer_event = SimpleTimer.addPeriodicEvent( "core:sleepAct", 2*60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { if ( !stopped ){ checkSleepActions(); } } }); } } } } }); } COConfigurationManager.addAndFireParameterListeners( new String[]{ "On Downloading Complete Do", "On Seeding Complete Do" }, new ParameterListener() { private TimerEventPeriodic timer_event; public void parameterChanged( String parameterName ) { String dl_act = COConfigurationManager.getStringParameter( "On Downloading Complete Do" ); String se_act = COConfigurationManager.getStringParameter( "On Seeding Complete Do" ); synchronized( this ){ boolean dl_nothing = dl_act.equals( "Nothing" ); boolean se_nothing = se_act.equals( "Nothing" ); if ( dl_nothing ){ ca_last_time_downloading = -1; } if ( se_nothing ){ ca_last_time_seeding = -1; } if ( dl_nothing && se_nothing ){ if ( timer_event != null ){ timer_event.cancel(); timer_event = null; } }else{ if ( timer_event == null ){ timer_event = SimpleTimer.addPeriodicEvent( "core:closeAct", 30*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { if ( !stopped ){ checkCloseActions(); } } }); } checkCloseActions(); } } } }); } protected void checkSleepActions() { boolean ps_downloading = COConfigurationManager.getBooleanParameter( "Prevent Sleep Downloading" ); boolean ps_fp_seed = COConfigurationManager.getBooleanParameter( "Prevent Sleep FP Seeding" ); String declining_subsystems = ""; for ( PowerManagementListener l: power_listeners ){ try{ if ( !l.requestPowerStateChange( PowerManagementListener.ST_SLEEP, null )){ declining_subsystems += (declining_subsystems.length()==0?"":",") + l.getPowerName(); } }catch( Throwable e ){ Debug.out( e ); } } if ( declining_subsystems.length() == 0 && !( ps_downloading || ps_fp_seed )){ return; } PlatformManager platform = PlatformManagerFactory.getPlatformManager(); boolean prevent_sleep = false; String prevent_reason = null; if ( declining_subsystems.length() > 0 ){ prevent_sleep = true; prevent_reason = "subsystems declined sleep: " + declining_subsystems; }else{ List<DownloadManager> managers = getGlobalManager().getDownloadManagers(); for ( DownloadManager manager: managers ){ int state = manager.getState(); if ( state == DownloadManager.STATE_FINISHING || manager.getDownloadState().getFlag( DownloadManagerState.FLAG_METADATA_DOWNLOAD )){ if ( ps_downloading ){ prevent_sleep = true; prevent_reason = "active downloads"; break; } }else{ if ( state == DownloadManager.STATE_DOWNLOADING ){ PEPeerManager pm = manager.getPeerManager(); if ( pm != null ){ if ( pm.hasDownloadablePiece()){ if ( ps_downloading ){ prevent_sleep = true; prevent_reason = "active downloads"; break; } }else{ // its effectively seeding, change so logic about recheck obeyed below state = DownloadManager.STATE_SEEDING; } } } if ( state == DownloadManager.STATE_SEEDING && ps_fp_seed ){ DiskManager disk_manager = manager.getDiskManager(); if ( disk_manager != null && disk_manager.getCompleteRecheckStatus() != -1 ){ // wait until recheck is complete before we mark as downloading-complete if ( ps_downloading ){ prevent_sleep = true; prevent_reason = "active downloads"; break; } }else{ try{ DefaultRankCalculator calc = StartStopRulesDefaultPlugin.getRankCalculator( PluginCoreUtils.wrap( manager )); if ( calc.getCachedIsFP()){ prevent_sleep = true; prevent_reason = "first-priority seeding"; break; } }catch( Throwable e ){ } } } } } } if ( prevent_sleep != platform.getPreventComputerSleep()){ if ( prevent_sleep ){ prevent_sleep_remove_trigger = false; }else{ if ( !prevent_sleep_remove_trigger ){ prevent_sleep_remove_trigger = true; return; } } if ( prevent_reason == null ){ if ( ps_downloading && ps_fp_seed ){ prevent_reason = "no active downloads or first-priority seeding"; }else if ( ps_downloading ){ prevent_reason = "no active downloads"; }else{ prevent_reason = "no active first-priority seeding"; } } setPreventComputerSleep( platform, prevent_sleep, prevent_reason ); } } private void setPreventComputerSleep( PlatformManager platform, boolean prevent_sleep, String prevent_reason ) { for ( PowerManagementListener l: power_listeners ){ try{ l.informPowerStateChange( PowerManagementListener.ST_SLEEP, new Object[]{ prevent_sleep, prevent_reason }); }catch( Throwable e ){ Debug.out( e ); } } Logger.log( new LogEvent(LOGID, "Computer sleep prevented state changed to '" + prevent_sleep + "' due to " + prevent_reason )); try{ platform.setPreventComputerSleep( prevent_sleep ); }catch( Throwable e ){ Debug.out( e ); } } protected void checkCloseActions() { List<DownloadManager> managers = getGlobalManager().getDownloadManagers(); boolean is_downloading = false; boolean is_seeding = false; for ( DownloadManager manager: managers ){ if ( manager.isPaused()){ // if anything's paused we don't want to trigger any actions as something transient (e.g. speed test) is going on return; } if ( manager.getDownloadState().getFlag( DownloadManagerState.FLAG_METADATA_DOWNLOAD )){ return; } int state = manager.getState(); if ( state == DownloadManager.STATE_FINISHING ){ is_downloading = true; }else{ if ( state == DownloadManager.STATE_DOWNLOADING ){ PEPeerManager pm = manager.getPeerManager(); if ( pm != null ){ if ( pm.hasDownloadablePiece()){ is_downloading = true; }else{ // its effectively seeding, change so logic about recheck obeyed below state = DownloadManager.STATE_SEEDING; } } } if ( state == DownloadManager.STATE_SEEDING ){ DiskManager disk_manager = manager.getDiskManager(); if ( disk_manager != null && disk_manager.getCompleteRecheckStatus() != -1 ){ // wait until recheck is complete before we mark as downloading-complete is_downloading = true; }else{ is_seeding = true; } } } } long now = SystemTime.getMonotonousTime(); if ( is_downloading ){ ca_last_time_downloading = now; ca_last_time_seeding = -1; }else if ( is_seeding ){ ca_last_time_seeding = now; } String dl_act = COConfigurationManager.getStringParameter( "On Downloading Complete Do" ); if ( !dl_act.equals( "Nothing" )){ if ( ca_last_time_downloading >= 0 && !is_downloading && now - ca_last_time_downloading >= 30*1000 ){ executeCloseAction( true, true, dl_act, null ); } } String se_act = COConfigurationManager.getStringParameter( "On Seeding Complete Do" ); if ( !se_act.equals( "Nothing" )){ if ( ca_last_time_seeding >= 0 && !is_seeding && now - ca_last_time_seeding >= 30*1000 ){ executeCloseAction( true, false, se_act, null ); } } } public void executeCloseAction( String action, String reason ) { executeCloseAction( false, false, action, reason ); } private void executeCloseAction( final boolean obey_reset, final boolean download_trigger, final String action, final String reason ) { // prevent retriggering on resume from standby ca_last_time_downloading = -1; ca_last_time_seeding = -1; boolean reset = obey_reset && COConfigurationManager.getBooleanParameter( "Stop Triggers Auto Reset" ); if ( reset ){ if ( download_trigger ){ COConfigurationManager.setParameter( "On Downloading Complete Do", "Nothing" ); }else{ COConfigurationManager.setParameter( "On Seeding Complete Do", "Nothing" ); } } String type_str = reason==null?MessageText.getString( "core.shutdown." + (download_trigger?"dl":"se")):reason; String action_str = MessageText.getString( "ConfigView.label.stop." + action ); String message = MessageText.getString( "core.shutdown.alert", new String[]{ action_str, type_str, }); UIFunctions ui_functions = UIFunctionsManager.getUIFunctions(); if ( ui_functions != null ){ ui_functions.forceNotify( UIFunctions.STATUSICON_NONE, null, message, null, new Object[0], -1 ); } Logger.log( new LogAlert( LogAlert.UNREPEATABLE, LogEvent.LT_INFORMATION, message )); new DelayedEvent( "CoreShutdown", 10*1000, new AERunnable() { public void runSupport() { Logger.log( new LogEvent(LOGID, "Executing close action '" + action + "' due to " + (download_trigger?"downloading":"seeding") + " completion" )); // quit vuze -> quit // shutdown computer -> quit vuze + shutdown // sleep/hibernate = announceAll and then sleep/hibernate with Vuze still running if ( action.equals( CA_QUIT_VUZE )){ requestStop(); }else if ( action.equals( CA_SLEEP ) || action.equals( CA_HIBERNATE )){ announceAll( true ); try{ PlatformManagerFactory.getPlatformManager().shutdown( action.equals( CA_SLEEP )?PlatformManager.SD_SLEEP:PlatformManager.SD_HIBERNATE ); }catch( Throwable e ){ Debug.out( "PlatformManager: shutdown failed", e ); } }else if ( action.equals( CA_SHUTDOWN )){ ca_shutdown_computer_after_stop = true; requestStop(); }else if ( action.startsWith( "RunScript" )){ String script; if ( download_trigger ){ script = COConfigurationManager.getStringParameter( "On Downloading Complete Script", "" ); }else{ script = COConfigurationManager.getStringParameter( "On Seeding Complete Script", "" ); } File script_file = new File( script.trim()); if ( !script_file.isFile()){ Logger.log( new LogEvent(LOGID, "Script failed to run - '" + script_file + "' isn't a valid script file" )); Debug.out( "Invalid script: " + script_file ); }else{ try{ boolean close_vuze = action.equals( "RunScriptAndClose" ); if ( !close_vuze ){ // assume script might implement a sleep announceAll( true ); } getPluginManager().getDefaultPluginInterface().getUtilities().createProcess( script_file.getAbsolutePath()); if ( close_vuze ){ requestStop(); } }catch( Throwable e ){ Debug.out( e ); } } }else{ Debug.out( "Unknown close action '" + action + "'" ); } } }); } public AzureusCoreOperation createOperation( final int type ) { AzureusCoreOperation op = new AzureusCoreOperation() { public int getOperationType() { return( type ); } public AzureusCoreOperationTask getTask() { return null; } public void reportCurrentTask( String task ) { AzureusCoreImpl.this.reportCurrentTask( this, task ); } public void reportPercent( int percent ) { AzureusCoreImpl.this.reportPercent( this, percent ); } }; for (int i=0;i<operation_listeners.size();i++){ try{ ((AzureusCoreOperationListener)operation_listeners.get(i)).operationCreated( op ); }catch( Throwable e ){ Debug.printStackTrace(e); } } return( op ); } public void createOperation( final int type, AzureusCoreOperationTask task ) { final AzureusCoreOperationTask[] f_task = { task }; AzureusCoreOperation op = new AzureusCoreOperation() { public int getOperationType() { return( type ); } public AzureusCoreOperationTask getTask() { return( f_task[0] ); } public void reportCurrentTask( String task ) { AzureusCoreImpl.this.reportCurrentTask( this, task ); } public void reportPercent( int percent ) { AzureusCoreImpl.this.reportPercent( this, percent ); } }; for (int i=0;i<operation_listeners.size();i++){ // don't catch exceptions here as we want errors from task execution to propagate // back to the invoker if (((AzureusCoreOperationListener)operation_listeners.get(i)).operationCreated( op )){ f_task[0] = null; } } // nobody volunteeered to run it for us, we'd better do it if ( f_task[0] != null ){ task.run( op ); } } protected void reportCurrentTask( AzureusCoreOperation op, String currentTask ) { if ( op.getOperationType() == AzureusCoreOperation.OP_INITIALISATION ){ PluginInitializer.fireEvent( PluginEvent.PEV_INITIALISATION_PROGRESS_TASK, currentTask ); } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((AzureusCoreListener)it.next()).reportCurrentTask( op, currentTask ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } protected void reportPercent( AzureusCoreOperation op, int percent ) { if ( op.getOperationType() == AzureusCoreOperation.OP_INITIALISATION ){ PluginInitializer.fireEvent( PluginEvent.PEV_INITIALISATION_PROGRESS_PERCENT, new Integer( percent )); } Iterator it = listeners.iterator(); while( it.hasNext()){ try{ ((AzureusCoreListener)it.next()).reportPercent( op, percent ); }catch( Throwable e ){ Debug.printStackTrace(e); } } } public void addLifecycleListener( AzureusCoreLifecycleListener l ) { lifecycle_listeners.add(l); } public void removeLifecycleListener( AzureusCoreLifecycleListener l ) { lifecycle_listeners.remove(l); } public void addListener( AzureusCoreListener l ) { listeners.add( l ); } public void removeListener( AzureusCoreListener l ) { listeners.remove( l ); } public void addOperationListener( AzureusCoreOperationListener l ) { operation_listeners.add(l); } public void removeOperationListener( AzureusCoreOperationListener l ) { operation_listeners.remove(l); } public static void addCoreRunningListener(AzureusCoreRunningListener l) { mon_coreRunningListeners.enter(); try { if (AzureusCoreImpl.coreRunningListeners != null) { coreRunningListeners.add(l); return; } } finally { mon_coreRunningListeners.exit(); } l.azureusCoreRunning(AzureusCoreImpl.getSingleton()); } public void addPowerManagementListener( PowerManagementListener listener ) { power_listeners.add( listener ); } public void removePowerManagementListener( PowerManagementListener listener ) { power_listeners.remove( listener ); } }