/* * File : PluginInterfaceImpl.java * Created : 12 nov. 2003 * By : Olivier * * Azureus - a Java Bittorrent client * * 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. * * 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 ( see the LICENSE file ). * * 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 */ package org.gudy.azureus2.pluginsimpl.local; import java.util.*; import java.io.File; import java.net.URL; import org.gudy.azureus2.platform.PlatformManagerFactory; import org.gudy.azureus2.plugins.*; import org.gudy.azureus2.plugins.dht.mainline.*; import org.gudy.azureus2.plugins.logging.Logger; import org.gudy.azureus2.plugins.messaging.MessageManager; import org.gudy.azureus2.plugins.network.ConnectionManager; import org.gudy.azureus2.pluginsimpl.local.dht.mainline.*; import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl; import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl; import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl; import org.gudy.azureus2.pluginsimpl.local.installer.PluginInstallerImpl; import org.gudy.azureus2.pluginsimpl.local.ipc.IPCInterfaceImpl; import org.gudy.azureus2.pluginsimpl.local.ipfilter.IPFilterImpl; import org.gudy.azureus2.pluginsimpl.local.logging.LoggerImpl; import org.gudy.azureus2.pluginsimpl.local.messaging.MessageManagerImpl; import org.gudy.azureus2.pluginsimpl.local.network.ConnectionManagerImpl; import org.gudy.azureus2.pluginsimpl.local.peers.protocol.*; import org.gudy.azureus2.pluginsimpl.local.sharing.ShareManagerImpl; import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl; import org.gudy.azureus2.pluginsimpl.local.tracker.*; import org.gudy.azureus2.pluginsimpl.local.ui.*; import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository; import org.gudy.azureus2.pluginsimpl.local.ui.config.ParameterRepository; import org.gudy.azureus2.pluginsimpl.local.ui.config.PluginConfigUIFactoryImpl; import org.gudy.azureus2.pluginsimpl.local.utils.*; import org.gudy.azureus2.pluginsimpl.local.update.*; import org.gudy.azureus2.plugins.ipc.IPCInterface; import org.gudy.azureus2.plugins.ipfilter.IPFilter; import org.gudy.azureus2.plugins.tracker.Tracker; import org.gudy.azureus2.plugins.ui.config.Parameter; import org.gudy.azureus2.plugins.ui.config.PluginConfigUIFactory; import org.gudy.azureus2.plugins.ui.tables.peers.PluginPeerItemFactory; import org.gudy.azureus2.plugins.ui.tables.mytorrents.PluginMyTorrentsItemFactory; import org.gudy.azureus2.plugins.peers.protocol.*; import org.gudy.azureus2.plugins.platform.PlatformManager; import org.gudy.azureus2.plugins.sharing.*; import org.gudy.azureus2.plugins.clientid.ClientIDManager; import org.gudy.azureus2.plugins.ddb.DistributedDatabase; import org.gudy.azureus2.plugins.download.*; import org.gudy.azureus2.plugins.torrent.*; import org.gudy.azureus2.plugins.ui.*; import org.gudy.azureus2.plugins.ui.config.ConfigSection; import org.gudy.azureus2.plugins.utils.*; import org.gudy.azureus2.plugins.update.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.core3.logging.*; /** * @author Olivier * */ public class PluginInterfaceImpl implements PluginInterface { private static final LogIDs LOGID = org.gudy.azureus2.core3.logging.LogIDs.PLUGIN; private Plugin plugin; private PluginInitializer initialiser; private Object initialiser_key; private ClassLoader class_loader; private List listeners = new ArrayList(); private List event_listeners = new ArrayList(); private String key; private String pluginConfigKey; private Properties props; private String pluginDir; private PluginConfig config; private String plugin_id; private String plugin_version; private boolean operational; private boolean disabled; private Logger logger; private IPCInterfaceImpl ipc_interface; private List children = new ArrayList(); private List configSections = new ArrayList(); public PluginInterfaceImpl( Plugin _plugin, PluginInitializer _initialiser, Object _initialiser_key, ClassLoader _class_loader, String _key, Properties _props, String _pluginDir, String _plugin_id, String _plugin_version ) { plugin = _plugin; initialiser = _initialiser; initialiser_key = _initialiser_key; class_loader = _class_loader; key = _key; pluginConfigKey = "Plugin." + _key; props = new propertyWrapper(_props ); pluginDir = _pluginDir; config = new PluginConfigImpl(this,pluginConfigKey); plugin_id = _plugin_id; plugin_version = _plugin_version; ipc_interface = new IPCInterfaceImpl( initialiser, plugin ); } public Plugin getPlugin() { return( plugin ); } protected void setOperational( boolean b ) { operational = b; } public boolean isOperational() { return( operational ); } public Object getInitializerKey() { return( initialiser_key ); } public PluginManager getPluginManager() { return( initialiser.getPluginManager()); } public String getAzureusName() { return( Constants.AZUREUS_NAME ); } public String getAzureusVersion() { return( Constants.AZUREUS_VERSION ); } /** * @deprecated */ public void addView(PluginView view) { getUIManager().getSWTManager().addView(view); } public void addConfigSection(ConfigSection section) { ConfigSectionRepository.getInstance().addConfigSection(section); configSections.add(section); } public void removeConfigSection(ConfigSection section) { ConfigSectionRepository.getInstance().removeConfigSection(section); configSections.remove(section); } public ConfigSection[] getConfigSections() { return (ConfigSection[]) configSections.toArray(new ConfigSection[0]); } /** * @deprecated */ public void openTorrentFile(String fileName) { try{ getDownloadManager().addDownload( new File(fileName)); }catch( DownloadException e ){ throw( new RuntimeException(e)); } } /** * @deprecated */ public void openTorrentURL(String url) { try{ getDownloadManager().addDownload( new URL( url )); }catch( Throwable e ){ throw( new RuntimeException(e)); } } public void setPluginName( String name ) { props.put( "plugin.name", name ); } public String getPluginName() { String name = null; if ( props != null ){ name = (String)props.get( "plugin.name"); } if ( name == null ){ try{ name = new File(pluginDir).getName(); }catch( Throwable e ){ } } if ( name == null || name.length() == 0 ){ name = plugin.getClass().getName(); } return( name ); } public void setPluginVersion( String version ) { props.put( "plugin.version", version ); } public String getPluginVersion() { String version = (String)props.get("plugin.version"); if ( version == null ){ version = plugin_version; } return( version ); } public String getPluginID() { String id = (String)props.get("plugin.id"); if ( id == null ){ id = plugin_id; } return( id==null?"<none>":id ); } public boolean isMandatory() { String mand = getPluginProperties().getProperty( "plugin.mandatory"); return( mand != null && mand.trim().toLowerCase().equals("true")); } public boolean isBuiltIn() { String dir = getPluginDirectoryName(); if ( dir == null ){ return( PluginInitializer.isLoadingBuiltin()); } return( dir.length() == 0 || getPluginID().equals( "azupdater" )); } public void setDisabled( boolean _disabled ) { disabled = _disabled; } public boolean isDisabled() { return( disabled ); } public Properties getPluginProperties() { return(props); } public String getPluginDirectoryName() { return pluginDir; } public void setPluginDirectoryName( String name ) { initialiser_key = new File(name); pluginDir = name; } public void addConfigUIParameters(Parameter[] parameters, String displayName) { ParameterRepository.getInstance().addPlugin(parameters, displayName); } public PluginConfig getPluginconfig() { return config; } public PluginConfigUIFactory getPluginConfigUIFactory() { return new PluginConfigUIFactoryImpl(config,pluginConfigKey); } public String getPluginConfigKey() { return( pluginConfigKey ); } /** @deprecated Use getUIManager().getTableManager().createColumn */ public void addColumnToPeersTable(String columnName, PluginPeerItemFactory item) { Debug.out( "Method PluginInterface::addColumnToPeersTable deprecated. Use getUIManager().getTableManager().createColumn" ); } /** @deprecated Use getUIManager().getTableManager().createColumn */ public void addColumnToMyTorrentsTable(String columnName, PluginMyTorrentsItemFactory item) { Debug.out( "Method PluginInterface::addColumnToMyTorrentsTable deprecated. Use getUIManager().getTableManager().createColumn" ); } public Tracker getTracker() { return( TrackerImpl.getSingleton()); } public ShareManager getShareManager() throws ShareException { return( ShareManagerImpl.getSingleton()); } public DownloadManager getDownloadManager() { return( DownloadManagerImpl.getSingleton(initialiser.getAzureusCore())); } public MainlineDHTManager getMainlineDHTManager() { return new MainlineDHTManagerImpl(initialiser.getAzureusCore()); } public TorrentManager getTorrentManager() { return( TorrentManagerImpl.getSingleton().specialise( this )); } public Logger getLogger() { if ( logger == null ){ logger = new LoggerImpl( this ); } return( logger ); } public IPFilter getIPFilter() { return( new IPFilterImpl()); } public Utilities getUtilities() { return( new UtilitiesImpl( initialiser.getAzureusCore(), this )); } public ShortCuts getShortCuts() { return( new ShortCutsImpl(this)); } public UIManager getUIManager() { return( new UIManagerImpl( this )); } public UpdateManager getUpdateManager() { return( UpdateManagerImpl.getSingleton( initialiser.getAzureusCore())); } public PeerProtocolManager getPeerProtocolManager() { return( PeerProtocolManagerImpl.getSingleton()); } public boolean isUnloadable() { String dir = getPluginDirectoryName(); // mechanism to override unloadability boolean disable_unload = getPluginProperties().getProperty( "plugin.unload.disabled", "" ).equalsIgnoreCase( "true" ); if ( disable_unload ){ return( false ); } // if not dir based then just test this one if ( dir == null || dir.length() == 0 ){ return(getPlugin() instanceof UnloadablePlugin ); } List pis = PluginInitializer.getPluginInterfaces(); for (int i=0;i<pis.size();i++){ PluginInterface pi = (PluginInterface)pis.get(i); String other_dir = pi.getPluginDirectoryName(); if ( other_dir == null || other_dir.length() == 0 ){ continue; } if ( dir.equals( other_dir )){ if ( !(pi.getPlugin() instanceof UnloadablePlugin )){ return( false ); } } } for (int i=0;i<children.size();i++){ if ( !((PluginInterface)children.get(i)).isUnloadable()){ return( false ); } } return( true ); } public void unload() throws PluginException { if ( !isUnloadable()){ throw( new PluginException( "Plugin isn't unloadable" )); } String dir = getPluginDirectoryName(); // if not dir based then just test this one if ( dir == null || dir.length() == 0 ){ ((UnloadablePlugin)getPlugin()).unload(); initialiser.unloadPlugin( this ); }else{ // we must copy the list here as when we unload interfaces they will be // removed from the original list List pis = new ArrayList(PluginInitializer.getPluginInterfaces()); for (int i=0;i<pis.size();i++){ PluginInterfaceImpl pi = (PluginInterfaceImpl)pis.get(i); String other_dir = pi.getPluginDirectoryName(); if ( other_dir == null || other_dir.length() == 0 ){ continue; } if ( dir.equals( other_dir )){ ((UnloadablePlugin)pi.getPlugin()).unload(); initialiser.unloadPlugin( pi ); } } } for (int i=0;i<children.size();i++){ ((PluginInterface)children.get(i)).unload(); } setOperational(false); class_loader = null; } protected void unloadSupport() { ipc_interface.unload(); } public void reload() throws PluginException { // we use the "reload" method to load disabled plugins regardless of whether they are // unloadable. If currently disabled then no unloading to do anyway if ( isUnloadable() || isOperational()){ unload(); } initialiser.reloadPlugin( this ); } public void uninstall() throws PluginException { PluginInstallerImpl.getSingleton(getPluginManager()).uninstall( this ); } public boolean isInitialisationThread() { return( initialiser.isInitialisationThread()); } public ClientIDManager getClientIDManager() { return( ClientIDManagerImpl.getSingleton()); } public ConnectionManager getConnectionManager() { return ConnectionManagerImpl.getSingleton( initialiser.getAzureusCore()); } public MessageManager getMessageManager() { return MessageManagerImpl.getSingleton( initialiser.getAzureusCore() ); } public DistributedDatabase getDistributedDatabase() { return( DDBaseImpl.getSingleton(initialiser.getAzureusCore())); } public PlatformManager getPlatformManager() { return( PlatformManagerFactory.getPlatformManager()); } protected void initialisationComplete() { for (int i=0;i<listeners.size();i++){ try{ ((PluginListener)listeners.get(i)).initializationComplete(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } for (int i=0;i<children.size();i++){ ((PluginInterfaceImpl)children.get(i)).initialisationComplete(); } } protected void closedownInitiated() { for (int i=0;i<listeners.size();i++){ try{ ((PluginListener)listeners.get(i)).closedownInitiated(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } for (int i=0;i<children.size();i++){ ((PluginInterfaceImpl)children.get(i)).closedownInitiated(); } } protected void closedownComplete() { for (int i=0;i<listeners.size();i++){ try{ ((PluginListener)listeners.get(i)).closedownComplete(); }catch( Throwable e ){ Debug.printStackTrace( e ); } } for (int i=0;i<children.size();i++){ ((PluginInterfaceImpl)children.get(i)).closedownComplete(); } } public void firePluginEvent( PluginEvent event ) { for (int i=0;i<event_listeners.size();i++){ try{ ((PluginEventListener)event_listeners.get(i)).handleEvent( event ); }catch( Throwable e ){ Debug.printStackTrace( e ); } } for (int i=0;i<children.size();i++){ ((PluginInterfaceImpl)children.get(i)).firePluginEvent(event); } } public ClassLoader getPluginClassLoader() { return( class_loader ); } public PluginInterface getLocalPluginInterface( Class plugin_class, String id ) throws PluginException { try{ Plugin p = (Plugin)plugin_class.newInstance(); PluginInterfaceImpl pi = new PluginInterfaceImpl( p, initialiser, initialiser_key, class_loader, key + "." + id, props, pluginDir, plugin_id + "." + id, plugin_version ); p.initialize( pi ); children.add( pi ); return( pi ); }catch( Throwable e ){ if ( e instanceof PluginException ){ throw((PluginException)e); } throw( new PluginException( "Local initialisation fails", e )); } } public IPCInterface getIPC() { return( ipc_interface ); } public boolean isShared() { String shared_dir = FileUtil.getApplicationFile( "plugins" ).toString(); String plugin_dir = getPluginDirectoryName(); return( plugin_dir.startsWith( shared_dir )); } public void addListener( PluginListener l ) { listeners.add(l); if ( initialiser.isInitialisationComplete()){ l.initializationComplete(); } } public void removeListener( PluginListener l ) { listeners.remove(l); } public void addEventListener( PluginEventListener l ) { event_listeners.add(l); } public void removeEventListener( PluginEventListener l ) { event_listeners.remove(l); } protected void generateEvidence( IndentWriter writer ) { writer.println( getPluginName()); try{ writer.indent(); writer.println( "id:" + getPluginID() + ",version:" + getPluginVersion()); String user_dir = FileUtil.getUserFile( "plugins" ).toString(); String shared_dir = FileUtil.getApplicationFile( "plugins" ).toString(); String plugin_dir = getPluginDirectoryName(); String type; if ( plugin_dir.startsWith( shared_dir )){ type = "shared"; }else if ( plugin_dir.startsWith( user_dir )){ type = "per-user"; }else{ type = "built-in"; } writer.println( "type:" + type + ",enabled:" + !isDisabled() + ",operational:" + isOperational()); }finally{ writer.exdent(); } } // unfortunately we need to protect ourselves against the plugin itself trying to set // plugin.version and plugin.id as this screws things up if they get it "wrong". // They should be setting these things in the plugin.properties file // currently the RSSImport plugin does this (version 1.1 sets version as 1.0) protected class propertyWrapper extends Properties { protected boolean initialising = true; protected propertyWrapper( Properties _props ) { Iterator it = _props.keySet().iterator(); while( it.hasNext()){ Object key = it.next(); put( key, _props.get(key)); } initialising = false; } public Object setProperty( String str, String val ) { // if its us then we probably know what we're doing :P if ( ! ( plugin.getClass().getName().startsWith( "org.gudy") || plugin.getClass().getName().startsWith( "com.aelitis."))){ if ( str.equalsIgnoreCase( "plugin.id" ) || str.equalsIgnoreCase("plugin.version" )){ if (org.gudy.azureus2.core3.logging.Logger.isEnabled()) org.gudy.azureus2.core3.logging.Logger .log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Plugin '" + getPluginName() + "' tried to set property '" + str + "' - action ignored")); return( null ); } } return( super.setProperty( str, val )); } public Object put( Object key, Object value ) { // if its us then we probably know what we're doing :P if ( ! ( plugin.getClass().getName().startsWith( "org.gudy") || plugin.getClass().getName().startsWith( "com.aelitis."))){ if ((!initialising ) && key instanceof String ){ String k_str = (String)key; if ( k_str.equalsIgnoreCase( "plugin.id" ) || k_str.equalsIgnoreCase("plugin.version" )){ if (org.gudy.azureus2.core3.logging.Logger.isEnabled()) org.gudy.azureus2.core3.logging.Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Plugin '" + getPluginName() + "' tried to set property '" + k_str + "' - action ignored")); return( null ); } } } return( super.put( key, value )); } public Object get( Object key ) { return( super.get(key)); } } }