/* * Created on Nov 20, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. 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; version 2 of the License only. * * 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. */ package com.aelitis.azureus.core.cnetwork.impl; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.AEDiagnostics; import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator; import org.gudy.azureus2.core3.util.AEDiagnosticsLogger; import org.gudy.azureus2.core3.util.AEThread2; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.core3.util.FileUtil; import org.gudy.azureus2.core3.util.IndentWriter; import org.gudy.azureus2.core3.util.SimpleTimer; import org.gudy.azureus2.core3.util.TimerEvent; import org.gudy.azureus2.core3.util.TimerEventPerformer; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkException; import com.aelitis.azureus.core.cnetwork.ContentNetworkListener; import com.aelitis.azureus.core.cnetwork.ContentNetworkManager; import com.aelitis.azureus.core.custom.Customization; import com.aelitis.azureus.core.custom.CustomizationManager; import com.aelitis.azureus.core.custom.CustomizationManagerFactory; import com.aelitis.azureus.core.util.CopyOnWriteList; 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; public class ContentNetworkManagerImpl implements ContentNetworkManager, AEDiagnosticsEvidenceGenerator { private static final boolean LOAD_ALL_NETWORKS = true; private static final String CONFIG_FILE = "cnetworks.config"; private static ContentNetworkManagerImpl singleton = new ContentNetworkManagerImpl(); public static void preInitialise() { 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]; if ( comp.getType() == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){ try{ ((ContentNetworkManagerImpl)getSingleton()).importNetwork( comp.getContent()); comp.setProcessed(); }catch( Throwable e ){ log( "Failed to import from vuze file", e ); Debug.out( e ); } } } } } }); } public static ContentNetworkManager getSingleton() { return( singleton ); } private List<ContentNetworkImpl> networks = new ArrayList<ContentNetworkImpl>(); private CopyOnWriteList<ContentNetworkListener> listeners = new CopyOnWriteList<ContentNetworkListener>(); protected ContentNetworkManagerImpl() { loadConfig(); addNetwork( new ContentNetworkVuze( this )); AEDiagnostics.addEvidenceGenerator( this ); CustomizationManager cust_man = CustomizationManagerFactory.getSingleton(); Customization cust = cust_man.getActiveCustomization(); if ( cust != null ){ String cust_name = COConfigurationManager.getStringParameter( "cnetworks.custom.name", "" ); String cust_version = COConfigurationManager.getStringParameter( "cnetworks.custom.version", "0" ); boolean new_name = !cust_name.equals( cust.getName()); boolean new_version = Constants.compareVersions( cust_version, cust.getVersion() ) < 0; if ( new_name || new_version ){ try{ InputStream[] streams = cust.getResources( Customization.RT_CNETWORKS ); for (int i=0;i<streams.length;i++){ InputStream is = streams[i]; try{ VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is); if ( vf != null ){ VuzeFileComponent[] comps = vf.getComponents(); for (int j=0;j<comps.length;j++){ VuzeFileComponent comp = comps[j]; int type = comp.getType(); if ( type == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){ try{ // change here as we always add all networks upfront so // we always set the customisation flag regardless of // whether existing or not ContentNetwork imported = importNetwork( comp.getContent()); imported.setPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION, true ); comp.setProcessed(); }catch( Throwable e ){ log( "Failed to import customisation network", e ); } } } } }finally{ try{ is.close(); }catch( Throwable e ){ } } } }finally{ COConfigurationManager.setParameter( "cnetworks.custom.name", cust.getName()); COConfigurationManager.setParameter( "cnetworks.custom.version", cust.getVersion()); } } } SimpleTimer.addPeriodicEvent( "MetaSearchRefresh", 23*60*60*1000, new TimerEventPerformer() { public void perform( TimerEvent event ) { checkForUpdates(); } }); if ( networks.size() > 1 || LOAD_ALL_NETWORKS ){ new AEThread2( "CNetwork:init", true ) { public void run() { checkForUpdates(); } }.start(); } } protected void checkForUpdates() { } protected ContentNetworkImpl importNetwork( Map content ) throws IOException { ContentNetworkImpl network = ContentNetworkImpl.importFromBEncodedMapStatic( this, content ); return( addNetwork( network )); } // @see com.aelitis.azureus.core.cnetwork.ContentNetworkManager#addContentNetwork(long) public void addContentNetwork( final long id ) throws ContentNetworkException { } public ContentNetwork getContentNetworkForURL( String url ) { try{ String host = new URL( url ).getHost(); for ( ContentNetwork cn: getContentNetworks()){ String site = (String)cn.getProperty( ContentNetwork.PROPERTY_SITE_HOST ); if ( site != null && site.endsWith( host )){ return( cn ); } } }catch( Throwable e ){ Debug.printStackTrace(e); } return( null ); } public ContentNetwork getStartupContentNetwork() { ContentNetwork[] networks = getContentNetworks(); for ( ContentNetwork network: networks ){ if ( network.isStartupNetwork()){ return( network ); } } return( getContentNetwork( ContentNetwork.CONTENT_NETWORK_VUZE )); } public ContentNetwork[] getContentNetworks() { synchronized( this ){ return((ContentNetwork[])networks.toArray( new ContentNetworkImpl[ networks.size()] )); } } public ContentNetworkImpl getContentNetwork( long id ) { synchronized( this ){ for ( int i=0;i<networks.size();i++ ){ ContentNetworkImpl network = networks.get(i); if ( network.getID() == id ){ return( network ); } } return( null ); } } protected ContentNetworkImpl addNetwork( ContentNetworkImpl network ) { boolean replace = false; synchronized( this ){ Iterator<ContentNetworkImpl> it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl existing_network = it.next(); if ( existing_network.getID() == network.getID()){ if ( network.getVersion() > existing_network.getVersion()){ try{ existing_network.updateFrom( network ); }catch( Throwable e ){ Debug.printStackTrace( e ); } network = existing_network; replace = true; break; }else{ log( "Network " + existing_network.getString() + " already up to date" ); return( existing_network ); } } } if ( replace ){ log( "Updated network: " + network.getString()); }else{ log( "Added network: " + network.getString()); networks.add( network ); } // we never persist the vuze network if ( network.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){ saveConfig(); } } Iterator<ContentNetworkListener> it = (Iterator<ContentNetworkListener>)listeners.iterator(); while( it.hasNext()){ try{ if ( replace ){ it.next().networkChanged( network ); }else{ it.next().networkAdded( network ); } }catch( Throwable e ){ Debug.out( e ); } } return( network ); } protected void removeNetwork( ContentNetworkImpl network ) { synchronized( this ){ if ( !networks.remove( network )){ return; } network.destroy(); saveConfig(); } log( "Removed network: " + network.getString()); Iterator<ContentNetworkListener> it = (Iterator<ContentNetworkListener>)listeners.iterator(); while( it.hasNext()){ try{ it.next().networkRemoved( network ); }catch( Throwable e ){ Debug.out( e ); } } } protected void loadConfig() { if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){ Map map = FileUtil.readResilientConfigFile( CONFIG_FILE ); List list = (List)map.get( "networks" ); if ( list != null ){ for (int i=0;i<list.size();i++){ Map cnet_map = (Map)list.get(i); try{ ContentNetworkImpl cn = ContentNetworkImpl.importFromBEncodedMapStatic( this, cnet_map ); if ( cn.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){ networks.add( cn ); } }catch( Throwable e ){ log( "Failed to load " + cnet_map, e ); } } } } } protected void saveConfig() { Map map = new HashMap(); List list = new ArrayList(); map.put( "networks", list ); Iterator<ContentNetworkImpl> it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl network = it.next(); if ( network.getID() == ContentNetwork.CONTENT_NETWORK_VUZE ){ continue; } Map cnet_map = new HashMap(); try{ network.exportToBEncodedMap( cnet_map ); list.add( cnet_map ); }catch( Throwable e ){ log( "Failed to save " + network.getName(), e ); } } if ( list.size() == 0 ){ FileUtil.deleteResilientConfigFile( CONFIG_FILE ); }else{ FileUtil.writeResilientConfigFile( CONFIG_FILE, map ); } } public void addListener( ContentNetworkListener listener ) { listeners.add( listener ); } public void removeListener( ContentNetworkListener listener ) { listeners.remove( listener ); } public void generate( IndentWriter writer ) { writer.println( "Content Networks" ); try{ writer.indent(); synchronized( this ){ Iterator<ContentNetworkImpl> it = networks.iterator(); while( it.hasNext()){ ContentNetworkImpl network = it.next(); writer.println( network.getString()); } } }finally{ writer.exdent(); } } public static void log( String s, Throwable e ) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" ); diag_logger.log( s ); diag_logger.log( e ); } public static void log( String s ) { AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" ); diag_logger.log( s ); } }