/* * PHEX - The pure-java Gnutella-servent. * Copyright (C) 2001 - 2008 Phex Development Group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 * * --- CVS Information --- * $Id: Search.java 4222 2008-07-10 15:44:51Z gregork $ */ package phex.query; import phex.common.URN; import phex.common.log.NLogger; import phex.download.RemoteFile; import phex.event.AsynchronousDispatcher; import phex.event.PhexEventTopics; import phex.msg.InvalidMessageException; import phex.msg.QueryMsg; import phex.msg.QueryResponseMsg; import phex.msg.QueryResponseRecord; import phex.security.AccessType; import phex.servent.Servent; //+++++++++++++++++++++++++++++++++++++++++++++++ import com.jicoma.ic.BitJoePrefs; //++++++++++++++++++++++++++++++++++++++++++++++ public abstract class Search { protected final Servent servent; /** * The time when the search was started. */ protected long startTime; /** * The dynamic query engine that actually runs the search in case * a dynamic query is used. This can attribute can be null in case * no dynamic query is used (if we are a leaf). */ protected DynamicQueryEngine queryEngine; /** * The MsgQuery object that forms the query for this search. */ protected QueryMsg queryMsg; /** * The status of the search. */ protected boolean isSearching; /** * Associated class that is able to hold search results. Access to this * should be locked by holding 'this'. */ protected SearchResultHolder searchResultHolder; protected Search( Servent servent ) { this.servent = servent; isSearching = false; searchResultHolder = new SearchResultHolder(); } public int getQueryHitCount() { return searchResultHolder.getQueryHitCount(); } /** * Tries a very basic calculation about the search progress. * @return */ public int getProgress() { if ( !isSearching ) { return 100; } if ( queryEngine != null ) { return queryEngine.getProgress(); } else { /*long currentTime = System.currentTimeMillis(); // time progress... int timeProgress = (int)(100.0 - (double)( startTime + DynamicQueryConstants.DEFAULT_QUERY_TIMEOUT - currentTime ) / (double)DynamicQueryConstants.DEFAULT_QUERY_TIMEOUT * 100.0 ); // return the max of all these return Math.min( timeProgress, 100);*/ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ long currentTime = System.currentTimeMillis(); int timeProgress = (int)(100.0 - (double)( startTime + BitJoePrefs.StopTimeSetting.get() - currentTime ) / (double)BitJoePrefs.StopTimeSetting.get()* 100.0 ); return Math.min( timeProgress, 100); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } } public boolean isSearching() { return isSearching; } public void checkForSearchTimeout( long currentTime ) { if ( queryEngine != null ) { if ( queryEngine.isQueryFinished() ) { stopSearching(); } } /*else if ( currentTime > startTime + DynamicQueryConstants.DEFAULT_QUERY_TIMEOUT ) { // timed out stop search stopSearching(); }*/ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ else if ( currentTime > startTime + BitJoePrefs.StopTimeSetting.get()) { stopSearching(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } public void startSearching( final QueryManager queryService ) { AsynchronousDispatcher.invokeLater( new Runnable() { public void run() { startTime = System.currentTimeMillis(); // set the creation time just before we send the query this // will prevent the query to timeout before it could be send queryMsg.setCreationTime( startTime ); NLogger.debug( Search.class, "Sending Query " + queryMsg ); queryEngine = queryService.sendMyQuery( queryMsg ); isSearching = true; fireSearchStarted(); } } ); } public void stopSearching() { if ( !isSearching ) {// already stopped return; } isSearching = false; if ( queryEngine != null ) { queryEngine.stopQuery(); } fireSearchStoped(); } /** * Used by subclasses to check if the record is valid. In this case a * security check is done on the record URN. * @param record * @return true if valid, false otherwise. */ protected boolean isResponseRecordValid( QueryResponseRecord record ) { // REWORK maybe we should move the altloc security check // from GGEPExtension.parseAltExtensionData to here to? // MERGE with FilteredQueryResponseMonitor.isResponseRecordValid() URN urn = record.getURN(); if ( urn != null && servent.getSecurityService().controlUrnAccess( urn ) != AccessType.ACCESS_GRANTED ) { NLogger.debug( Search.class, "Record contains blocked URN: " + urn.getAsString() ); return false; } return true; } public abstract void processResponse( QueryResponseMsg msg ) throws InvalidMessageException; ///////////////////// START event handling methods //////////////////////// protected void fireSearchStarted() { SearchDataEvent searchChangeEvent = new SearchDataEvent( this, SearchDataEvent.SEARCH_STARTED ); fireSearchChangeEvent( searchChangeEvent ); } protected void fireSearchStoped() { SearchDataEvent searchChangeEvent = new SearchDataEvent( this, SearchDataEvent.SEARCH_STOPED ); fireSearchChangeEvent( searchChangeEvent ); } public void fireSearchChanged() { SearchDataEvent searchChangeEvent = new SearchDataEvent( this, SearchDataEvent.SEARCH_CHANGED ); fireSearchChangeEvent( searchChangeEvent ); } protected void fireSearchHitsAdded( RemoteFile[] newHits ) { SearchDataEvent searchChangeEvent = new SearchDataEvent( this, SearchDataEvent.SEARCH_HITS_ADDED, newHits ); fireSearchChangeEvent( searchChangeEvent ); } private void fireSearchChangeEvent( final SearchDataEvent searchChangeEvent ) { servent.getEventService().publish( PhexEventTopics.Search_Data, searchChangeEvent ); } ///////////////////// END event handling methods //////////////////////// }