blob: f499be81b203750098c5508fec59311d542f4b34 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.ptp.rdt.server.dstore.core;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCProjectNature;
import org.eclipse.cdt.core.CProjectNature;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ICContainer;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IParent;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.parser.ParserMessages;
import org.eclipse.cdt.utils.EFSExtensionManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.dstore.core.model.DE;
import org.eclipse.dstore.core.model.DataElement;
import org.eclipse.dstore.core.model.DataStore;
import org.eclipse.dstore.core.model.DataStoreResources;
import org.eclipse.dstore.core.model.DataStoreSchema;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ptp.internal.rdt.core.IRemoteIndexerInfoProvider;
import org.eclipse.ptp.internal.rdt.core.Serializer;
import org.eclipse.ptp.internal.rdt.core.callhierarchy.CalledByResult;
import org.eclipse.ptp.internal.rdt.core.callhierarchy.CallsToResult;
import org.eclipse.ptp.internal.rdt.core.contentassist.Proposal;
import org.eclipse.ptp.internal.rdt.core.contentassist.RemoteContentAssistInvocationContext;
import org.eclipse.ptp.internal.rdt.core.includebrowser.IIndexIncludeValue;
import org.eclipse.ptp.internal.rdt.core.index.RemoteIndexerProgress;
import org.eclipse.ptp.internal.rdt.core.index.RemoteIndexerTask;
import org.eclipse.ptp.internal.rdt.core.miners.CDTMiner;
import org.eclipse.ptp.internal.rdt.core.model.Scope;
import org.eclipse.ptp.internal.rdt.core.navigation.OpenDeclarationResult;
import org.eclipse.ptp.internal.rdt.core.search.RemoteSearchMatch;
import org.eclipse.ptp.internal.rdt.core.search.RemoteSearchQuery;
import org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem;
import org.eclipse.ptp.internal.rdt.core.typehierarchy.THGraph;
import org.eclipse.ptp.rdt.core.RDTLog;
import org.eclipse.ptp.rdt.core.resources.RemoteNature;
import org.eclipse.ptp.rdt.core.serviceproviders.IIndexServiceProvider;
import org.eclipse.ptp.rdt.ui.messages.Messages;
import org.eclipse.ptp.rdt.ui.subsystems.ProjectChangeListener;
import org.eclipse.ptp.rdt.ui.subsystems.StatusMonitor;
import org.eclipse.ptp.remote.launch.core.RemoteServerManager;
import org.eclipse.ptp.services.core.IService;
import org.eclipse.ptp.services.core.IServiceConfiguration;
import org.eclipse.ptp.services.core.IServiceProvider;
import org.eclipse.ptp.services.core.ServiceModelManager;
/**
* An Remote Tools subsystem which is used to provide C/C++ indexing services
* from a Miner running on a remote host. <strong>EXPERIMENTAL</strong>. This
* class or interface has been added as part of a work in progress. There is no
* guarantee that this API will work or that it will remain the same. Please do
* not use this API without consulting with the RDT team.
*
* @author crecoskie
*
*/
public class RemoteToolsCIndexSubsystem implements ICIndexSubsystem {
private final Map<IProject, String> fInitializedProjects = new HashMap<IProject, String>();
private final ProjectChangeListener fProjectOpenListener = new ProjectChangeListener(this);
private final RemoteToolsCIndexServiceProvider fProvider;
private final List<String> fErrorMessages = new ArrayList<String>();
private DStoreServer fDStoreServer = null;
public RemoteToolsCIndexSubsystem(RemoteToolsCIndexServiceProvider provider) {
fProvider = provider;
ResourcesPlugin.getWorkspace().addResourceChangeListener(fProjectOpenListener);
generateErrorMessages();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* checkAllProjects(org.eclipse.core.runtime.IProgressMonitor)
*/
public void checkAllProjects(IProgressMonitor monitor) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot workspaceRoot = workspace.getRoot();
for (IProject project : workspaceRoot.getProjects()) {
// is the project open? if not, there's not much we can do
if (!project.isOpen())
continue;
// is this an RDT C/C++ project?
// check the project natures... we care about the project if it has
// both the remote nature and
// at least one of the CDT natures
try {
if (!project.hasNature(RemoteNature.REMOTE_NATURE_ID)
|| !(project.hasNature(CProjectNature.C_NATURE_ID) || project.hasNature(CCProjectNature.CC_NATURE_ID)))
continue;
checkProject(project, monitor);
} catch (Throwable e) {
RDTLog.logError(e);
}
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#checkProject
* (org.eclipse.core.resources.IProject,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public void checkProject(IProject project, IProgressMonitor monitor) {
if (project == null) {
return;
}
if (fInitializedProjects.containsKey(project)) {
String projectURI = project.getLocationURI().toString();
if (projectURI.equals(fInitializedProjects.get(project))) {
return;
} else {
// the project's uri is changed, so we need to initialize it
// again.
// no need to unregister its scope, since initializeScope
// handles it.
}
}
try {
initializeScope(project, monitor);
} catch (CoreException e) {
RDTLog.logError(e);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* computeCompletionProposals(org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.ptp.internal.rdt.core.contentassist.
* RemoteContentAssistInvocationContext,
* org.eclipse.cdt.core.model.ITranslationUnit)
*/
public List<Proposal> computeCompletionProposals(Scope scope, RemoteContentAssistInvocationContext context,
ITranslationUnit unit) {
checkAllProjects(new NullProgressMonitor());
String path = EFSExtensionManager.getDefault().getPathFromURI(unit.getLocationURI());
DataStore dataStore = getDataStore(null);
if (dataStore == null) {
return Collections.emptyList();
}
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(),
CDTMiner.C_CONTENT_ASSIST_COMPUTE_PROPOSALS);
if (queryCmd == null) {
return Collections.emptyList();
}
NullProgressMonitor monitor = new NullProgressMonitor();
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
ArrayList<Object> args = new ArrayList<Object>();
// need to know the scope
DataElement dataElement = dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR, scope.getName());
args.add(dataElement);
// invocation context
args.add(createSerializableElement(dataStore, context));
// translation unit
args.add(createSerializableElement(dataStore, unit));
// path to translation unit
dataElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, path);
args.add(dataElement);
// execute the command
DataElement status = dataStore.command(queryCmd, args, dataStore.getDescriptorRoot());
try {
smonitor.waitForUpdate(status, monitor);
} catch (Exception e) {
RDTLog.logError(e);
}
DataElement element = status.get(0);
String data = element.getName();
try {
Object result = Serializer.deserialize(data);
if (result == null || !(result instanceof List<?>)) {
return Collections.emptyList();
}
return (List<Proposal>) result;
} catch (IOException e) {
RDTLog.logError(e);
} catch (ClassNotFoundException e) {
RDTLog.logError(e);
}
return Collections.emptyList();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* computeTypeGraph(org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ICElement,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public THGraph computeTypeGraph(Scope scope, ICElement input, IProgressMonitor monitor) {
String path = EFSExtensionManager.getDefault().getPathFromURI(input.getLocationURI());
Object result = sendRequest(CDTMiner.C_TYPE_HIERARCHY_COMPUTE_TYPE_GRAPH,
new Object[] { scope, getHostName(), input, path }, monitor);
if (result == null) {
return new THGraph();
}
return (THGraph) result;
}
/**
* Shutdown and clean up the subsystem
*/
public void dispose() {
if (fDStoreServer != null) {
fDStoreServer.cancel();
}
ResourcesPlugin.getWorkspace().removeResourceChangeListener(fProjectOpenListener);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#findInclude
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.index.IIndexFileLocation, java.lang.String, int,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IIndexIncludeValue findInclude(Scope scope, IIndexFileLocation location, String name, int offset,
IProgressMonitor monitor) {
Object result = sendRequest(CDTMiner.C_INCLUDES_FIND_INCLUDE,
new Object[] { scope, getHostName(), location, name, offset }, monitor);
if (result == null) {
return null;
}
return (IIndexIncludeValue) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#findIncludedBy
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.index.IIndexFileLocation,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IIndexIncludeValue[] findIncludedBy(Scope scope, IIndexFileLocation location, IProgressMonitor monitor) {
Object result = sendRequest(CDTMiner.C_INCLUDES_FIND_INCLUDED_BY, new Object[] { scope, getHostName(), location }, monitor);
if (result == null) {
return new IIndexIncludeValue[0];
}
return (IIndexIncludeValue[]) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#findIncludesTo
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.index.IIndexFileLocation,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IIndexIncludeValue[] findIncludesTo(Scope scope, IIndexFileLocation location, IProgressMonitor monitor) {
Object result = sendRequest(CDTMiner.C_INCLUDES_FIND_INCLUDES_TO, new Object[] { scope, getHostName(), location }, monitor);
if (result == null) {
return new IIndexIncludeValue[0];
}
return (IIndexIncludeValue[]) result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* findTypeHierarchyInput(org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ICElement)
*/
public ICElement[] findTypeHierarchyInput(Scope scope, ICElement memberInput) {
String path = EFSExtensionManager.getDefault().getPathFromURI(memberInput.getLocationURI());
Object result = sendRequest(CDTMiner.C_TYPE_HIERARCHY_FIND_INPUT1,
new Object[] { scope, getHostName(), memberInput, path }, null);
if (result == null) {
return new ICElement[] { null, null };
}
return (ICElement[]) result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* findTypeHierarchyInput(org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ITranslationUnit, int, int)
*/
public ICElement[] findTypeHierarchyInput(Scope scope, ITranslationUnit unit, int selectionStart, int selectionLength) {
String path = EFSExtensionManager.getDefault().getPathFromURI(unit.getLocationURI());
Object result = sendRequest(CDTMiner.C_TYPE_HIERARCHY_FIND_INPUT2, new Object[] { scope, getHostName(), unit,
new Integer(selectionStart), new Integer(selectionLength) }, null);
if (result == null) {
return new ICElement[] { null, null };
}
return (ICElement[]) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#getCallees
* (org.eclipse.ptp.internal.rdt.core.model.Scope, java.lang.String,
* java.lang.String, int, int, org.eclipse.core.runtime.IProgressMonitor)
*/
public CallsToResult getCallees(Scope scope, ICElement subject, IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.6") + subject, 100); //$NON-NLS-1$
String path = EFSExtensionManager.getDefault().getPathFromURI(subject.getLocationURI());
Object result = sendRequest(CDTMiner.C_CALL_HIERARCHY_GET_CALLS, new Object[] { scope, getHostName(), subject, path }, null);
if (result == null) {
return new CallsToResult();
}
return (CallsToResult) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#getCallers
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ICElement,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public CalledByResult getCallers(Scope scope, ICElement subject, IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.5") + subject, 100); //$NON-NLS-1$
String path = EFSExtensionManager.getDefault().getPathFromURI(subject.getLocationURI());
Object result = sendRequest(CDTMiner.C_CALL_HIERARCHY_GET_CALLERS, new Object[] { scope, getHostName(), subject, path },
null);
if (result == null) {
return new CalledByResult();
}
return (CalledByResult) result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* getCHDefinitions(org.eclipse.ptp.internal.rdt.core.model.Scope,
* java.lang.String, java.lang.String, int, int,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public ICElement[] getCHDefinitions(Scope scope, ICElement subject, IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.7") + subject, 100); //$NON-NLS-1$
String path = EFSExtensionManager.getDefault().getPathFromURI(subject.getLocationURI());
Object result = sendRequest(CDTMiner.C_CALL_HIERARCHY_GET_DEFINITIONS_FROM_ELEMENT, new Object[] { scope, getHostName(),
subject, path }, null);
if (result == null) {
return new ICElement[0];
}
return (ICElement[]) result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#
* getCHDefinitions(org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ITranslationUnit, int, int,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public ICElement[] getCHDefinitions(Scope scope, ITranslationUnit unit, int selectionStart, int selectionLength,
IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.7") + unit, 100); //$NON-NLS-1$
String path = EFSExtensionManager.getDefault().getPathFromURI(unit.getLocationURI());
Object result = sendRequest(CDTMiner.C_CALL_HIERARCHY_GET_DEFINITIONS_FROM_WORKING_COPY, new Object[] { scope,
getHostName(), unit, path, selectionStart, selectionLength }, null);
if (result == null) {
return new ICElement[0];
}
return (ICElement[]) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#getModel
* (org.eclipse.cdt.core.model.ITranslationUnit,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public ITranslationUnit getModel(ITranslationUnit unit, IProgressMonitor monitor) {
Object result = sendRequest(CDTMiner.C_MODEL_BUILDER, new Object[] { unit }, monitor);
if (result == null) {
return null;
}
// the working copy
return (ITranslationUnit) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#indexDelta
* (org.eclipse.ptp.internal.rdt.core.model.Scope, java.util.List,
* java.util.List, java.util.List,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus indexDelta(Scope scope, IRemoteIndexerInfoProvider provider, List<ICElement> newElements,
List<ICElement> changedElements, List<ICElement> deletedElements, IProgressMonitor monitor, RemoteIndexerTask task) {
removeProblems(scope);
DataStore dataStore = getDataStore(monitor);
if (dataStore == null)
return Status.OK_STATUS;
DataElement result = getDataStore(monitor).createObject(null, CDTMiner.T_INDEX_STATUS_DESCRIPTOR, "index"); //$NON-NLS-1$
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
int workCount = newElements.size() + changedElements.size();
monitor.beginTask("Incrementally Indexing...", workCount); //$NON-NLS-1$
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(), CDTMiner.C_INDEX_DELTA);
if (queryCmd != null) {
ArrayList<Object> args = new ArrayList<Object>();
args.add(dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR, scope.getName()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getScheme()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getRootPath()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getMappedPath()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getHost()));
String serializedProvider = null;
try {
serializedProvider = Serializer.serialize(provider);
} catch (IOException e) {
RDTLog.logError(e);
}
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_SCANNER_INFO_PROVIDER, serializedProvider));
for (ICElement element : newElements) {
String remotePath = convertURIToRemotePath(element.getLocationURI());
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_DELTA_ADDED, remotePath));
}
for (ICElement element : changedElements) {
String remotePath = convertURIToRemotePath(element.getLocationURI());
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_DELTA_CHANGED, remotePath));
}
for (ICElement element : deletedElements) {
String remotePath = convertURIToRemotePath(element.getLocationURI());
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_DELTA_REMOVED, remotePath));
}
DataElement status = dataStore.command(queryCmd, args, result);
// poll for progress information until the operation is done or
// canceled
while (!status.getName().equals("done") && !status.getName().equals("cancelled") && !monitor.isCanceled()) { //$NON-NLS-1$ //$NON-NLS-2$
RemoteIndexerProgress progress = getIndexerProgress(status);
task.updateProgressInformation(progress);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
RDTLog.logError(e);
}
}
try {
try {
smonitor.waitForUpdate(status, monitor);
} catch (InterruptedException e) { // Canceled
if (monitor.isCanceled())
cancelOperation(status.getParent());
}
} catch (Exception e) {
RDTLog.logError(e);
}
if (status.getName().equals("done") || status.getName().equals("cancelled") || monitor.isCanceled()) { //$NON-NLS-1$//$NON-NLS-2$
for (int i = 0; i < status.getNestedSize(); i++) {
DataElement element = status.get(i);
if (element != null && CDTMiner.T_INDEXING_ERROR.equals(element.getType())) {
// Error occurred on the server
String message = element.getAttribute(DE.A_NAME) + ". "; //$NON-NLS-1$
for (int j = 0; j < fErrorMessages.size(); j++) {
if (message.indexOf(fErrorMessages.get(j)) > 0) {
String msg = reportProblem(scope, message);
RDTLog.logWarning(msg);
}
}
}
}
}
monitor.done();
}
return Status.OK_STATUS;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#isIndexed
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.index.IIndexFileLocation,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public boolean isIndexed(Scope scope, IIndexFileLocation location, IProgressMonitor monitor) {
Object result = sendRequest(CDTMiner.C_INCLUDES_IS_INDEXED, new Object[] { scope, getHostName(), location }, monitor);
if (result != null) {
return Boolean.parseBoolean(result.toString());
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#moveIndexFile
* (java.lang.String, java.lang.String,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public String moveIndexFile(String scopeName, String newIndexLocation, IProgressMonitor monitor) {
String actualLocation = sendRequestStringResult(CDTMiner.C_MOVE_INDEX_FILE, new Object[] { scopeName, newIndexLocation },
monitor);
return actualLocation;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#openDeclaration
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.cdt.core.model.ITranslationUnit, java.lang.String, int, int,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public OpenDeclarationResult openDeclaration(Scope scope, ITranslationUnit unit, String selectedText, int selectionStart,
int selectionLength, IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.9"), 100); //$NON-NLS-1$
String path = EFSExtensionManager.getDefault().getPathFromURI(unit.getLocationURI());
Object result = sendRequest(CDTMiner.C_NAVIGATION_OPEN_DECLARATION, new Object[] { scope, unit, path, selectedText,
selectionStart, selectionLength }, monitor);
if (result == null)
return OpenDeclarationResult.failureUnexpectedError();
return (OpenDeclarationResult) result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#registerScope
* (org.eclipse.ptp.internal.rdt.core.model.Scope, java.lang.String[],
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus registerScope(Scope scope, List<ICElement> elements, String configLocation, IProgressMonitor monitor) {
DataStore dataStore = getDataStore(monitor);
if (dataStore != null) {
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
monitor.beginTask(Messages.getString("RSECIndexSubsystem.3"), 100); //$NON-NLS-1$
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(), CDTMiner.C_SCOPE_REGISTER);
if (queryCmd != null) {
ArrayList<Object> args = new ArrayList<Object>();
// need to know the scope
DataElement scopeElement = dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR, scope.getName());
args.add(scopeElement);
// scheme for scope
DataElement dataElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getScheme());
args.add(dataElement);
// host
DataElement hostElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getHost());
args.add(hostElement);
// root path for scope on server
DataElement rootPath = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getRootPath());
args.add(rootPath);
// mapped path for scope on local machine
DataElement mappedPath = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getMappedPath());
args.add(mappedPath);
// need to know where to find the pdom file for the scope
DataElement configElement = dataStore.createObject(null, CDTMiner.T_SCOPE_CONFIG_LOCATION, configLocation);
args.add(configElement);
// add in the filenames
for (ICElement element : elements) {
addElement(dataStore, args, element);
}
// execute the command
DataElement status = dataStore.command(queryCmd, args, dataStore.getDescriptorRoot());
try {
smonitor.waitForUpdate(status, monitor);
} catch (Exception e) {
RDTLog.logError(e);
}
}
}
return Status.OK_STATUS;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#reindexScope
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.ptp.internal.rdt.core.IRemoteIndexerInfoProvider,
* org.eclipse.core.runtime.IProgressMonitor,
* org.eclipse.ptp.internal.rdt.core.index.RemoteIndexerTask)
*/
public IStatus reindexScope(Scope scope, IRemoteIndexerInfoProvider provider, String indexLocation, IProgressMonitor monitor,
RemoteIndexerTask task) {
removeProblems(scope);
DataStore dataStore = getDataStore(monitor);
if (dataStore == null)
return Status.OK_STATUS;
DataElement result = getDataStore(monitor).createObject(null, CDTMiner.T_INDEX_STATUS_DESCRIPTOR, "index"); //$NON-NLS-1$
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
monitor.beginTask("Rebuilding indexing...", 100); //$NON-NLS-1$
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(), CDTMiner.C_INDEX_REINDEX);
if (queryCmd != null) {
ArrayList<Object> args = new ArrayList<Object>();
args.add(dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR, scope.getName()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getScheme()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getRootPath()));
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, scope.getMappedPath()));
args.add(dataStore.createObject(null, CDTMiner.T_SCOPE_CONFIG_LOCATION, indexLocation));
String serializedProvider = null;
try {
serializedProvider = Serializer.serialize(provider);
} catch (IOException e) {
RDTLog.logError(e);
}
args.add(dataStore.createObject(null, CDTMiner.T_INDEX_SCANNER_INFO_PROVIDER, serializedProvider));
DataElement status = dataStore.command(queryCmd, args, result);
// poll for progress information until the operation is done or
// canceled
while (!status.getName().equals("done") && !status.getName().equals("cancelled") && !monitor.isCanceled()) { //$NON-NLS-1$ //$NON-NLS-2$
RemoteIndexerProgress progress = getIndexerProgress(status);
task.updateProgressInformation(progress);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
RDTLog.logError(e);
}
}
try {
try {
smonitor.waitForUpdate(status, monitor);
} catch (InterruptedException e) { // Canceled
if (monitor.isCanceled())
cancelOperation(status.getParent());
}
} catch (Exception e) {
RDTLog.logError(e);
}
if (status.getName().equals("done") || status.getName().equals("cancelled") || monitor.isCanceled()) { //$NON-NLS-1$//$NON-NLS-2$
for (int i = 0; i < status.getNestedSize(); i++) {
DataElement element = status.get(i);
if (element != null && CDTMiner.T_INDEXING_ERROR.equals(element.getType())) {
// Error occurred on the server
String message = element.getAttribute(DE.A_NAME) + ". "; //$NON-NLS-1$
for (int j = 0; j < fErrorMessages.size(); j++) {
if (message.indexOf(fErrorMessages.get(j)) > 0) {
String msg = reportProblem(scope, message);
RDTLog.logWarning(msg);
}
}
}
}
}
monitor.done();
}
return Status.OK_STATUS;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#removeIndexFile
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus removeIndexFile(Scope scope, IProgressMonitor monitor) {
sendRequest(CDTMiner.C_REMOVE_INDEX_FILE, new Object[] { scope }, monitor);
return Status.OK_STATUS;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#runQuery
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.ptp.internal.rdt.core.search.RemoteSearchQuery,
* org.eclipse.core.runtime.IProgressMonitor)
*/
@SuppressWarnings("unchecked")
public List<RemoteSearchMatch> runQuery(Scope scope, RemoteSearchQuery query, IProgressMonitor monitor) {
monitor.beginTask(Messages.getString("RSECIndexSubsystem.8") + query.getScopeDescription(), 100); //$NON-NLS-1$
Object result = sendRequest(CDTMiner.C_SEARCH_RUN_QUERY, new Object[] { scope, getHostName(), query }, null);
if (result == null) {
return Collections.emptyList();
}
return (List<RemoteSearchMatch>) result;
}
/**
* @param requestType
* @param arguments
* @param monitor
* @return
*/
public Object sendRequest(String requestType, Object[] arguments, IProgressMonitor monitor) {
return sendRequest(requestType, arguments, monitor, true);
}
/**
* @param requestType
* @param arguments
* @param monitor
* @return
*/
public String sendRequestStringResult(String requestType, Object[] arguments, IProgressMonitor monitor) {
return (String) sendRequest(requestType, arguments, monitor, false);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.internal.rdt.core.subsystems.ICIndexSubsystem#unregisterScope
* (org.eclipse.ptp.internal.rdt.core.model.Scope,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus unregisterScope(Scope scope, IProgressMonitor monitor) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(scope.getName());
fInitializedProjects.remove(project);
DataStore dataStore = getDataStore(monitor);
if (dataStore != null) {
// DataElement result = dataStore.createObject(null,
// CDTMiner.T_INDEX_STATUS_DESCRIPTOR, name);
// DataElement statusDescriptor =
// dataStore.createObjectDescriptor(null,
// CDTMiner.T_INDEX_STATUS_DESCRIPTOR);
// result.setDescriptor(statusDescriptor);
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
monitor.beginTask(Messages.getString("RSECIndexSubsystem.4"), 100); //$NON-NLS-1$
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(), CDTMiner.C_SCOPE_UNREGISTER);
if (queryCmd != null) {
ArrayList<Object> args = new ArrayList<Object>();
// need to know the scope
DataElement scopeElement = dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR, scope.getName());
args.add(scopeElement);
// execute the command
// DataElement status = dataStore.command(queryCmd,
// dataStore.getDescriptorRoot(), true);
DataElement status = dataStore.command(queryCmd, args, dataStore.getDescriptorRoot());
try {
smonitor.waitForUpdate(status, monitor);
} catch (Exception e) {
RDTLog.logError(e);
}
}
}
return Status.OK_STATUS;
}
private DataElement createSerializableElement(DataStore dataStore, Object object) {
try {
String serialized = Serializer.serialize(object);
return dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, serialized);
} catch (IOException e) {
RDTLog.logError(e);
return null;
}
}
private void generateErrorMessages() {
// fErrorMessages.add(ParserMessages.getFormattedString("ScannerProblemFactory.error.preproc.inclusionNotFound", "")); //$NON-NLS-1$ //$NON-NLS-2$
// fErrorMessages.add(ParserMessages.getFormattedString("ScannerProblemFactory.error.preproc.definitionNotFound", "")); //$NON-NLS-1$ //$NON-NLS-2$
fErrorMessages.add("Unresolved inclusion:"); //$NON-NLS-1$
fErrorMessages.add("Macro definition not found:"); //$NON-NLS-1$
}
private RemoteIndexerProgress getIndexerProgress(DataElement status) {
int num = status.getNestedSize();
if (num > 0) {
boolean foundProgressInfo = false;
int counter = 1;
DataElement element = null;
while (!foundProgressInfo && counter <= num) {
element = status.get(num - counter);
if (element != null && CDTMiner.T_INDEXER_PROGRESS_INFO.equals(element.getType())) {
foundProgressInfo = true;
}
counter++;
}
if (element != null && CDTMiner.T_INDEXER_PROGRESS_INFO.equals(element.getType())) {
String data = element.getName();
try {
Object result = Serializer.deserialize(data);
if (result == null || !(result instanceof RemoteIndexerProgress)) {
return null;
}
RemoteIndexerProgress info = (RemoteIndexerProgress) result;
return info;
} catch (IOException e) {
RDTLog.logError(e);
} catch (ClassNotFoundException e) {
RDTLog.logError(e);
}
}
}
return null;
}
private void initializeScope(IProject project, IProgressMonitor monitor) throws CoreException {
// get the service model configuration for this project
final ServiceModelManager serviceModelManager = ServiceModelManager.getInstance();
IServiceConfiguration config = serviceModelManager.getActiveConfiguration(project);
// is the indexing service associated with our service provider?
IService service = serviceModelManager.getService(RemoteToolsCIndexServiceProvider.SERVICE_ID);
IServiceProvider provider = config.getServiceProvider(service);
// if so, initialize a scope for the project consisting of all
// its translation units
final List<ICElement> cElements = new LinkedList<ICElement>();
IResourceVisitor fileCollector = new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile) {
// add the path
ITranslationUnit tu = CoreModelUtil.findTranslationUnit((IFile) resource);
if (tu != null) {
cElements.add(tu);
return false;
}
}
return true;
}
};
// collect the translation units
project.accept(fileCollector);
String configLocation = ((IIndexServiceProvider) provider).getIndexLocation();
Scope scope = new Scope(project);
// unregister the scope if there already is one
unregisterScope(scope, monitor);
// register the new scope
registerScope(scope, cElements, configLocation, monitor);
String projectURI = project.getLocationURI().toString();
fInitializedProjects.put(project, projectURI);
}
/**
* Sends a request in a set format of arguments.
*
* @param deserializeResult
* If true the result will be deserialized, if false it will
* treat the result as a raw string.
*/
private Object sendRequest(String requestType, Object[] arguments, IProgressMonitor monitor, boolean deserializeResult) {
DataStore dataStore = getDataStore(monitor);
if (dataStore == null)
return null;
DataElement queryCmd = dataStore.localDescriptorQuery(dataStore.getDescriptorRoot(), requestType);
if (queryCmd == null)
return null;
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
ArrayList<Object> args = new ArrayList<Object>();
for (Object argument : arguments) {
if (argument instanceof Scope) {
DataElement dataElement = dataStore.createObject(null, CDTMiner.T_SCOPE_SCOPENAME_DESCRIPTOR,
((Scope) argument).getName());
args.add(dataElement);
dataElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, ((Scope) argument).getScheme());
args.add(dataElement);
// root path for scope on server
DataElement rootPath = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR,
((Scope) argument).getRootPath());
args.add(rootPath);
// path mappings for scope
DataElement pathElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR,
((Scope) argument).getMappedPath());
args.add(pathElement);
} else if (argument instanceof String) {
DataElement dataElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, (String) argument);
args.add(dataElement);
} else if (argument instanceof Integer || argument instanceof Boolean || argument instanceof Character
|| argument instanceof Double || argument instanceof Float) {
DataElement dataElement = dataStore.createObject(null, CDTMiner.T_INDEX_STRING_DESCRIPTOR, argument.toString());
args.add(dataElement);
} else {
args.add(createSerializableElement(dataStore, argument));
}
}
// execute the command
DataElement status = dataStore.command(queryCmd, args, dataStore.getDescriptorRoot());
try {
monitor = monitor == null ? new NullProgressMonitor() : monitor;
smonitor.waitForUpdate(status, monitor);
} catch (Exception e) {
RDTLog.logError(e);
}
DataElement element = status.get(0);
if (element == null) {
return null;
}
if (DataStoreResources.model_error.equals(element.getType())) {
// Error occurred on the server
RDTLog.logError(status.getValue()); // prints the server error stack
// trace to the log
return null;
}
String data = element.getName();
if (!deserializeResult)
return data;
try {
Object result = Serializer.deserialize(data);
return result;
} catch (IOException e) {
RDTLog.logError(e);
} catch (ClassNotFoundException e) {
RDTLog.logError(e);
}
return null;
}
/**
* @param dataStore
* @param args
* @param filePath
* @param element
*/
protected void addElement(DataStore dataStore, ArrayList<Object> args, ICElement element) {
String filePath = null;
// if it's a translation unit, we can just add it
if (element instanceof ITranslationUnit) {
filePath = convertURIToRemotePath(element.getLocationURI());
}
else {
// if it's a container or a project, add the child elements
if (element instanceof ICContainer || element instanceof ICProject) {
try {
ICElement[] children = ((IParent) element).getChildren();
for (int k = 0; k < children.length; k++)
addElement(dataStore, args, children[k]);
} catch (CModelException e) {
RDTLog.logError(e);
}
}
}
if (filePath != null) {
DataElement fileElement = dataStore.createObject(null, CDTMiner.T_INDEX_FILENAME_DESCRIPTOR, filePath);
args.add(fileElement);
}
}
protected void cancelOperation(DataElement command) {
// send cancel command
DataStore dataStore = command.getDataStore();
DataElement cmdDescriptor = command.getDescriptor();
DataElement cancelDescriptor = dataStore.localDescriptorQuery(cmdDescriptor, DataStoreSchema.C_CANCEL);
if (cancelDescriptor != null) {
dataStore.command(cancelDescriptor, command);
}
}
protected URI convertRemotePathToURI(String path) throws URISyntaxException {
return fProvider.getConnection().getRemoteServices().getFileManager(fProvider.getConnection()).toURI(path);
}
protected String convertURIToRemotePath(URI locationURI) {
String path = EFSExtensionManager.getDefault().getPathFromURI(locationURI);
return path;
}
protected String getHostName() {
return fProvider.getConnectionName();
}
protected DataStore getDataStore(IProgressMonitor monitor) {
SubMonitor subMon = SubMonitor.convert(monitor, 10);
try {
if (fDStoreServer == null) {
fDStoreServer = (DStoreServer) RemoteServerManager.getServer(DStoreServer.SERVER_ID, fProvider.getConnection());
}
fDStoreServer.setWorkDir(fProvider.getIndexLocation());
DataStore dataStore = fDStoreServer.getDataStore();
if (!dataStore.isConnected()) {
try {
fDStoreServer.startServer(subMon.newChild(5));
} catch (IOException e) {
return null;
}
DataElement status = dataStore.activateMiner("org.eclipse.ptp.internal.rdt.core.miners.CDTMiner"); //$NON-NLS-1$
StatusMonitor smonitor = StatusMonitor.getStatusMonitorFor(fProvider.getConnection(), dataStore);
try {
smonitor.waitForUpdate(status, subMon.newChild(5));
} catch (InterruptedException e) {
// Data store will be disconnected if error occurs
}
}
return dataStore;
} finally {
if (monitor != null) {
monitor.done();
}
}
}
protected void removeProblems(Scope scope) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot workspaceRoot = workspace.getRoot();
IProject project = workspaceRoot.getProject(scope.getName());
try {
project.deleteMarkers("org.eclipse.ptp.rdt.ui.indexerproblemmarker", true, IResource.DEPTH_INFINITE); //$NON-NLS-1$
} catch (CoreException e) {
RDTLog.logError(e);
}
}
protected String reportProblem(Scope scope, String message) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot workspaceRoot = workspace.getRoot();
IProject project = workspaceRoot.getProject(scope.getName());
// parser for error message
int errorMessageStart = message.indexOf("Indexer: "); //$NON-NLS-1$
int errorMessageEnd = message.indexOf(": ", errorMessageStart + 9); //$NON-NLS-1$
String errorMessage = message.substring(errorMessageStart + 9, errorMessageEnd);
boolean includeError = true;
if (errorMessage.indexOf("inclusion") < 0) //$NON-NLS-1$
includeError = false;
// parser for include/macro name
int includeStart = errorMessageEnd + 2;
int includeEnd = message.indexOf(" in file: ", includeStart); //$NON-NLS-1$
String include = message.substring(includeStart, includeEnd);
// parse for file name and line number
int fileStart = includeEnd + 10;
int fileEnd = message.indexOf(":", fileStart); //$NON-NLS-1$
String fileName = message.substring(fileStart, fileEnd);
int lineStart = fileEnd;
int lineEnd = message.indexOf(". ", lineStart); //$NON-NLS-1$
String lineNumber = message.substring(lineStart + 1, lineEnd);
// put error message back together
Object[] args = new Object[] { include, fileName, new Integer(lineNumber.replace(",", "")) }; //$NON-NLS-1$ //$NON-NLS-2$
String info = ParserMessages.getFormattedString("BaseProblemFactory.problemPattern", args); //$NON-NLS-1$
if (includeError)
info = ParserMessages.getFormattedString("ScannerProblemFactory.error.preproc.inclusionNotFound", info); //$NON-NLS-1$
else
info = ParserMessages.getFormattedString("ScannerProblemFactory.error.preproc.definitionNotFound", info); //$NON-NLS-1$
String infoMsg = Messages.getString("RSECIndexSubsystem.11"); //$NON-NLS-1$
String wholeMessage = NLS.bind(Messages.getString("RSECIndexSubsystem.12"), new Object[] { info }) + " " + infoMsg; //$NON-NLS-1$ //$NON-NLS-2$
IFile file = null;
String projectLocation = project.getLocationURI().getPath();
fileStart = fileName.indexOf(projectLocation);
if (fileStart == -1) {
fileName = null;
} else {
fileName = fileName.substring(fileStart + projectLocation.length() + 1);
IPath path = new Path(fileName);
file = project.getFile(path);
}
if (file != null) {
try {
IMarker marker = file.createMarker("org.eclipse.ptp.rdt.ui.indexerproblemmarker"); //$NON-NLS-1$
marker.setAttribute(IMarker.LINE_NUMBER, Integer.parseInt(lineNumber.replace(",", ""))); //$NON-NLS-1$ //$NON-NLS-2$
marker.setAttribute(IMarker.MESSAGE, wholeMessage);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
} catch (CoreException e) {
RDTLog.logError(e);
}
} else {
try {
IMarker marker = project.createMarker("org.eclipse.ptp.rdt.ui.indexerproblemmarker"); //$NON-NLS-1$
marker.setAttribute(IMarker.MESSAGE, wholeMessage);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
} catch (CoreException e) {
RDTLog.logError(e);
}
}
return wholeMessage;
}
}