Package com.aelitis.azureus.core.metasearch.impl

Source Code of com.aelitis.azureus.core.metasearch.impl.MetaSearchManagerImpl

/*
* Created on May 6, 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.metasearch.impl;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.xml.util.XUXmlWriter;

import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginListener;
import org.gudy.azureus2.plugins.ui.UIManager;
import org.gudy.azureus2.plugins.ui.UIManagerEvent;
import org.gudy.azureus2.plugins.utils.FeatureManager;
import org.gudy.azureus2.plugins.utils.StaticUtilities;
import org.gudy.azureus2.plugins.utils.FeatureManager.FeatureDetails;
import org.gudy.azureus2.plugins.utils.FeatureManager.Licence;
import org.gudy.azureus2.plugins.utils.search.Search;
import org.gudy.azureus2.plugins.utils.search.SearchException;
import org.gudy.azureus2.plugins.utils.search.SearchInitiator;
import org.gudy.azureus2.plugins.utils.search.SearchInstance;
import org.gudy.azureus2.plugins.utils.search.SearchListener;
import org.gudy.azureus2.plugins.utils.search.SearchObserver;
import org.gudy.azureus2.plugins.utils.search.SearchProvider;
import org.gudy.azureus2.plugins.utils.search.SearchProviderResults;
import org.gudy.azureus2.plugins.utils.search.SearchResult;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;

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.messenger.config.PlatformMetaSearchMessenger;
import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.metasearch.MetaSearch;
import com.aelitis.azureus.core.metasearch.MetaSearchException;
import com.aelitis.azureus.core.metasearch.MetaSearchManager;
import com.aelitis.azureus.core.metasearch.MetaSearchManagerListener;
import com.aelitis.azureus.core.metasearch.Result;
import com.aelitis.azureus.core.metasearch.ResultListener;
import com.aelitis.azureus.core.metasearch.SearchParameter;
import com.aelitis.azureus.core.subs.Subscription;
import com.aelitis.azureus.core.subs.SubscriptionManager;
import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
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.util.ConstantsVuze;
import com.aelitis.azureus.util.ImportExportUtils;

public class
MetaSearchManagerImpl
  implements MetaSearchManager, UtilitiesImpl.searchManager, AEDiagnosticsEvidenceGenerator
{
  private static final boolean AUTO_MODE_DEFAULT    = true;
 
 
  private static final String  LOGGER_NAME = "MetaSearch";
 
  private static final int REFRESH_MILLIS = 23*60*60*1000;
 
  private static MetaSearchManagerImpl singleton; 
 
  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];
             
              int  comp_type = comp.getType();
             
              if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
               
                try{
                  Engine e =
                    getSingleton().importEngine(
                      comp.getContent(),
                      (expected_types & VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE) == 0 );
                 
                  comp.setProcessed();
                 
                  if ( e != null ){
                   
                    comp.setData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY, e );
                  }
                }catch( Throwable e ){
                 
                  Debug.printStackTrace(e);
                }
              }else if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION ){
               
                getSingleton().addOperation( comp.getContent());
               
                comp.setProcessed();
              }
            }
          }
        }
      })
   
    TorrentUtils.addTorrentAttributeListener(
        new TorrentUtils.torrentAttributeListener()
        {
          public void
          attributeSet(
            TOTorrent   torrent,
            String     attribute,
            Object     value )
          {
            if (   attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM &&
                !TorrentUtils.isReallyPrivate( torrent )){
             
              try{
                getSingleton().checkPotentialAssociations( torrent.getHash(), (String)value );
               
              }catch( Throwable e ){
               
                Debug.printStackTrace(e);
              }
            }
          }
        });
  }
 
  public static synchronized MetaSearchManagerImpl
  getSingleton()
  {
    if ( singleton == null ){
     
      singleton = new MetaSearchManagerImpl();
    }
    return( singleton );
  }
 
  private MetaSearchImpl  meta_search;
  private AsyncDispatcher  dispatcher = new AsyncDispatcher( 10000 );
 
  private AESemaphore  initial_refresh_sem = new AESemaphore( "MetaSearch:initrefresh" );
 
  private AESemaphore  refresh_sem = new AESemaphore( "MetaSearch:refresh", 1 );
 
  private boolean  checked_customization;
 
  private AsyncDispatcher          op_dispatcher   = new AsyncDispatcher(5*1000);
  private List<MetaSearchManagerListener>  listeners     = new ArrayList<MetaSearchManagerListener>();
  private List<Map>            operations    = new ArrayList<Map>();
 
  private String    extension_key;
 
  private Map<String,EngineImpl>  potential_associations =
    new LinkedHashMap<String,EngineImpl>(32,0.75f,true)
    {
      protected boolean
      removeEldestEntry(
           Map.Entry<String,EngineImpl> eldest)
      {
        return size() > 32;
      }
    };
  protected
  MetaSearchManagerImpl()
  {
    meta_search = new MetaSearchImpl( this );
   
    AEDiagnostics.addEvidenceGenerator( this );
   
    extension_key = COConfigurationManager.getStringParameter( "metasearch.extkey.latest", "" );

    if ( extension_key.length() == 0 ){
     
      extension_key = null;
    }
   
    setupExtensions();
   
    SimpleTimer.addPeriodicEvent(
      "MetaSearchRefresh",
      REFRESH_MILLIS,
      new TimerEventPerformer()
      {
        public void
        perform(
          TimerEvent   event )
        {
          refresh();
        }
      });
   
    refresh();
   
    UtilitiesImpl.addSearchManager( this );
  }
 
  public void
  addProvider(
    PluginInterface    pi,
    SearchProvider     provider )
  {
    String  id = pi.getPluginID() + "." + provider.getProperty( SearchProvider.PR_NAME );
   
    try{
      meta_search.importFromPlugin( id, provider );
     
    }catch( Throwable e ){
     
      Debug.out( "Failed to add search provider '" + id + "' (" + provider + ")", e );
    }
  }
 
  public SearchProvider[]
    getProviders()
  {
    Engine[] engines = meta_search.getEngines( true, false );
   
    SearchProvider[] result = new SearchProvider[engines.length];
   
    for (int i=0;i<engines.length;i++){
       
      result[i] = new engineInfo( engines[i] );
    }
   
    return( result );
  }
 
  public Search
  createSearch(
    String     provider_ids,
    String     properties_str )
 
    throws SearchException
  {
    String[]  bits = XUXmlWriter.splitWithEscape( provider_ids, ',' );
   
    long[]  pids = new long[ bits.length ];
   
    for ( int i=0; i<bits.length; i++ ){
     
      pids[i] = Long.parseLong( bits[i] );
    }

    Map<String,String>  properties = new HashMap<String, String>();
   
    bits = XUXmlWriter.splitWithEscape( properties_str, ',' );

    for ( int i=0; i<bits.length; i++ ){

      String[] x = XUXmlWriter.splitWithEscape( bits[i], '=' );
     
      properties.put( x[0].trim(), x[1].trim());
    }
   
    return( createSearch( pids, properties, null ));
  }
 
    public Search
    createSearch(
      SearchProvider[]  providers,
      Map<String,String>  properties,
      SearchListener    listener )
   
      throws SearchException
    {
      long[]  pids;
     
      if ( providers == null ){
       
        pids = new long[0];
       
      }else{
       
        pids = new long[providers.length];
       
        for (int i=0;i<pids.length;i++){
     
          Long  id = (Long)providers[i].getProperty( SearchProvider.PR_ID );
     
          if ( id == null ){
       
            throw( new SearchException( "Unknown provider - no id available" ));
          }
         
          pids[i] = id;
      }
      }
     
      return( createSearch( pids, properties, listener ));
    }
   
    protected Search
    createSearch(
      long[]        provider_ids,
      Map<String,String>  properties,
      SearchListener    listener )
   
      throws SearchException
    {
    List<SearchParameter>  sps = new ArrayList<SearchParameter>();

     String  search_term = properties.get( SearchInitiator.PR_SEARCH_TERM );
    
     if ( search_term == null ){
      
       throw( new SearchException( "Search term is mandatory" ));
     }
    
    sps.add( new SearchParameter( "s", search_term ));

     String  mature     = properties.get( SearchInitiator.PR_MATURE );
     
    if ( mature != null ){
     
      sps.add( new SearchParameter( "m", mature.toString()));
    }
 
    SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );

    Map<String,String>  context = new HashMap<String, String>();
   
    context.put( Engine.SC_FORCE_FULL, "true" );

    String  headers     = null;
    int    max_per_engine  = 256;
   
    SearchObject search = new SearchObject( listener );
   
    Engine[]  used_engines;
   
    if ( provider_ids.length == 0 ){
     
      used_engines = getMetaSearch().search( search, parameters, headers, context, max_per_engine );

    }else{
     
      List<Engine>  selected_engines = new ArrayList<Engine>();
     
      for ( long id: provider_ids ){
       
        Engine engine = meta_search.getEngine( id );
       
        if ( engine == null ){
         
          throw( new SearchException( "Unknown engine id - " + id ));
         
        }else{
         
          selected_engines.add( engine );
        }
      }
     
      Engine[] engines = selected_engines.toArray( new Engine[ selected_engines.size()] );
 
      used_engines = getMetaSearch().search( engines, search, parameters, headers, context, max_per_engine );
    }
   
    search.setEnginesUsed( used_engines );
   
    return( search );
    }
 
  protected void
  refresh()
  {
    dispatcher.dispatch(
      new AERunnable()
      {
        public void
        runSupport()
        {
          if ( dispatcher.getQueueSize() == 0 ){
           
            try{
              syncRefresh();
                           
            }catch( Throwable e ){
             
            }
          }
        }
      });
  }
 
  protected void
  ensureEnginesUpToDate()
  {
    long timeout = meta_search.getEngineCount() == 0?(30*1000):(10*1000);
   
    if ( !initial_refresh_sem.reserve( timeout )){
     
      log( "Timeout waiting for initial refresh to complete, continuing" );
    }
  }
 
  protected void
  syncRefresh()
 
    throws MetaSearchException
  {
    boolean refresh_completed   = false;
    boolean  first_run      = false;
   
    try{
      refresh_sem.reserve();
     
      first_run = COConfigurationManager.getBooleanParameter( "metasearch.refresh.first_run", true );
     
      if ( !checked_customization ){
       
        checked_customization = true;
       
        CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
       
        Customization cust = cust_man.getActiveCustomization();
       
        if ( cust != null ){
         
          String cust_name   = COConfigurationManager.getStringParameter( "metasearch.custom.name", "" );
          String cust_version = COConfigurationManager.getStringParameter( "metasearch.custom.version", "0" );
         
          boolean  new_name   = !cust_name.equals( cust.getName());
          boolean  new_version = org.gudy.azureus2.core3.util.Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
         
          if ( new_name || new_version ){

            log( "Customization: checking templates for " + cust.getName() + "/" + cust.getVersion());
           
            try{
              InputStream[] streams = cust.getResources( Customization.RT_META_SEARCH_TEMPLATES );
             
              if ( streams.length > 0 && new_name ){
               
                  // reset engines
               
                log( "    setting auto-mode to false" );
               
                setAutoMode( false );
               
                /*
                Engine[]  engines = meta_search.getEngines( false, false );

                for (int i=0;i<engines.length;i++){
                 
                  Engine engine = engines[i];
                 
                  if ( engine.getSelectionState()) == Engine.SEL_STATE_MANUAL_SELECTED ){
                   
                  }
                }
                */
              }
              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];
                     
                      if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
                       
                        try{
                          Engine e =
                            getSingleton().importEngine( comp.getContent(), false );
                         
                          log( "    updated " + e.getName());
                         
                          e.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
                         
                        }catch( Throwable e ){
                         
                          Debug.printStackTrace(e);
                        }
                      }
                    }
                  }
                }finally{
                 
                  try{
                    is.close();
                   
                  }catch( Throwable e ){
                  }
                }
              }
            }finally{
             
              COConfigurationManager.setParameter( "metasearch.custom.name", cust.getName());
              COConfigurationManager.setParameter( "metasearch.custom.version", cust.getVersion());
            }
          }
        }
      }
     
      log( "Refreshing engines" );
         
        // featured templates are always shown - can't be deselected
        // popular ones are selected if in 'auto' mode
        // manually selected ones are, well, manually selected
     
      Map<Long,PlatformMetaSearchMessenger.templateInfo>    vuze_selected_ids     = new HashMap<Long, PlatformMetaSearchMessenger.templateInfo>();
      Map<Long,PlatformMetaSearchMessenger.templateInfo>    vuze_preload_ids     = new HashMap<Long,PlatformMetaSearchMessenger.templateInfo>();
     
      Set<Long>    featured_ids       = new HashSet<Long>();
      Set<Long>    popular_ids       = new HashSet<Long>();
      Set<Long>    manual_vuze_ids     = new HashSet<Long>();
     
      boolean    auto_mode = isAutoMode();
         
      Engine[]  engines = meta_search.getEngines( false, false );
 
      String  fud = meta_search.getFUD();
     
      try{
        PlatformMetaSearchMessenger.templateInfo[] featured = PlatformMetaSearchMessenger.listFeaturedTemplates( extension_key, fud );
       
        String featured_str = "";
       
        for (int i=0;i<featured.length;i++){
         
          PlatformMetaSearchMessenger.templateInfo template = featured[i];
         
          if ( !template.isVisible()){
           
            continue;
          }
         
          Long key = new Long( template.getId());
         
          vuze_selected_ids.put( key,  template );
         
          featured_ids.add( key );
         
          featured_str += (featured_str.length()==0?"":",") + key;
        }
         
        log( "Featured templates: " + featured_str );
       
        if ( auto_mode || first_run ){
         
          PlatformMetaSearchMessenger.templateInfo[] popular = PlatformMetaSearchMessenger.listTopPopularTemplates( extension_key, fud );
         
          String popular_str = "";
          String preload_str = "";
         
          for (int i=0;i<popular.length;i++){
           
            PlatformMetaSearchMessenger.templateInfo template = popular[i];
           
            if ( !template.isVisible()){
             
              continue;
            }
           
            Long  key = new Long( template.getId());
           
            if ( auto_mode ){
             
              if ( !vuze_selected_ids.containsKey( key )){
               
                vuze_selected_ids.put( key,  template );
               
                popular_ids.add( key );
               
                popular_str += (popular_str.length()==0?"":",") + key;
              }
            }else{
             
              if ( !vuze_preload_ids.containsKey( key )){
               
                vuze_preload_ids.put( key, template );
                               
                preload_str += (preload_str.length()==0?"":",") + key;
              }
            }
          }
         
          log( "Popular templates: " + popular_str );
         
          if ( preload_str.length() > 0 ){
           
            log( "Pre-load templates: " + popular_str );
          }
        }
           
          // pick up explicitly selected vuze ones
       
        String manual_str = "";
       
        for (int i=0;i<engines.length;i++){
         
          Engine  engine = engines[i];
         
          Long key = new Long( engine.getId());
         
          if (   engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
              engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED &&
              !vuze_selected_ids.containsKey( key )){
           
            manual_vuze_ids.add( key );
          }
        }
       
        if ( manual_vuze_ids.size() > 0 ){
         
          long[]  manual_ids = new long[manual_vuze_ids.size()];
         
          Iterator<Long> it = manual_vuze_ids.iterator();
         
          int  pos = 0;
         
          while( it.hasNext()){
           
            manual_ids[pos++] = it.next().longValue();
          }
         
          PlatformMetaSearchMessenger.templateInfo[] manual = PlatformMetaSearchMessenger.getTemplateDetails( extension_key, manual_ids );
                   
          for (int i=0;i<manual.length;i++){
           
            PlatformMetaSearchMessenger.templateInfo template = manual[i];
           
            if ( !template.isVisible()){
             
              continue;
            }
           
            Long  key = new Long( template.getId());
                         
            vuze_selected_ids.put( key, template );
                           
            manual_str += (manual_str.length()==0?"":",") + key;
          }
        }
       
        log( "Manual templates: " + manual_str );
       
        Map<Long,Engine> existing_engine_map = new HashMap<Long,Engine>();
       
        String existing_str = "";
       
        for (int i=0;i<engines.length;i++){
         
          Engine  engine = engines[i];
         
          Long key = new Long( engine.getId());
 
          existing_engine_map.put( key, engine );
         
          existing_str += (existing_str.length()==0?"":",") + key +
                    "[source=" + Engine.ENGINE_SOURCE_STRS[engine.getSource()] +
                    ",type=" + engine.getType() +
                    ",selected=" + Engine.SEL_STATE_STRINGS[engine.getSelectionState()] + "]";
        }
       
        log( "Existing templates: " + existing_str );
       
          // we've compiled a list of the engines we should have and their latest dates
       
          // update any that are out of date
       
        Iterator<Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo>> it = vuze_selected_ids.entrySet().iterator();
       
        while( it.hasNext()){
         
          Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
         
          vuze_preload_ids.remove( entry.getKey());
         
          long  id       = entry.getKey().longValue();
         
          PlatformMetaSearchMessenger.templateInfo template = entry.getValue();
         
          long  modified   = template.getModifiedDate();
                 
          Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
         
          boolean  update = this_engine == null || this_engine.getLastUpdated() < modified;
 
          if ( update ){
           
            PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
 
            log( "Downloading definition of template " + id );
            log( details.getValue());
           
            if ( details.isVisible()){
             
              try{
                this_engine =
                  meta_search.importFromJSONString(
                    details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
                    details.getId(),
                    details.getModifiedDate(),
                    details.getRankBias(),
                    details.getName(),
                    details.getValue());
               
                this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
                               
                meta_search.addEngine( this_engine );
               
              }catch( Throwable e ){
               
                log( "Failed to import engine '" + details.getValue() + "'", e );
              }
            } 
          }else if ( this_engine.getRankBias() != template.getRankBias()){
           
            this_engine.setRankBias( template.getRankBias());
           
            log( "Updating rank bias for " + this_engine.getString() + " to " + template.getRankBias());

          }else{
           
            log( "Not updating " + this_engine.getString() + " as unchanged" );
          }
         
          if ( this_engine != null ){
             
            int sel_state = this_engine.getSelectionState();
           
            if ( sel_state == Engine.SEL_STATE_DESELECTED ){
           
              log( "Auto-selecting " + this_engine.getString());
             
              this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
             
            }else if ( auto_mode && sel_state == Engine.SEL_STATE_MANUAL_SELECTED ){
             
              log( "Switching Manual to Auto select for " + this_engine.getString());
             
              this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
            }
          }
        }
       
          // do any pre-loads
       
        it = vuze_preload_ids.entrySet().iterator();
       
        while( it.hasNext()){
         
          Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
         
          long  id       = ((Long)entry.getKey()).longValue();
                 
          Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
           
          if ( this_engine == null ){
           
            PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
 
            log( "Downloading pre-load definition of template " + id );
            log( details.getValue());
           
            if ( details.isVisible()){
             
              try{
                this_engine =
                  meta_search.importFromJSONString(
                    details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
                    details.getId(),
                    details.getModifiedDate(),
                    details.getRankBias(),
                    details.getName(),
                    details.getValue());
               
                this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
               
                this_engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
                               
                meta_search.addEngine( this_engine );
               
              }catch( Throwable e ){
               
                log( "Failed to import engine '" + details.getValue() + "'", e );
              }
            }     
          }
        }
       
          // deselect any not in use
       
        for (int i=0;i<engines.length;i++){
         
          Engine  engine = engines[i];
         
          if (   engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
              engine.getSelectionState() == Engine.SEL_STATE_AUTO_SELECTED &&
              !vuze_selected_ids.containsKey( new Long( engine.getId()))){
           
            log( "Deselecting " + engine.getString() + " as no longer visible on Vuze");
           
            engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
          }
        }
       
          // finally pick up any unreported selection changes and re-affirm positive selections
       
        for (int i=0;i<engines.length;i++){
         
          Engine  engine = engines[i];
         
          if (   engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
              engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
           
            engine.recordSelectionState();
           
          }else{
           
            engine.checkSelectionStateRecorded();
          }
        }
       
        refresh_completed = true;
       
      }catch( Throwable e ){
       
        log( "Refresh failed", e );
       
        throw( new MetaSearchException( "Refresh failed", e ));
      }
    }finally{
     
      if ( first_run && refresh_completed ){
       
        COConfigurationManager.setParameter( "metasearch.refresh.first_run", false );
      }
     
      refresh_sem.release();
     
      initial_refresh_sem.releaseForever();
    }
  }
 
  public MetaSearch
  getMetaSearch()
  {
    return( meta_search );
  }
 
  public boolean
  isAutoMode()
  {
    return( COConfigurationManager.getBooleanParameter( "metasearch.auto.mode", AUTO_MODE_DEFAULT ));
  }
 
  protected void
  setAutoMode(
    boolean  auto )
  {
    COConfigurationManager.setParameter( "metasearch.auto.mode", auto );
  }
 
  public void
  setSelectedEngines(
    long[]    ids,
    boolean    auto )
 
    throws MetaSearchException
  {
    try{
      String  s = "";
     
      for (int i=0;i<ids.length;i++){
       
        s += (i==0?"":",") + ids[i];
      }
     
      log( "setSelectedIds: " + s + ", auto=" + auto );
     
        // first update state of auto and existing engines
     
      COConfigurationManager.setParameter( "metasearch.auto.mode", auto );

      Engine[]  engines = meta_search.getEngines( false, false );
     
      Map<Long,Engine>  engine_map = new HashMap<Long,Engine>();
     
      for( int i=0;i<engines.length;i++){
       
        engine_map.put( new Long( engines[i].getId()), engines[i] );
      }
       
      Set<Engine> selected_engine_set = new HashSet<Engine>();
     
      for (int i=0;i<ids.length;i++){
       
        long   id = ids[i];
       
        Engine existing = (Engine)engine_map.get(new Long(id));
       
        if ( existing != null ){
         
          existing.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
         
          selected_engine_set.add( existing );
        }
      }
   
        // now refresh - this will pick up latest state of things
     
      syncRefresh();
     
      engines = meta_search.getEngines( false, false );

        // next add in any missing engines
     
      for (int i=0;i<ids.length;i++){
       
        long   id = ids[i];
       
        Engine existing = (Engine)engine_map.get(new Long(id));
       
        if ( existing == null ){
                           
          PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
 
          log( "Downloading definition of template " + id );
          log( details.getValue());
         
          Engine new_engine =
            meta_search.importFromJSONString(
              details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
              details.getId(),
              details.getModifiedDate(),
              details.getRankBias(),
              details.getName(),
              details.getValue());
             
          new_engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
                   
          new_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
           
          meta_search.addEngine( new_engine );
         
          selected_engine_set.add( new_engine );
        }
      }
     
        // deselect any existing manually selected ones that are no longer selected
     
      for( int i=0;i<engines.length;i++){

        Engine e = engines[i];
       
        if ( e.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
         
          if ( !selected_engine_set.contains( e )){
       
            e.setSelectionState( Engine.SEL_STATE_DESELECTED  );
          }
        }
      }
    }catch( Throwable e ){
     
      e.printStackTrace();
     
      if ( e instanceof MetaSearchException ){
       
        throw((MetaSearchException)e);
      }
     
      throw( new MetaSearchException( "Failed to set selected engines", e ));
    }
  }
 
  public Engine
  addEngine(
    long    id,
    int      type,
    String    name,
    String    json_value )
 
    throws MetaSearchException
  {
    if ( id == -1 ){
     
      id = getLocalTemplateID();
    }
   
    try{
      Engine engine =
        meta_search.importFromJSONString(
          type, id, SystemTime.getCurrentTime(), 1, name, json_value );
     
      engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
     
      engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
     
      meta_search.addEngine( engine );
     
      return( engine );
     
    }catch( Throwable e ){
     
      throw( new MetaSearchException( "Failed to add engine", e ));
    }
  }
 
  public boolean
  isImportable(
    VuzeFile    vf )
  {
    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_METASEARCH_TEMPLATE ){
       
        try{
          EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap( comp.getContent());
         
          long  id = engine.getId();
         
          Engine existing = meta_search.getEngine( id );
         
          if ( existing != null ){
           
            if ( !existing.sameLogicAs( engine )){
             
              return( true );
            }
          }else{
            try{           
              Engine[] engines = meta_search.getEngines( false, false );
               
              boolean is_new = true;
             
              for ( Engine e: engines ){
                 
                if ( e.sameLogicAs( engine )){
                   
                  is_new = false;
                 
                  break;
                }
              }
             
              if ( is_new ){
               
                return( true );
              }
            }catch( Throwable e ){ 
            } 
          }
        }catch( Throwable e ){       
        }
      }
    }
   
    return( false );
  }
 
  public Engine
  importEngine(
    Map      map,
    boolean    warn_user )
 
    throws MetaSearchException
  {
    try{
      EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap(map);
     
      long  id = engine.getId();
     
      Engine existing = meta_search.getEngine( id );
     
      if ( existing != null ){
       
        if ( existing.sameLogicAs( engine )){
         
          if ( warn_user ){
           
            UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
           
            String details = MessageText.getString(
                "metasearch.addtemplate.dup.desc",
                new String[]{ engine.getName() });
           
            ui_manager.showMessageBox(
                "metasearch.addtemplate.dup.title",
                "!" + details + "!",
                UIManagerEvent.MT_OK );
          }
         
          return( existing );
        }
      }else{
                 
        try{           
          Engine[] engines = meta_search.getEngines( false, false );
           
          for ( Engine e: engines ){
             
            if ( e.sameLogicAs( engine )){
               
              return( e );
            }
          }
        }catch( Throwable e ){
         
        }
      }
     
      if ( warn_user ){
       
        UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
       
        String details = MessageText.getString(
            "metasearch.addtemplate.desc",
            new String[]{ engine.getName() });
       
        long res = ui_manager.showMessageBox(
            "metasearch.addtemplate.title",
            "!" + details + "!",
            UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
       
        if ( res != UIManagerEvent.MT_YES ){
         
          throw( new MetaSearchException( "User declined the template" ));
        }
      }
        // if local template then we try to use the id as is otherwise we emsure that
        // it is a local one
     
      if ( id >= 0 && id < Integer.MAX_VALUE ){
       
        id = getLocalTemplateID();
       
        engine.setId( id );
      }
     
      engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
     
      engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
     
      meta_search.addEngine( engine );
     
      if ( warn_user ){
       
        UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
       
        String details = MessageText.getString(
            "metasearch.addtemplate.done.desc",
            new String[]{ engine.getName() });
       
        ui_manager.showMessageBox(
            "metasearch.addtemplate.done.title",
            "!" + details + "!",
            UIManagerEvent.MT_OK );
      }
     
      return( engine );
     
    }catch( Throwable e ){
     
      if ( warn_user ){
       
        UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
       
        String details = MessageText.getString(
            "metasearch.addtemplate.failed.desc",
            new String[]{ Debug.getNestedExceptionMessage(e) });
       
        ui_manager.showMessageBox(
            "metasearch.addtemplate.failed.title",
            "!" + details + "!",
            UIManagerEvent.MT_OK );
      }
     
      throw( new MetaSearchException( "Failed to add engine", e ));
    }
  }
 
  protected void
  addPotentialAssociation(
    EngineImpl    engine,
    String      key )
  {   
    if ( engine.isShareable() && !engine.isAuthenticated()){
     
      synchronized( potential_associations ){
       
        potential_associations.put( key, engine );
      }
    }
  }
 
  private void
  checkPotentialAssociations(
    byte[]    hash,
    String    key )
  {
    EngineImpl  engine;
   
    synchronized( potential_associations ){
     
      engine = potential_associations.remove( key );
    }
 
    if ( engine != null ){
 
      try{
        VuzeFile vf = engine.exportToVuzeFile( true );
       
        byte[] bytes = vf.exportToBytes();
                       
        String url_str = "vuze://?body=" + new String( bytes, Constants.BYTE_ENCODING );
               
        SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
   
        Subscription subs =
          sub_man.createSingletonRSS(
            vf.getName() + ": " + engine.getName() + " (v" + engine.getVersion() + ")",
            new URL( url_str ),
            Integer.MAX_VALUE );
     
        subs.setSubscribed( true );
     
        subs.addAssociation( hash );
       
      }catch( Throwable e ){
       
        Debug.out( e );
      }
    }
  }
 
  public Engine[]
  loadFromVuzeFile(
    File    file )
  {
    VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( file.getAbsolutePath());
   
    if ( vf != null ){
     
      return( loadFromVuzeFile( vf ));
    }
   
    return( new Engine[0]);
  }
 
  public Engine[]
  loadFromVuzeFile(
    VuzeFile    vf )
  {
    List<Engine>  result = new ArrayList<Engine>();
   
    VuzeFileComponent[] comps = vf.getComponents();
   
    for (int j=0;j<comps.length;j++){
     
      VuzeFileComponent comp = comps[j];
     
      if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
       
        try{
          result.add( importEngine( comp.getContent(), false ));
                     
        }catch( Throwable e ){
         
          Debug.printStackTrace(e);
        }
      }
    }
   
    return(result.toArray(new Engine[result.size()]));
  }
 
  public long
  getLocalTemplateID()
  {
    synchronized( this ){
     
      Random random = new Random();
     
      while( true ){
     
        long id = ((long)Integer.MAX_VALUE) + random.nextInt( Integer.MAX_VALUE );
       
        if ( meta_search.getEngine( id ) == null ){
         
          return( id );
        }
      }
    }
  }
 
  public void
  addListener(
    MetaSearchManagerListener    listener )
  {     
    synchronized( listeners ){
     
      listeners.add( listener );
    }
     
    dispatchOps();
  }
 
  public void
  removeListener(
    MetaSearchManagerListener    listener )
  {
   
  }
 
  private void
  addOperation(
    Map    map )
  {
    synchronized( listeners ){
     
      operations.add( map );
    }
   
    dispatchOps();
  }
 
  private void
  dispatchOps()
  {
    op_dispatcher.dispatch(
      new AERunnable()
      {
        public void
        runSupport()
        {
          List<MetaSearchManagerListener>  l;
          List<Map>            o;
         
          synchronized( listeners ){
         
            if ( listeners.size() == 0 || operations.size() == 0 ){
             
              return;
            }
           
            l = new ArrayList<MetaSearchManagerListener>( listeners );
           
            o = new ArrayList<Map>( operations );
           
            operations.clear();
          }
         
          for ( MetaSearchManagerListener listener: l ){
           
            for ( Map operation: o ){
         
              try{

                int  type = ImportExportUtils.importInt( operation, "type", -1 );
               
                if ( type == 1 ){
                 
                  String  term = ImportExportUtils.importString( operation, "term", null );
               
                  if ( term == null ){
                   
                    Debug.out( "search term missing" );
                   
                  }else{
                   
                    listener.searchRequest( term );
                  }
                }else{
               
                  Debug.out( "unknown operation type " + type );
                }               
              }catch( Throwable e ){
               
                Debug.out( e );
              }
            }
          }
        }
      });
  }
 
  private void
  setupExtensions()
  {
    PluginInterface pi = PluginInitializer.getDefaultInterface();
   
    final FeatureManager fm = pi.getUtilities().getFeatureManager();
         
    fm.addListener(
      new FeatureManager.FeatureManagerListener()
      {
        public void
        licenceAdded(
          Licence  licence )
        {
          getExtensions( fm, false );
        }
       
        public void
        licenceChanged(
          Licence  licence )
        {
          getExtensions( fm, false );
        }
       
        public void
        licenceRemoved(
          Licence  licence )
        {
          getExtensions( fm, false );
        }
      });
   
    if ( pi.getPluginState().isInitialisationComplete()){
     
      getExtensions( fm, true );
     
    }else{
     
      pi.addListener(
        new PluginListener()
        {
          public void
          initializationComplete()
          {
            getExtensions( fm, false );
          }
         
          public void
          closedownInitiated()
          {
          }
         
          public void
          closedownComplete()
          { 
          }
        });
    }
  }
 
  private void
  getExtensions(
    FeatureManager    fm,
    boolean        init )
  {
    String  existing_ext   = extension_key;
    String  latest_ext    = null;
   
    FeatureDetails[] fds = fm.getFeatureDetails( "core" );
   
    for ( FeatureDetails fd: fds ){
       
      if ( !fd.hasExpired()){
       
        String finger_print = (String)fd.getProperty( FeatureDetails.PR_FINGERPRINT );
         
        if ( finger_print != null ){
       
          latest_ext = fd.getLicence().getShortID() + "-" + finger_print;
         
          break;
        }
      }
    }

    if ( existing_ext != latest_ext ){
     
      if ( existing_ext == null || latest_ext == null || !existing_ext.equals( latest_ext )){
       
        extension_key  = latest_ext;
       
        COConfigurationManager.setParameter( "metasearch.extkey.latest", latest_ext==null?"":latest_ext );
       
        if ( !init ){
         
          refresh();
        }
      }
    }
  }
 
  protected String
  getExtensionKey()
  {
    return( extension_key );
  }
 
  public void
  log(
    String     s,
    Throwable   e )
  {
    AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
   
    diag_logger.log( s );
    diag_logger.log( e );
   
    if ( ConstantsVuze.DIAG_TO_STDOUT ){
     
      System.out.println(Thread.currentThread().getName() + "|"
          + System.currentTimeMillis() + "] " + s + ": " + Debug.getNestedExceptionMessage(e));
   
  }
 
  public void
  log(
    String   s )
  {
    AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
   
    diag_logger.log( s );
   
    if ( ConstantsVuze.DIAG_TO_STDOUT ){
     
      System.out.println(Thread.currentThread().getName() + "|"
          + System.currentTimeMillis() + "] " + s);
    }
  }
 
  public void
  generate(
    IndentWriter    writer )
  {
    writer.println( "Metasearch: auto=" + isAutoMode());
     
    try{
      writer.indent();

      meta_search.generate( writer );
     
    }finally{
     
      writer.exdent();
    }
  }
 
  protected static class
  SearchObject
    implements Search, ResultListener
  {
    private SearchListener    listener;
   
    private Map<Long,engineInfo>  engine_map = new HashMap<Long, engineInfo>();
    private boolean          engines_set;
   
    private List<SearchProviderResults>  pending_results = new ArrayList<SearchProviderResults>();
   
    private boolean  is_complete;
   
    protected
    SearchObject(
      SearchListener  _listener )
    {
      listener = _listener;
    }
   
    protected void
    setEnginesUsed(
      Engine[]  engines )
    {
      boolean  report_complete;
     
      synchronized( engine_map ){
       
        for ( Engine e: engines ){
         
          getInfo( e );
        }
       
        engines_set = true;
       
        report_complete = reportOverallComplete();
      }
     
      if ( listener != null && report_complete ){
         
        listener.completed();
      }
    }
   
    private boolean
    reportOverallComplete()
    {
      if ( is_complete || !engines_set ){
       
        return( false );
      }
     
      for ( engineInfo info: engine_map.values()){
       
        if ( !info.isComplete()){
         
          return( false );
        }
      }
     
      is_complete = true;
     
      return( true );
    }
   
    protected engineInfo
    getInfo(
      Engine    engine )
    {
      synchronized( engine_map ){

        engineInfo res = engine_map.get( engine.getId());
       
        if ( res == null ){
         
          res = new engineInfo( engine );
         
          engine_map.put( engine.getId(), res );
        }
       
        return( res );
      }
    }
   
    public void
    contentReceived(
      Engine     engine,
      String     content )
    { 
        // boring
    }
   
    public void
    matchFound(
      Engine     engine,
      String[]   fields )
    { 
      // boring
    }
   
    public void
    resultsReceived(
      Engine       engine,
      final Result[]   results )
    {
      SearchProviderResults  result;

      synchronized( engine_map ){
       
        final engineInfo info = getInfo( engine );
       
        result =
          new SearchProviderResults()
          {
            public SearchProvider
            getProvider()
            {
              return( info );
            }
           
            public SearchResult[]
            getResults()
            {
              return( wrapResults( results ));
            }
           
            public boolean
            isComplete()
            {
              return( false );
            }
           
            public SearchException
            getError()
            {
              return( null );
            }
          };
         
        pending_results.add( result );
      }
     
      if ( listener != null ){
       
        listener.receivedResults( new SearchProviderResults[]{ result });
      }
    }
   
    public void
    resultsComplete(
      Engine     engine )
    {
      boolean          report_complete;
      SearchProviderResults  result;
     
      synchronized( engine_map ){
       
        final engineInfo info = getInfo( engine );
       
        info.setComplete();
       
        report_complete = reportOverallComplete();
     
        result =
          new SearchProviderResults()
          {
            public SearchProvider
            getProvider()
            {
              return( info );
            }
           
            public SearchResult[]
            getResults()
            {
              return( new SearchResult[0] );
            }
           
            public boolean
            isComplete()
            {
              return( true );
            }
           
            public SearchException
            getError()
            {
              return( null );
            }
          };
         
        pending_results.add( result );
      }
     
      if ( listener != null ){
       
        listener.receivedResults( new SearchProviderResults[]{ result });
       
        if ( report_complete ){
         
          listener.completed();
        }
      }
    }
   
    protected void
    failed(
      Engine            engine,
      final SearchException    error )
    {
      boolean          report_complete;
      SearchProviderResults  result;
     
      synchronized( engine_map ){
       
        final engineInfo info = getInfo( engine );
       
        info.setComplete();
       
        report_complete = reportOverallComplete();
       
        result =
            new SearchProviderResults()
            {
              public SearchProvider
              getProvider()
              {
                return( info );
              }
             
              public SearchResult[]
              getResults()
              {
                return( new SearchResult[0] );
              }
             
              public boolean
              isComplete()
              {
                return( false );
              }
             
              public SearchException
              getError()
              {
                return( error );
              }
            };
           
        pending_results.add( result );
      }
     
      if ( listener != null ){
       
        listener.receivedResults( new SearchProviderResults[]{ result });
       
        if ( report_complete ){
         
          listener.completed();
        }
      }
    }
   
    public void
    engineFailed(
      Engine     engine,
      Throwable   cause )
    {
      failed( engine, new SearchException( "Search failed", cause ));
    }
   
    public void
    engineRequiresLogin(
      Engine     engine,
      Throwable   cause )
    {
      failed( engine, new SearchException( "Authentication required", cause ));
    }
   
    protected SearchResult[]
    wrapResults(
      Result[]  res )
    {
      SearchResult[] x = new SearchResult[ res.length ];
     
      for ( int i=0;i<x.length;i++){
       
        x[i] = new resultWrapper( res[i] );
      }
     
      return( x );
    }
   
    public SearchProviderResults[]
       getResults()
    {
         synchronized( engine_map ){

           SearchProviderResults[] result = pending_results.toArray( new SearchProviderResults[pending_results.size()]);
          
           pending_results.clear();
          
           return( result );
         }
    }
      
       public boolean
       isComplete()
       {
         synchronized( engine_map ){
          
           if ( !is_complete ){
            
             return( false );
           }
          
           if ( pending_results.size() > 0 ){
            
             return( false );
           }
          
           return( true );
         }
       }
      
       protected static class
       resultWrapper
         implements SearchResult
       {
         private Result  result;
        
         protected
         resultWrapper(
           Result    _result )
         {
           result  = _result;
         }
        
         public Object
         getProperty(
           int    property_name )
         {
           switch( property_name ){
             case PR_NAME:{
            
               return( result.getName());
             }
             case PR_PUB_DATE:{
              
               return( result.getPublishedDate());
             }
             case PR_SIZE:{
              
               return( result.getSize());
             }
             case PR_LEECHER_COUNT:{
              
               return( new Long( result.getNbPeers()));
             }
             case PR_SEED_COUNT:{
              
               return( new Long( result.getNbSeeds()));
             }
             case PR_SUPER_SEED_COUNT:{
              
               return( new Long( result.getNbSuperSeeds()));
             }
             case PR_CATEGORY:{
              
               return( result.getCategory());
             }
             case PR_COMMENTS:{
              
               return( new Long( result.getComments()));
             }
             case PR_VOTES:{
              
               return( new Long( result.getVotes()));
             }
             case PR_CONTENT_TYPE:{
              
               return( result.getContentType());
             }
             case PR_DETAILS_LINK:{
              
               return( result.getCDPLink());
             }
             case PR_DOWNLOAD_LINK:{
              
               return( result.getDownloadLink());
             }
             case PR_PLAY_LINK:{
              
               return( result.getPlayLink());
             }
             case PR_PRIVATE:{
              
               return( result.isPrivate());
             }
             case PR_DRM_KEY:{
              
               return( result.getDRMKey());
             }
             case PR_DOWNLOAD_BUTTON_LINK:{
              
               return( result.getDownloadButtonLink());
             }
             case PR_RANK:{
            
               float rank = result.getRank();
              
               return( new Long(rank==-1?-1:(long)( rank * 100 )));
             }
             case PR_ACCURACY:{
            
               float accuracy = result.getAccuracy();
              
               return( new Long(accuracy==-1?-1:(long)( accuracy * 100 )));
             }
             case PR_VOTES_DOWN:{
              
               return( new Long( result.getVotesDown()));
             }
             case PR_UID:{
            
               return( result.getUID());
             }
             case PR_HASH:{
              
               String base32_hash = result.getHash();
              
               if ( base32_hash != null ){
                
                 return( Base32.decode( base32_hash ));
               }
              
               return( null );
             }
             default:{
              
               Debug.out( "Unknown property type " + property_name );
             }
           }
          
           return( null );
         }
       }
  }
 
    protected static class
    engineInfo
      implements SearchProvider
    {
      private Engine    engine;
        
      private boolean    complete;
     
      protected
      engineInfo(
        Engine    _engine )
      {
        engine  = _engine;
      }
   
      protected void
      setComplete()
      {
        complete  = true;
      }
     
      protected boolean
      isComplete()
      {
        return( complete );
      }
     
    public SearchInstance
    search(
      Map<String,Object>  search_parameters,
      SearchObserver    observer )
   
      throws SearchException
    {
      throw( new SearchException( "Not supported" ));
    }
   
    public Object
    getProperty(
      int      property )
    {
      if ( property == PR_ID ){
       
        return( engine.getId());
       
      }else if ( property == PR_NAME ){
       
        return( engine.getName());
       
      }else{
       
        return( null );
      }
    }
   
    public void
    setProperty(
      int      property,
      Object    value )
    {
      Debug.out( "Not supported" );
    }
  }
   
    public static void
    main(
      String[]  args )
    {
      try{
      VuzeFile  vf = VuzeFileHandler.getSingleton().create();
     
      Map contents = new HashMap();
     
      contents.put( "type", new Long( 1 ));
      contents.put( "term", "donkey" );
     
      vf.addComponent(
        VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION,
        contents);
     
      vf.write( new File( "C:\\temp\\search.vuze" ));
     
      }catch( Throwable e ){
       
        e.printStackTrace();
      }
    }
}
TOP

Related Classes of com.aelitis.azureus.core.metasearch.impl.MetaSearchManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.