srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/locatecomponent/ShowMethodCallLocationsJob.java
changeset 0 a02c979e8dfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/locatecomponent/ShowMethodCallLocationsJob.java	Sat Jan 09 10:04:11 2010 +0530
@@ -0,0 +1,658 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package com.nokia.s60tools.appdep.locatecomponent;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.index.IIndexChangeEvent;
+import org.eclipse.cdt.core.index.IIndexChangeListener;
+import org.eclipse.cdt.core.index.IIndexManager;
+import org.eclipse.cdt.core.index.IIndexerStateEvent;
+import org.eclipse.cdt.core.index.IIndexerStateListener;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.internal.ui.search.CSearchMessages;
+import org.eclipse.cdt.internal.ui.search.PDOMSearchPatternQuery;
+import org.eclipse.cdt.internal.ui.search.PDOMSearchQuery;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.search.ui.IQueryListener;
+import org.eclipse.search.ui.ISearchQuery;
+import org.eclipse.search.ui.NewSearchUI;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.s60tools.appdep.core.AppDepSettings;
+import com.nokia.s60tools.appdep.exceptions.CacheFileDoesNotExistException;
+import com.nokia.s60tools.appdep.exceptions.CacheIndexNotReadyException;
+import com.nokia.s60tools.appdep.resources.Messages;
+import com.nokia.s60tools.appdep.ui.views.main.MainViewDataPopulator;
+import com.nokia.s60tools.appdep.util.AppDepConsole;
+import com.nokia.s60tools.sdk.SdkInformation;
+import com.nokia.s60tools.util.console.IConsolePrintUtility;
+import com.nokia.s60tools.util.debug.DbgUtility;
+import com.nokia.s60tools.util.exceptions.JobCancelledByUserException;
+import com.nokia.s60tools.util.sourcecode.CannotFoundFileException;
+import com.nokia.s60tools.util.sourcecode.IProjectFinder;
+import com.nokia.s60tools.util.sourcecode.ISourcesFinder;
+import com.nokia.s60tools.util.sourcecode.ProjectFinderFactory;
+import com.nokia.s60tools.util.sourcecode.SourceFinderFactory;
+
+/**
+ * Job for seeking possible concrete implementation of generic component name.
+ */
+// If public access to {@link PDOMSearchPatternQuery} is provided later on, the suppressing of warnings in here is no more needed.
+@SuppressWarnings("restriction")
+public class ShowMethodCallLocationsJob extends Job implements IQueryListener {
+
+	/**
+	 * Amount of steps used for the create project job progress follow-up.
+	 */
+	private static final int CREATING_PROJECT_STEPS = 5;
+	/**
+	 * Step amounts reserved for searching and indexing phase.
+	 */
+	private static final int SEARCH_AND_INDEX_STEPS = 85;
+
+	/**
+	 * Search string formed for the used search service-
+	 */
+	private String searchString = null;
+
+	/**
+	 * Project to be created for which contents the search is done.
+	 */
+	private ICProject cProject;
+
+	/**
+	 * File list defining valid search scope.
+	 */
+	private String[] filesBelongsToComponent;
+
+	/**
+	 * Job's progress monitor.
+	 */
+	private IProgressMonitor progressMonitor;
+	/**
+	 * Name of the component the method call locations are searched from.
+	 */
+	private String componentName = null;
+	
+	/**
+	 * Method name to be searched from the component.
+	 */
+	private String methodName = null;
+	/**
+	 * Name of main task that is show to the user in job progress dialog.
+	 */
+	private final String mainTaskMessage;
+
+	/**
+	 * Constructor.
+	 * @param jobName Job name 
+	 * @param mainTaskMessage Task name used for main task message
+	 * @param componentName Component name to search method calls from.
+	 * @param methodName Method name which occurrences to search from the component..
+	 * @param isUserJob if <code>true</code> job is set as user level job that prompts dialog.
+	 */
+	public ShowMethodCallLocationsJob(String jobName, String mainTaskMessage, String componentName, String methodName, boolean isUserJob) {
+		super(jobName);
+		this.mainTaskMessage = mainTaskMessage;
+		this.componentName = componentName;
+		this.methodName = methodName;
+		setUser(isUserJob);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	protected IStatus run(IProgressMonitor monitor) {
+		
+		progressMonitor = monitor;
+		IStatus status;		
+
+		try {
+		
+			progressMonitor.beginTask(mainTaskMessage,  100);
+
+			AppDepSettings settings = AppDepSettings.getActiveSettings();
+
+			SdkInformation sdkInfo = settings.getCurrentlyUsedSdk();
+			String epocRootPath = sdkInfo.getEpocRootDir(); 			
+
+			progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.SearchingFiles_SubTask_Msg") +"\n" +componentName +"'..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			
+			filesBelongsToComponent = getUsedComponentSourceFiles(settings, componentName, epocRootPath);			
+			//Limit number of files simple founding part of the method name, to decrease project files
+			setSearchString(methodName);
+									
+			checkIfCancelled();
+			progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.SearchingBldInf_SubTask_Msg")); //$NON-NLS-1$
+			progressMonitor.worked(CREATING_PROJECT_STEPS);
+			
+			//Finds and sets source files as IFile to variables
+			String bldFile = getBldInfFileName(filesBelongsToComponent);
+			
+			//If the project already exist, just executing the search
+			if(isProjectAllreadyExistingAndOpenIfClosed(bldFile, progressMonitor)){
+
+				progressMonitor.worked(SEARCH_AND_INDEX_STEPS);
+				checkIfCancelled();
+				executeSearch(searchString);
+				status = Status.OK_STATUS;
+
+			}
+			//otherwise first create a project, wait until indexed, and then execute the search
+			else{			
+				//Create a job to create project by bld.inf file if needed, and then execute search
+				progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.CreatingProjectFromBldInf_SubTask_Msg") +"\n" +bldFile +"'..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				checkIfCancelled();
+				status = createAndRunProjectCreatingJobAndExecuteSearch(bldFile, progressMonitor);				
+				progressMonitor.worked(CREATING_PROJECT_STEPS);
+
+				if(status.getSeverity() == IStatus.ERROR){
+					this.cancel();
+				}
+				else{
+					startIndexingAndSearch();					
+					status = Job.ASYNC_FINISH;
+				}
+			}
+			
+		} catch (JobCancelledByUserException e) {
+			// Job cancel because of user request 
+			this.cancel();
+			status = Status.CANCEL_STATUS;
+		}catch (Exception e) {
+			// Job cancel because of an exception 
+			e.printStackTrace();
+			String errMsg = Messages.getString("CreateProjectJob.Err_Msg") + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$ 
+			status = reportError(e, errMsg);
+			this.cancel();	
+		}
+		return status;
+	}
+
+	/**
+	 * Reports error to user.
+	 * @param e Encountered exception.
+	 * @param errMsg Error message.
+	 * @return status object.
+	 */
+	private IStatus reportError(Exception e, String errMsg) {
+		IStatus status;
+		status = new Status(
+				Status.ERROR,Platform.PI_RUNTIME,
+				Status.ERROR,errMsg, e);
+		AppDepConsole.getInstance().println(errMsg, IConsolePrintUtility.MSG_ERROR);
+		return status;
+	}
+	
+	/**
+	 * Gets all source files belonging to the given component.
+	 * @param settings Tool settings.
+	 * @param componentName component name to search method call locations from.
+	 * @param epocRootPath EPOCROOT path
+	 * @return Source file name array
+	 * @throws CannotFoundFileException
+	 * @throws CacheFileDoesNotExistException 
+	 * @throws CacheIndexNotReadyException 
+	 * @throws IOException 
+	 */
+	private String[] getUsedComponentSourceFiles(AppDepSettings settings,
+			String componentName, String epocRootPath)
+			throws CannotFoundFileException, IOException, CacheIndexNotReadyException, CacheFileDoesNotExistException {
+
+		ISourcesFinder finder = SourceFinderFactory.createSourcesFinder(AppDepConsole.getInstance());
+		String  variant = MainViewDataPopulator.getTargetPlatformIdStringForComponent(settings, componentName);
+		String build = settings.getBuildType().getBuildTypeName();		
+		String [] files = finder.findSourceFiles(componentName, variant, build, epocRootPath);
+		return files;
+	}
+
+	/**
+	 * Sets search string based on the method name.
+	 * @param methodName Method name.
+	 */
+	private void setSearchString(String methodName) {
+		String shortMethodName = methodName;
+		int start = methodName.indexOf("::"); //$NON-NLS-1$
+		if(start != -1){
+			shortMethodName = methodName.substring(start + 2);
+			
+		}
+		int end = shortMethodName.indexOf("("); //$NON-NLS-1$
+		if(end != -1){
+			shortMethodName = shortMethodName.substring(0, end);
+		}
+		
+		String longMethodNameWithOutParams;
+		if(methodName.indexOf("(") != -1){ //$NON-NLS-1$
+			longMethodNameWithOutParams = methodName.substring(0, methodName.indexOf("(")); //$NON-NLS-1$
+		}else{
+			longMethodNameWithOutParams = methodName;
+		}
+		
+		searchString  =  longMethodNameWithOutParams;// methodName;// shortMethodName;				
+	}
+
+
+	/**
+	 * Seeks all files by bld.inf file and set them to filesInBldInf 
+	 * and seeks all bld.inf to add them to bldInfFiles
+	 * @param files File name array.
+	 * @return bld.inf file path and an empty string if not found.
+	 * @throws URISyntaxException
+	 * @throws JobCancelledByUserException 
+	 */
+	private String getBldInfFileName(String[] files) throws URISyntaxException, JobCancelledByUserException {
+		//Opening project(s) where source files belongs to
+		IProjectFinder prjFinder = ProjectFinderFactory.createProjectFinder(AppDepConsole.getInstance(), progressMonitor);
+		Vector<String> bldInfFiles = new Vector<String>();
+		int errorsCount = 0;
+		for (int i = 0; i < files.length; i++) {
+			String bldInfFile;
+			try {
+				String mmpFile = prjFinder.findMMPFile(files[i]);
+				//If search is canceled, null was returned from the previously called method				
+				if(mmpFile == null){
+					checkIfCancelled();
+				}else{
+					bldInfFile = prjFinder.findBLDINFFile(mmpFile);
+					//If search is canceled, null is returned, cancellation check will be check if null is returned
+					if(bldInfFile != null){
+						bldInfFiles.add(bldInfFile);
+					}else {
+						checkIfCancelled();
+					}
+				}
+			} catch (CannotFoundFileException e) {
+				errorsCount++;//Just counting errors, really doing nothing with those but skipping if some file does not exist
+			}
+		}
+
+		// Throwing an error in case bld.inf file was not found
+		if(bldInfFiles.size() == 0){
+			String errMsg = Messages.getString("ShowMethodCallLocationsJob.CouldNotFindBldInfFile_ErrMsg") //$NON-NLS-1$
+							+ componentName
+							+ "'"; //$NON-NLS-1$
+			throw new RuntimeException(errMsg);
+		}
+		// Returning found bld.inf file path name on success
+		return bldInfFiles.elementAt(0);
+	}
+
+	/**
+	 * Checks if job was cancelled by user.
+	 * @throws JobCancelledByUserException
+	 */
+	private void checkIfCancelled() throws JobCancelledByUserException {
+		if(progressMonitor.isCanceled()){
+			throw new JobCancelledByUserException(Messages.getString("ShowMethodCallLocationsJob.JobCanceledByUser_ErrMsg")); //$NON-NLS-1$
+		}
+	}	
+	
+	/**
+	 * Creates a project.
+	 * @param bldFile bld.inf file to create project based on.
+	 * @param monitor Progress monitor object
+	 * @throws IOException 
+	 * @throws CoreException 
+	 */
+	private IStatus createAndRunProjectCreatingJobAndExecuteSearch(String bldFile, IProgressMonitor monitor) throws IOException, CoreException {		
+			
+			DEProjectUtils utils = new DEProjectUtils(AppDepConsole.getInstance());
+			CProjectJobStatus stat = utils.createProjectImpl(progressMonitor, bldFile);
+
+			this.cProject = stat.getCProject();		
+			IStatus status = stat.getStatus();
+		
+			return status;
+	}	
+	
+	/**
+	 * Checks if project already exist in workspace.
+	 * @param bldFile bld.inf file to create project based on.
+	 * @param monitor Progress monitor object
+	 * @return <code>true</code> if project is found from workspace, otherwise <code>false</code>.
+	 * @throws IOException
+	 * @throws CoreException 
+	 */
+	private boolean isProjectAllreadyExistingAndOpenIfClosed(String bldFile, IProgressMonitor monitor) throws IOException, CoreException {
+
+		IPath path = new Path(bldFile);	
+		IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(path);
+		
+		if(files.length > 0){	
+			
+			IProject prj = files[0].getProject();
+			if(prj.isOpen()){
+				return true;
+			}
+			else{
+				prj.open(monitor);				
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * Creates query and execute the search
+	 * @param searchText Search text
+	 * @throws JobCancelledByUserException 
+	 */
+	private void executeSearch(final String searchText){
+
+		progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.ExcecutingSearch_SubTask_Msg")); //$NON-NLS-1$
+		
+		final IResource[] resources = createResourcesTable();
+		
+		
+		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Starting to execute search with " +resources.length +" resources..."); //$NON-NLS-1$ //$NON-NLS-2$
+		
+			Runnable runSeach = new Runnable(){
+				public void run(){
+					try {
+						if(progressMonitor.isCanceled()){
+							cancelProgress();
+						}else{
+							ISearchQuery query = null;
+							//Query is created by CDT:s interal API
+							query = getSearchQuery(searchText, resources);
+							//Start to listen search query for noticing done() when its completed
+							NewSearchUI.addQueryListener(getIQueryListener());
+							NewSearchUI.activateSearchResultView();		
+							NewSearchUI.runQueryInBackground(query);
+						}
+					}
+					catch (Exception e) {
+						e.printStackTrace();
+						AppDepConsole.getInstance().println(Messages.getString("ShowMethodCallLocationsJob.UnableToExecuteSearch_ErrMsg_Part2") +e, AppDepConsole.MSG_ERROR); //$NON-NLS-1$
+						errorProgress(Messages.getString("ShowMethodCallLocationsJob.UnableToExecuteSearch_ErrMsg_Part1"), e);  //$NON-NLS-1$
+					}
+				}
+
+			};
+			
+			// Showing a visible message in its own thread
+			// in order not to cause invalid thread access
+			Display.getDefault().asyncExec(runSeach);									
+	}		
+	
+	/**
+	 * Get search query.
+	 * <p>
+	 * This method is using CDT:s internal API:s and if public access to {@link PDOMSearchPatternQuery}
+	 * is provided, implementation should be changed to use public implementation. 
+	 * Internal API is used, because of ready made implementation of find functions and methods references
+	 * is found in there. 
+	 * @param searchText, text to search, without parameters. Cut search String before first brace "(". 
+	 * With parameters and braces, you don't get any results. 
+	 * @param resources
+	 * @return query to give to Search engine.
+	 * @throws CoreException
+	 */
+	private ISearchQuery getSearchQuery(
+			final String searchText, final IResource[] resources)
+			throws CoreException {
+		
+		// get the list of elements for the scope
+		List<Object> elements = new ArrayList<Object>();
+		//Search from the given source files found in .map file
+		String scopeDescription = CSearchMessages.SelectionScope; 
+
+		for (int i = 0; i < resources.length; i++) {
+			elements.add(CoreModel.getDefault().create(resources[i]));
+		}
+
+		boolean isCaseSensitive = true;
+		//to Search query, we must give resources as ICElement
+		ICElement[] scope = elements.isEmpty() ? null : elements.toArray(new ICElement[elements.size()]);
+		//Same flags covers search for and limit to selections, we want to search functions/methods and only references
+		int searchFlags = PDOMSearchPatternQuery.FIND_FUNCTION | PDOMSearchPatternQuery.FIND_METHOD
+							| PDOMSearchQuery.FIND_REFERENCES;
+
+		//class to execute search is interal class provided in CDT, permission to use internal classes is granted.
+		//Parameters cannot be used wih Query, only class name(s) and method name
+		PDOMSearchPatternQuery query = new PDOMSearchPatternQuery(scope, scopeDescription, searchText, 
+				isCaseSensitive , searchFlags );		
+		
+		return query;
+	}
+	
+	/**
+	 * Creates a array containing IFile links to files that were found from map file.
+	 * @return Resource object array.
+	 */
+	private IResource[] createResourcesTable() {
+		HashSet<IFile> filesInBldInf = new HashSet<IFile>();
+		
+		for (int i = 0; i < filesBelongsToComponent.length; i++) {
+			String uriStr = filesBelongsToComponent[i].replace("\\", "/");; //$NON-NLS-1$ //$NON-NLS-2$
+			uriStr = "file://" + uriStr; //$NON-NLS-1$
+			IFile[] wsFile;
+			try {
+				wsFile = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(
+						new URI( uriStr));
+				for (int j = 0; j < wsFile.length; j++) {
+					filesInBldInf.add(wsFile[j]);							
+				}			
+			} catch (URISyntaxException e) {
+				e.printStackTrace();
+				AppDepConsole.getInstance().println(
+						Messages.getString("ShowMethodCallLocationsJob.UnableToAddFile_ErrMsg_Part1") +uriStr  //$NON-NLS-1$
+						+Messages.getString("ShowMethodCallLocationsJob.UnableToAddFile_ErrMsg_Part2") +e, AppDepConsole.MSG_ERROR); //$NON-NLS-1$
+				
+			}
+		}
+		
+		final IResource[] resources = (IFile[])filesInBldInf.toArray(new IFile[0]);
+		return resources;
+	}		
+
+	/**
+	 * Triggers indexing and searching.
+	 * @throws JobCancelledByUserException
+	 */
+	private void startIndexingAndSearch() throws JobCancelledByUserException {
+		checkIfCancelled();
+		IIndexManager indexManager = CCorePlugin.getIndexManager();		
+		boolean projectIndexed = indexManager.isProjectIndexed(cProject);
+		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Project: " +cProject.getElementName() + " indexed: " +projectIndexed + " and indexer is idling: " +indexManager.isIndexerIdle()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		
+		//If project is already indexed, search can be started right away
+		if(projectIndexed && indexManager.isIndexerIdle()){
+			executeSearch( searchString);								
+		}
+		//otherwise starting to listen indexer, and when its done, executing search
+		else{						
+			progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.StartingIndexing_SubTask_Msg")); //$NON-NLS-1$
+			IndexerStateListener listener = new IndexerStateListener();
+			indexManager.addIndexerStateListener(listener);			
+			indexManager.addIndexChangeListener(listener);
+		}
+	}	
+	
+	/**
+	 * Listener class implementation for listening indexer state changes and start
+	 * execution of search when indexer is in idle state.
+	 */
+	private class IndexerStateListener implements IIndexerStateListener, IIndexChangeListener {
+	
+		public IndexerStateListener(){
+			progressMonitor.subTask(Messages.getString("ShowMethodCallLocationsJob.IndexingProject_SubTask_Msg") +cProject.getProject().getName() +"'..."); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		
+		private Double step = new Double (new Double(SEARCH_AND_INDEX_STEPS) / new Double( filesBelongsToComponent.length));
+		private double workLeftFromPreviousStep = 0;
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.core.index.IIndexerStateListener#indexChanged(org.eclipse.cdt.core.index.IIndexerStateEvent)
+		 */
+		public void indexChanged(IIndexerStateEvent event) {
+			try {
+				boolean indexerIsIdle = event.indexerIsIdle();
+				if(indexerIsIdle){
+					execute();
+				}
+			} catch (Exception e) {
+				errorProgress(Messages.getString("ShowMethodCallLocationsJob.UnableToExecuteSearch_ErrMsg_Part1"), e); //$NON-NLS-1$
+			}
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.core.index.IIndexChangeListener#indexChanged(org.eclipse.cdt.core.index.IIndexChangeEvent)
+		 */
+		public void indexChanged(IIndexChangeEvent event) {
+
+			try{
+				if(progressMonitor.isCanceled()){
+					IIndexManager indexManager = CCorePlugin.getIndexManager();
+					removeListeners(indexManager);
+					cancelProgress();
+				}
+				
+				//Counting what's left from previous step and number of one step
+				double stepTo = workLeftFromPreviousStep + step;
+				Double stepNow = new Double(stepTo);
+				//Take out int value of this step (x from x.yyyyyy)
+				int workNow = stepNow.intValue();
+				stepNow = stepNow-workNow;
+				//put on hold what was left from this step to next step (yyyy from x.yyyy)			
+				workLeftFromPreviousStep = stepNow.doubleValue();
+				
+				progressMonitor.worked(workNow);
+				
+				//Continuing execution if indexer is idle.
+				IIndexManager indexManager = CCorePlugin.getIndexManager();
+				if(indexManager.isIndexerIdle()){
+					execute();
+				}
+			} catch (Exception e) {
+				errorProgress(Messages.getString("ShowMethodCallLocationsJob.UnableToExecuteSearch_ErrMsg_Part1"), e);//$NON-NLS-1$
+			}			
+		}
+		
+		/**
+		 * Starts execution of search 
+		 * @throws JobCancelledByUserException 
+		 */
+		private void execute() {
+			IIndexManager indexManager = CCorePlugin.getIndexManager();
+			boolean projectIndexed = indexManager.isProjectIndexed(cProject);
+			
+			DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Project indexed: " +projectIndexed  + " and indexer is idling: " +indexManager.isIndexerIdle());	//$NON-NLS-1$ //$NON-NLS-2$
+			//Search can be started if project is indexed and indexer is ready (not doing anything anymore).
+			if(projectIndexed && indexManager.isIndexerIdle()){
+				
+				removeListeners(indexManager);
+				executeSearch( searchString);								
+			}
+		}
+
+		/**
+		 * Removes listeners from index manager.
+		 * @param indexManager Index manager.
+		 */
+		private void removeListeners(IIndexManager indexManager) {
+			indexManager.removeIndexChangeListener(this);
+			indexManager.removeIndexerStateListener(this);
+		}
+		
+	}
+
+	/**
+	 * An error occurred, cancels progress and sends an error.
+	 */
+	private void errorProgress(String errMsg, Exception e) {
+		// Cancelling query
+		progressMonitor.done();
+		IStatus status = new Status(
+				Status.ERROR,Platform.PI_RUNTIME,
+				Status.ERROR,errMsg, e);		
+		done(status);
+	}	
+	
+	/**
+	 * Cancels progress without sending exception. 
+	 */
+	private void cancelProgress() {
+		// Cancelling query
+		progressMonitor.done();
+		done(Status.CANCEL_STATUS);
+	}
+
+	/**
+	 * Gets query listener interface.
+	 * @return this
+	 */
+	public IQueryListener getIQueryListener(){
+		return this;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.IQueryListener#queryAdded(org.eclipse.search.ui.ISearchQuery)
+	 */
+	public void queryAdded(ISearchQuery query) {
+		// not needed
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.IQueryListener#queryFinished(org.eclipse.search.ui.ISearchQuery)
+	 */
+	public void queryFinished(ISearchQuery query) {
+		//When query is finished, returning OK status
+		progressMonitor.done();
+        // Job has completed successfully
+	    done(Status.OK_STATUS);				
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.IQueryListener#queryRemoved(org.eclipse.search.ui.ISearchQuery)
+	 */
+	public void queryRemoved(ISearchQuery query) {
+		cancelProgress();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.IQueryListener#queryStarting(org.eclipse.search.ui.ISearchQuery)
+	 */
+	public void queryStarting(ISearchQuery query) {
+		// not needed		
+	}		
+	
+}