blob: 3e43703b2856409f635a32509ceb91277df075fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 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.internal.rdt.core.miners;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.parser.IParserLogService;
import org.eclipse.cdt.internal.core.index.CIndex;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.indexer.StandaloneFastIndexer;
import org.eclipse.cdt.internal.core.indexer.StandaloneIndexer;
import org.eclipse.cdt.internal.core.pdom.PDOMWriter;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMLinkageFactory;
import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCLinkageFactory;
import org.eclipse.cdt.internal.core.pdom.dom.cpp.PDOMCPPLinkageFactory;
import org.eclipse.cdt.internal.core.pdom.indexer.PDOMIndexerTask;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dstore.core.model.DataElement;
import org.eclipse.dstore.core.model.DataStore;
import org.eclipse.ptp.internal.rdt.core.IRemoteIndexerInfoProvider;
import org.eclipse.ptp.internal.rdt.core.model.Scope;
import org.eclipse.rse.dstore.universal.miners.UniversalServerUtilities;
public class RemoteIndexManager {
public static final String PDOM_EXTENSION = ".pdom"; //$NON-NLS-1$
private static final String CLASS_NAME = "CDTMiner-RemoteIndexManager"; //$NON-NLS-1$
private static RemoteIndexManager theInstance = null;
// private static final IParserLogService LOG = new DefaultLogService();
private static final PDOMCLinkageFactory cLinkageFactory = new PDOMCLinkageFactory();
private static final PDOMCPPLinkageFactory cppLinkageFactory = new PDOMCPPLinkageFactory();
private static final IIndexLocationConverter locationConverter = new RemoteLocationConverter();;
private static final Map<String, IPDOMLinkageFactory> linkageFactoryMap = new HashMap<String, IPDOMLinkageFactory>();
static {
linkageFactoryMap.put(ILinkage.C_LINKAGE_NAME, cLinkageFactory);
linkageFactoryMap.put(ILinkage.CPP_LINKAGE_NAME, cppLinkageFactory);
}
private final Map<String,StandaloneIndexer> scopeToIndexerMap;
private final Map<String,String> scopeToIndexLocationMap;
private RemoteIndexManager() {
scopeToIndexerMap = new HashMap<String,StandaloneIndexer>();
scopeToIndexLocationMap = new HashMap<String,String>();
}
public static synchronized RemoteIndexManager getInstance() {
if(theInstance == null)
theInstance = new RemoteIndexManager();
return theInstance;
}
public IIndex getIndexForScope(String scope, DataStore dataStore) {
if(scope.equals(Scope.WORKSPACE_ROOT_SCOPE_NAME)) {
Set<IIndexFragment> fragments = new HashSet<IIndexFragment>();
for(String currentScope : ScopeManager.getInstance().getAllScopes()) {
IIndexFragment fragment = getIndexerForScope(currentScope, dataStore, null).getIndex().getWritableFragment();
fragments.add(fragment);
}
if(fragments.isEmpty())
UniversalServerUtilities.logWarning(CLASS_NAME, "Index contains 0 fragments", dataStore); //$NON-NLS-1$
return new CIndex(fragments.toArray(new IIndexFragment[fragments.size()]), fragments.size());
}
else {
StandaloneFastIndexer indexer = getIndexerForScope(scope, dataStore, null);
return indexer.getIndex();
}
}
/**
* Gets the indexer and also sets up indexer preferences.
*
* @see PDOMIndexerTask constructor
*/
public StandaloneFastIndexer getIndexerForScope(String scope, IRemoteIndexerInfoProvider provider, DataStore dataStore, DataElement status) {
StandaloneFastIndexer indexer = getIndexerForScope(scope, dataStore, status);
// configure the indexer using the provider
indexer.setScannerInfoProvider(provider);
indexer.setLanguageMapper(new RemoteLanguageMapper(provider, dataStore));
indexer.setFilesToParseUpFront(provider.getFilesToParseUpFront().toArray(new String[]{}));
indexer.setFileEncodingRegistry(provider.getFileEncodingRegistry());
if(provider.checkIndexerPreference(IRemoteIndexerInfoProvider.KEY_SKIP_ALL_REFERENCES)) {
indexer.setSkipReferences(PDOMWriter.SKIP_ALL_REFERENCES);
}
else {
int skipReferences = 0;
if(provider.checkIndexerPreference(IRemoteIndexerInfoProvider.KEY_SKIP_TYPE_REFERENCES))
skipReferences |= PDOMWriter.SKIP_TYPE_REFERENCES;
if(provider.checkIndexerPreference(IRemoteIndexerInfoProvider.KEY_SKIP_MACRO_REFERENCES))
skipReferences |= PDOMWriter.SKIP_MACRO_REFERENCES;
//if(provider.checkIndexerPreference(IRemoteIndexerInfoProvider.KEY_SKIP_IMPLICIT_REFERENCES))
// skipReferences |= PDOMWriter.SKIP_IMPLICIT_REFERENCES;
if(skipReferences == 0)
indexer.setSkipReferences(PDOMWriter.SKIP_NO_REFERENCES);
else
indexer.setSkipReferences(skipReferences);
}
indexer.setIndexAllFiles(provider.checkIndexerPreference(IRemoteIndexerInfoProvider.KEY_INDEX_ALL_FILES));
return indexer;
}
/**
* Creates the given directory if it doesn't already exist.
*/
private boolean createIndexDirectory(String path) {
if(path == null)
return false;
File dir = new File(path);
if(dir.exists())
return dir.canWrite();
return dir.mkdirs();
}
public StandaloneFastIndexer getIndexerForScope(String scope, DataStore dataStore, DataElement status) {
if(scope.equals(Scope.WORKSPACE_ROOT_SCOPE_NAME)) {
throw new IllegalArgumentException("Attempted to get indexer for root scope."); //$NON-NLS-1$
}
StandaloneFastIndexer indexer = (StandaloneFastIndexer) scopeToIndexerMap.get(scope);
if (indexer != null) {
if (status != null) {
IParserLogService LOG = new RemoteLogService(dataStore, status);
indexer.setParserLog(LOG);
}
return indexer;
}
String path = scopeToIndexLocationMap.get(scope);
File indexFile = null;
if(path != null) {
indexFile = new File(path, scope + PDOM_EXTENSION);
try {
if(!indexFile.exists() && !indexFile.createNewFile()) {
indexFile = null;
}
} catch (IOException e) {
indexFile = null;
}
}
if(indexFile == null) {
indexFile = new File(scope + PDOM_EXTENSION); // creates a file object located in the server working directory
UniversalServerUtilities.logWarning(CLASS_NAME, "Can't create index file at " + path + " attempting to use " + indexFile.getParent() + " instead", dataStore); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
scopeToIndexLocationMap.put(scope, indexFile.getParent());
}
UniversalServerUtilities.logInfo(CLASS_NAME, "Index at location:" + indexFile.getAbsolutePath(), dataStore); //$NON-NLS-1$
try {
IParserLogService LOG = new RemoteLogService(dataStore, status);
indexer = new StandaloneFastIndexer(indexFile, locationConverter, linkageFactoryMap, null, null, LOG);
scopeToIndexerMap.put(scope, indexer);
} catch (CoreException e) {
UniversalServerUtilities.logError(CLASS_NAME, "Core Exception while getting indexer for scope", e, dataStore); //$NON-NLS-1$
}
return indexer;
}
/**
* Deletes the index file associated with the given scope name.
* @param scope
* @return true if and only if the file is successfully deleted; false otherwise
*/
public boolean removeIndexFile(String scope, DataStore dataStore) {
if(scope.equals(Scope.WORKSPACE_ROOT_SCOPE_NAME)) {
throw new IllegalArgumentException("Attempted to remove index file for root scope."); //$NON-NLS-1$
}
scopeToIndexerMap.remove(scope);
String loc = scopeToIndexLocationMap.remove(scope);
File indexFile;
if(loc == null)
indexFile = new File(scope + PDOM_EXTENSION);
else
indexFile = new File(loc, scope + PDOM_EXTENSION);
UniversalServerUtilities.logInfo(CLASS_NAME, "Remove index at location: " + indexFile.getAbsolutePath(), dataStore); //$NON-NLS-1$
return indexFile.delete();
}
/**
* Returns the index for the given projects.
* @param projects the projects to get the index for
* @return an index for the projects
*/
public IIndex getIndexForProjects(ICProject[] projects, DataStore dataStore) {
if(projects == null) {
throw new IllegalArgumentException("Get index for projects - projects cannot be null."); //$NON-NLS-1$
}
Set<IIndexFragment> fragments = new HashSet<IIndexFragment>();
Set<String> allScopes = ScopeManager.getInstance().getAllScopes();
for (int i = 0; i < projects.length; i++) {
String currentScope = projects[i].getElementName();
if (allScopes.contains(currentScope)) {
IIndexFragment fragment = getIndexerForScope(currentScope, dataStore, null).getIndex().getWritableFragment();
fragments.add(fragment);
}
}
CIndex index = new CIndex(fragments.toArray(new IIndexFragment[fragments.size()]), fragments.size());
return index;
}
public String setIndexFileLocation(String scope, String configLocation) {
String oldLocation = scopeToIndexLocationMap.get(scope);
if(configLocation.equals(oldLocation))
return configLocation;
scopeToIndexerMap.remove(scope); // invalidates the indexer object that uses the old location
if(createIndexDirectory(configLocation)) {
scopeToIndexLocationMap.put(scope, configLocation);
return configLocation;
}
else {
String serverDir = System.getProperty("user.dir"); //$NON-NLS-1$
scopeToIndexLocationMap.put(scope, serverDir);
return serverDir;
}
}
/**
* Attempts to move the pdom file to the given path. If that path
* is not writable it attempt to move the pdom to the server installation
* path instead.
*
* @return The actual path to where the file was moved.
*/
public String moveIndexFile(String scope, String path, DataStore dataStore) {
String oldLocation = scopeToIndexLocationMap.get(scope);
String newLocation = setIndexFileLocation(scope, path);
if(!newLocation.equals(path)) {
UniversalServerUtilities.logWarning(CLASS_NAME, "Can't move index file to " + path + " using " + newLocation + " instead", dataStore); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if(newLocation.equals(oldLocation)) {
UniversalServerUtilities.logWarning(CLASS_NAME, "Index file not moved because source and destination are the same", dataStore); //$NON-NLS-1$
return oldLocation;
}
UniversalServerUtilities.logWarning(CLASS_NAME, "Moving index file " + scope + PDOM_EXTENSION + " from " + oldLocation + " to " + newLocation, dataStore); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String fileName = scope + PDOM_EXTENSION;
File pdomFile = new File(oldLocation, fileName);
if(!pdomFile.exists()) {
UniversalServerUtilities.logWarning(CLASS_NAME, "Can't find index file at " + oldLocation, dataStore); //$NON-NLS-1$
return oldLocation;
}
boolean success = pdomFile.renameTo(new File(newLocation, fileName));
if(success) {
UniversalServerUtilities.logInfo(CLASS_NAME, "Index file moved from " + oldLocation + " to " + newLocation, dataStore); //$NON-NLS-1$ //$NON-NLS-2$
return newLocation;
}
else {
UniversalServerUtilities.logWarning(CLASS_NAME, "Index file could not be moved", dataStore); //$NON-NLS-1$
return oldLocation;
}
}
}