Package com.aelitis.azureus.plugins.remsearch

Source Code of com.aelitis.azureus.plugins.remsearch.RemSearchPluginPageGenerator

/*
* Created on Jan 27, 2010
* Created by Paul Gardner
*
* Copyright 2010 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.plugins.remsearch;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageGenerator;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
import org.json.simple.JSONObject;

import com.aelitis.azureus.core.metasearch.Engine;
import com.aelitis.azureus.core.metasearch.MetaSearchManager;
import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
import com.aelitis.azureus.core.metasearch.SearchParameter;

public class
RemSearchPluginPageGenerator
  implements TrackerWebPageGenerator
{
  private final boolean  MATURE_DEFAULT  = false;

  private final String SEARCH_PREFIX;
  private final String RESULTS_PREFIX;

  private final String  url_prefix;
  private final String  host_name;
  private final int    max_searches;
  private final int    max_results_per_engine;

  private RemSearchPluginPageGeneratorAdaptor    adapter;
 
  private Map<String,RemSearchPluginSearch>  searches = new HashMap<String, RemSearchPluginSearch>();

  private Map<Engine, RemSearchPluginEngine>  engine_map = new HashMap<Engine, RemSearchPluginEngine>();

  private long  total_searches;
  private long  total_fails;
  private long  total_engine_fails;
  private boolean  supports_async;
   
  private Random random = new Random();
 
  public
  RemSearchPluginPageGenerator(
    RemSearchPluginPageGeneratorAdaptor    _adapter,
    String                  _url_prefix,
    String                  _host_name,
    int                    _max_searches,
    int                    _max_results_per_engine,
    boolean                  _supports_async )
  {
    adapter          = _adapter;
    url_prefix        = _url_prefix;
    host_name        = _host_name;
    max_searches      = _max_searches;
    max_results_per_engine  = _max_results_per_engine;
    supports_async      = _supports_async;
   
    SEARCH_PREFIX   = _url_prefix + "/search?";
    RESULTS_PREFIX   = _url_prefix + "/get-results?";
  }
 
  protected MetaSearchManager
  getMetaSearchManager()
  {
    return( MetaSearchManagerFactory.getSingleton());
  }
 
  protected boolean
  supportsAsync()
  {
    return( supports_async );
  }
 
  public boolean
  generate(
    TrackerWebPageRequest      request,
    TrackerWebPageResponse      response )
 
    throws IOException
  {
    String  url = request.getURL();
   
    log( "HTTP request from " + request.getClientAddress());
                     
    if ( url.startsWith( SEARCH_PREFIX )){
     
      String[]  args = url.substring( SEARCH_PREFIX.length()).trim().split("&");
     
      String   term   = null;
      boolean  mature  = MATURE_DEFAULT;
     
      for (int i=0;i<args.length;i++){
       
        String[] bits = args[i].split("=");
       
        if ( bits.length != 2 ){
         
          continue;
        }
       
        String  lhs = bits[0].toLowerCase();
        String  rhs = URLDecoder.decode( bits[1], "UTF-8" );
       
        if ( lhs.equals( "q" )){
         
          term = rhs;
         
        }else if ( lhs.equals( "mature" )){
         
          mature = rhs.equalsIgnoreCase( "true" );
        }
      }
     
      if ( term == null ){
       
        term = "";
        //throw( new IOException( "search term missing" ));
      }
                 
      String  mature_str  = mature?"true":"false";
     
      String  headers    = null;
     
      String client_ip = getOriginator( request );
     
      handleSearch( client_ip, term, mature_str, headers, response );
     
      return( true );
     
    }else if ( url.startsWith( RESULTS_PREFIX )){
       
      String  params = url.substring( RESULTS_PREFIX.length()).trim();
     
      String[]  bits = params.split( "&" );
     
      String  sid = null;
      String  eid  = null;
     
      for ( String b: bits ){
     
        String[] x = b.split( "=" );
       
        if ( x[0].equals( "sid" )){
         
          sid  = x[1];
         
        }else if ( x[0].equals( "eid" )){
         
          eid = x[1];
        }
      }
     
      if ( sid == null || eid == null ){
       
        throw( new IOException( "sid or eid missing" ));
      }
     
      handleGetResult( sid, eid, response );
     
      return( true );
     
    }else{
     
      return( false );
    }
  }
 
  protected void
  handleSearch(
    String            originator,
    String            expr,
    String            mature,
    String            headers,
    TrackerWebPageResponse    response )
  {
    total_searches++;

    boolean  result_sent = false;
   
    OutputStream os = response.getOutputStream();
   
    PrintWriter pw = new PrintWriter( new OutputStreamWriter( os ));
   
    RemSearchPluginSearch search = null;

    try{
      adapter.searchReceived( originator );
       
      List<SearchParameter>  sps = new ArrayList<SearchParameter>();
           
      sps.add( new SearchParameter( "s", expr ));
     
      if ( mature != null ){
       
        sps.add( new SearchParameter( "m", mature.toString()));
      }
     
      SearchParameter[] parameters = sps.toArray( new SearchParameter[ sps.size()]);
         
      search = new RemSearchPluginSearch( this, originator, expr );

      adapter.searchCreated( search );
     
      synchronized( searches ){
       
        searches.put( search.getSID(), search );
       
        if ( searches.size() > max_searches ){
         
          throw( new IOException( "Too many active searches" ));
        }
      }
           
      String path = url_prefix;
     
      if ( path.length() == 0 ){
       
        path = "/";
      }
     
      if ( host_name != null && host_name.length() > 0 ){
     
        response.setHeader( "Set-Cookie", "JSESSIONID=" + search.getSID() + "." + host_name + "; path=" + path );
      }
     
      log( "Created: " + search.getSID() + ":  origin=" + originator );

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

      Engine[] engines = getEnginesToUse();
     
      if ( engines.length == 0 ){
       
        throw( new IOException( "No templates available for searching" ));
      }
     
      engines = getMetaSearchManager().getMetaSearch().search( engines, search, parameters, headers, context, max_results_per_engine );
       
      if ( engines.length == 0 ){
       
        throw( new IOException( "No templates available for searching" ));
      }
     
      search.setEngines( engines );
     
      JSONObject result = new JSONObject();
     
      result.put("sid", search.getSID());
         
      ArrayList<Map<String,Object>> engine_list = new ArrayList<Map<String,Object>>();
     
      for (int i=0;i<engines.length;i++){
       
        Engine  engine = engines[i];
             
        Map<String,Object> engine_map = (Map<String,Object>)new JSONObject();
       
        getEngineDetails( engine, engine_map );
     
        engine_list.add( engine_map  );   
      }
     
      result.put("engines", engine_list );
             
      result_sent = true;
     
      pw.println( "webSearch.setup(" + result.toString() + ")" );
     
      pw.flush();
     
    }catch( Throwable e ){
     
      log( "Search failed", e );
     
      total_fails++;
     
      if ( !result_sent ){
       
        JSONObject error_map = new JSONObject();
       
        if ( search != null ){
       
          error_map.put("sid", search.getSID());
        }
       
        error_map.put( "error", Debug.getNestedExceptionMessage(e));
       
        pw.println( "webSearch.failed(" + error_map.toString() + ")" );
       
        pw.flush();
      }
    }
  }
 
  protected Engine[]
   getEnginesToUse()
   {
     Engine[] engines = getMetaSearchManager().getMetaSearch().getEngines( true, true );
    
     List<Engine>  engines_to_use = new ArrayList<Engine>();
    
     synchronized( searches ){

       for ( Engine engine: engines ){
        
         LinkedList<Boolean>  history = getEngine( engine ).getHistory();
        
         if ( history.size() < 10 ){
          
           engines_to_use.add( engine );
          
         }else{
          
           int  bad    = 0;
           int  good  = 0;
          
           int  first_bad  = -1;
           int  first_good  = -1;
          
           int  pos = 0;
          
           boolean  add = false;
          
           for ( boolean success: history ){
          
             pos++;
            
             if ( success ){
              
               good++;
              
               if ( first_good == -1 ){
                
                 first_good = pos;
               }
             }else{
              
               bad++;
              
               if ( first_bad == -1 ){
                
                 first_bad = pos;
               }
             }
           }
          
             // don't let an intermittent fail stop engine use
          
           if ( first_good <= 10 ){
            
             add  = true;
            
           }else{
            
               // not looking so good
            
             int  rand;
            
             if ( first_good == -1 ){
              
               rand = history.size();
              
             }else{
              
               rand = bad;
             }
            
             add = random.nextInt( rand ) == 0;
           }
          
           if ( add ){
            
             engines_to_use.add( engine );
           }
         }
       }
     }
    
     return( engines_to_use.toArray( new Engine[ engines_to_use.size()]));
   }
  
   protected void
   handleGetResult(
     String            sid,
     String            eid,
     TrackerWebPageResponse    response )
   {
     RemSearchPluginSearch search;
    
     synchronized( searches ){

       search = searches.get( sid );
     }
    
     try{
       if ( search != null ){
        
         search.handleResultReceiver( eid, response );
          
       }else{
        
         throw( new IOException( "Search '" + sid + " not found" ));
       }           
     }catch( Throwable failure ){
      
       log( "Search " + sid + "/" + eid + ": " + Debug.getNestedExceptionMessage( failure ));
      
       Engine engine = getMetaSearchManager().getMetaSearch().getEngineByUID( eid );
      
       Map<String,Object> error_map = (Map<String,Object>)new JSONObject();
      
       error_map.put( "error", Debug.getNestedExceptionMessage( failure ));
      
       error_map.put("sid", sid);

       if ( engine != null ){
        
         getEngineDetails( engine, error_map );
        
       }else{
        
         error_map.put("id", eid );
       }
      
       try{
         PrintWriter pw = new PrintWriter( new OutputStreamWriter( response.getOutputStream(), "UTF-8" ));

         pw.println( "webSearch.engineFailed(" + error_map.toString() + ")" );
        
         pw.flush();
        
       }catch( Throwable e ){
       }
     }
   }
  
  protected void
  complete(
    RemSearchPluginSearch                search,
    List<RemSearchPluginSearch.engineResult>      ok,
    List<RemSearchPluginSearch.engineResult>      failed )
  {
    synchronized( searches ){

      if ( searches.remove( search.getSID()) == null ){
       
        return;
      }

      log( "Complete: " + search.getSID() + ", elapsed=" + search.getAge());

      if ( ok.size() == 0 ){
       
        total_fails++;
      }
     
      total_engine_fails += failed.size();
           
      for ( RemSearchPluginSearch.engineResult result: ok ){
       
        addEngineResult( result, true );
      }
     
      for ( RemSearchPluginSearch.engineResult result: failed ){
       
        addEngineResult( result, false );
      }
    }
  }
 
  public RemSearchPluginEngine[]
   getEngines()
   {
     Engine[] engines = getMetaSearchManager().getMetaSearch().getEngines( true, true );

     List<RemSearchPluginEngine> result = new ArrayList<RemSearchPluginEngine>();
    
     synchronized( searches ){
      
       for ( Engine engine: engines ){
        
         RemSearchPluginEngine e = engine_map.get( engine );
        
         if ( e == null ){
          
           e = new RemSearchPluginEngine( engine );
          
           engine_map.put( engine, e );
         }
        
         result.add( e );
       }
     }
    
     return( result.toArray( new RemSearchPluginEngine[result.size()]));
   }
  
   protected RemSearchPluginEngine
   getEngine(
     Engine    engine )
   {
     synchronized( searches ){
      
       RemSearchPluginEngine e = engine_map.get( engine );
      
       if ( e == null ){
        
         e = new RemSearchPluginEngine( engine );
        
         engine_map.put( engine, e );
       }
      
       return( e );
     }
   }
  
   protected void
   addEngineResult(
     RemSearchPluginSearch.engineResult    result,
     boolean                  ok )
   {
     getEngine( result.getEngine()).addHistory( ok, result.getSearchElapsedTime());
   }

   protected static void
   getEngineDetails(
     Engine          engine,
     Map<String,Object>    map )
   {
     map.put("name", engine.getName() );     
     map.put("id", engine.getUID());
     map.put("favicon", engine.getIcon());
     map.put("dl_link_css", engine.getDownloadLinkCSS());
     map.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]);
     map.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]);
   }
  
   protected String
   getOriginator(
     TrackerWebPageRequest    request )
   {
     String input_header       = request.getHeader();
     String lowercase_input_header  = input_header.toLowerCase();
      
     String  client_ip     = getRequestHeader( input_header, lowercase_input_header, "real-ip" );

     if ( client_ip == null ){
      
       client_ip     = getRequestHeader( input_header, lowercase_input_header, "client-ip" );
     }
    
     if ( client_ip == null ){
            
       client_ip = getRequestHeader( input_header, lowercase_input_header, "forwarded-for" )
     }
    
     if ( client_ip == null ){
      
       return( request.getClientAddress());
      
     }else{
      
       int  pos = client_ip.indexOf(',');
      
       if ( pos != -1 ){
        
         client_ip = client_ip.substring(0,pos);
       }
      
       try{
         InetAddress originator_host = InetAddress.getByName( client_ip.trim());
        
         if (   originator_host.isLinkLocalAddress() ||
             originator_host.isSiteLocalAddress() ||
             originator_host.isLoopbackAddress()){
          
           log( "Bad client IP '" + client_ip + "'" );
          
           return( request.getClientAddress());
          
         }else{
          
           return( originator_host.getHostAddress());
         }
        
       }catch( Throwable e ){
        
         log( "Bad client IP '" + client_ip + "'" );
        
         return( request.getClientAddress());
       }
     }
   }
  
   protected String
   getRequestHeader(
     String  str,
     String  lc_str,
     String  name )
   {
       // pick up "name" and "x-name"
    
     int  pos1 = lc_str.indexOf( name );
    
     if ( pos1 == -1 ){
      
       return( null );
     }
    
     int pos2 = lc_str.indexOf( "\r\n", pos1 );
    
     String entry;
    
     if ( pos2 == -1 ){
      
       entry = str.substring( pos1 );
      
     }else{
      
       entry = str.substring( pos1, pos2 );
     }
    
     int  pos = entry.indexOf(':');
    
     if ( pos == -1 ){
      
       return( null );
     }
    
     return( entry.substring( pos+1 ).trim());
   }
  
   public Map<String,RemSearchPluginSearch>
   getSearches()
   {
     synchronized( searches ){
      
       return( new HashMap<String,RemSearchPluginSearch>( searches ));
     }
   }
  
   protected Map<Engine, RemSearchPluginEngine>
   getEngineMap()
   {
     synchronized( searches ){
    
       return( new HashMap<Engine, RemSearchPluginEngine>( engine_map ));
     }
   }
  
   protected long
   getTotalSearches()
   {
     return( total_searches );
   }
  
   protected long
  getTotalSearchesFailed()
  {
    return( total_fails);
  }
 
   protected long
  getTotalEnginesFailed()
  {
    return( total_engine_fails );
 
 
   protected void
   log(
     String    str )
   {
     adapter.log( str );
   }
  
   protected void
   log(
     String    str,
     Throwable  e )
   {
     adapter.log( str, e );
   }
}
TOP

Related Classes of com.aelitis.azureus.plugins.remsearch.RemSearchPluginPageGenerator

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.