/* * Created on Jun 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.metasearch.impl.plugin; import java.io.IOException; import java.util.*; import org.gudy.azureus2.core3.util.AESemaphore; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.plugins.utils.search.SearchInstance; import org.gudy.azureus2.plugins.utils.search.SearchObserver; import org.gudy.azureus2.plugins.utils.search.SearchProvider; import org.gudy.azureus2.plugins.utils.search.SearchResult; import com.aelitis.azureus.core.metasearch.*; import com.aelitis.azureus.core.metasearch.impl.*; public class PluginEngine extends EngineImpl { private static int[][] FIELD_MAP = { { SearchResult.PR_CATEGORY, Engine.FIELD_CATEGORY }, { SearchResult.PR_COMMENTS, Engine.FIELD_COMMENTS }, { SearchResult.PR_CONTENT_TYPE, Engine.FIELD_CONTENT_TYPE }, { SearchResult.PR_DETAILS_LINK, Engine.FIELD_CDPLINK }, { SearchResult.PR_DOWNLOAD_BUTTON_LINK, Engine.FIELD_DOWNLOADBTNLINK }, { SearchResult.PR_DOWNLOAD_LINK, Engine.FIELD_TORRENTLINK }, { SearchResult.PR_DRM_KEY, Engine.FIELD_DRMKEY }, { SearchResult.PR_LEECHER_COUNT, Engine.FIELD_PEERS }, { SearchResult.PR_NAME, Engine.FIELD_NAME }, { SearchResult.PR_PLAY_LINK, Engine.FIELD_PLAYLINK }, { SearchResult.PR_PRIVATE, Engine.FIELD_PRIVATE }, { SearchResult.PR_PUB_DATE, Engine.FIELD_DATE }, { SearchResult.PR_SEED_COUNT, Engine.FIELD_SEEDS }, { SearchResult.PR_SIZE, Engine.FIELD_SIZE }, { SearchResult.PR_SUPER_SEED_COUNT, Engine.FIELD_SUPERSEEDS }, { SearchResult.PR_VOTES, Engine.FIELD_VOTES }, }; public static EngineImpl importFromBEncodedMap( MetaSearchImpl meta_search, Map map ) throws IOException { return( new PluginEngine( meta_search, map )); } private SearchProvider provider; public PluginEngine( MetaSearchImpl _meta_search, long _id, SearchProvider _provider ) { super( _meta_search, Engine.ENGINE_TYPE_PLUGIN, _id, 0, 1.0f, (String)_provider.getProperty( SearchProvider.PR_NAME )); provider = _provider; setSource( ENGINE_SOURCE_LOCAL ); } protected PluginEngine( MetaSearchImpl _meta_search, Map _map ) throws IOException { super( _meta_search, _map ); // recovery from when incorrectly defaulted to 0.0 if ( getRankBias() == 0.0f ){ setRankBias( 1.0f ); } setSource( ENGINE_SOURCE_LOCAL ); } public Map exportToBencodedMap() throws IOException { return( exportToBencodedMap( false )); } public Map exportToBencodedMap( boolean generic ) throws IOException { Map res = new HashMap(); super.exportToBencodedMap( res, generic ); return( res ); } public void setProvider( SearchProvider _provider ) { provider = _provider; } public SearchProvider getProvider() { return( provider ); } protected boolean useAccuracyForRank() { if ( provider == null ){ return( false ); } Boolean val = (Boolean)provider.getProperty( SearchProvider.PR_USE_ACCURACY_FOR_RANK ); if ( val == null ){ return( false ); } return( val.booleanValue()); } public boolean isActive() { return( provider != null && super.isActive()); } public String getNameEx() { return( super.getName() + ": (plugin)" ); } public String getDownloadLinkCSS() { if ( provider == null ){ return( null ); } return((String)provider.getProperty( SearchProvider.PR_DOWNLOAD_LINK_LOCATOR )); } public boolean supportsField( int field ) { if ( provider == null ){ return( false ); } int[] supports = (int[])provider.getProperty( SearchProvider.PR_SUPPORTS_RESULT_FIELDS ); if ( supports == null ){ return( true ); } for (int i=0;i<FIELD_MAP.length;i++){ int[] entry = FIELD_MAP[i]; if ( entry[1] == field ){ for (int j=0;j<supports.length;j++){ if ( supports[j] == entry[0] ){ return( true ); } } break; } } return( false ); } public boolean supportsContext( String context_key ) { return( false ); } public boolean isShareable() { return( false ); } public String getIcon() { if ( provider == null ){ return( null ); } return((String)provider.getProperty( SearchProvider.PR_ICON_URL )); } public String getReferer() { if ( provider == null ){ return( null ); } return((String)provider.getProperty( SearchProvider.PR_REFERER )); } protected Result[] searchSupport( SearchParameter[] params, Map searchContext, final int desired_max_matches, final int absolute_max_matches, String headers, final ResultListener listener ) throws SearchException { if ( provider == null ){ provider = getMetaSearch().resolveProvider( this ); if ( provider == null ){ return( new Result[0] ); } } Map search_parameters = new HashMap(); String term = null; for (int i=0;i<params.length;i++){ SearchParameter param = params[i]; String pattern = param.getMatchPattern(); String value = param.getValue(); if ( pattern.equals( "s" )){ term = value; search_parameters.put( SearchProvider.SP_SEARCH_TERM, value ); }else if ( pattern.equals( "m" )){ search_parameters.put( SearchProvider.SP_MATURE, new Boolean(value )); }else{ Debug.out( "Unrecognised search parameter '" + pattern + "=" + value + "' ignored" ); } } final String f_term = term; try{ final List<PluginResult> results = new ArrayList<PluginResult>(); final AESemaphore sem = new AESemaphore( "waiter" ); provider.search( search_parameters, new SearchObserver() { private boolean complete = false; public void resultReceived( SearchInstance search, SearchResult result ) { PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term ); synchronized( this ){ if ( complete ){ return; } results.add( p_result ); } if ( listener != null ){ listener.resultsReceived( PluginEngine.this, new Result[]{ p_result }); } synchronized( this ){ if ( absolute_max_matches >= 0 && results.size() >= absolute_max_matches ){ complete = true; sem.release(); } } } public void cancelled() { sem.release(); } public void complete() { sem.release(); } public Object getProperty( int property ) { if ( property == PR_MAX_RESULTS_WANTED ){ return( new Long( desired_max_matches )); } return( null ); } }); sem.reserve(); if ( listener != null ){ listener.resultsComplete( this ); } return((Result[])results.toArray(new Result[results.size()])); }catch( Throwable e ){ throw( new SearchException( "Search failed", e )); } } }