blob: ebd9818199fb757a2901bf00e5fc8b485bc31892 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 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
*
*******************************************************************************/
package org.eclipse.dltk.internal.core.search;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.search.indexing.IProjectIndexer;
import org.eclipse.osgi.util.NLS;
public class ProjectIndexerManager {
private final static String EXTPOINT = DLTKCore.PLUGIN_ID
+ ".projectIndexer"; //$NON-NLS-1$
private final static String NATURE_ATTR = "nature"; //$NON-NLS-1$
private static final String CLASS_ATTR = "class"; //$NON-NLS-1$
private static final String ID_ATTR = "id"; //$NON-NLS-1$
private static final String INDEXER_ATTR = "indexer"; //$NON-NLS-1$
private static final String ENABLE_ELEM = "enable"; //$NON-NLS-1$
private static final String DISABLE_ELEM = "disable"; //$NON-NLS-1$
private static final String INDEXER_ELEM = "projectIndexer"; //$NON-NLS-1$
// Contains list of indexers for selected nature.
private static Map<String, ProjectIndexerDescriptor> indexers;
private static final Map<String, Set<String>> enabledIndexers = new HashMap<String, Set<String>>();
private static final Map<String, Set<String>> disabledIndexers = new HashMap<String, Set<String>>();
private static class ProjectIndexerDescriptor {
private final String id;
private IConfigurationElement element;
private IProjectIndexer projectIndexer;
ProjectIndexerDescriptor(String id, IConfigurationElement element) {
this.id = id;
this.element = element;
}
public IProjectIndexer getObject() {
if (projectIndexer == null) {
try {
projectIndexer = (IProjectIndexer) element
.createExecutableExtension(CLASS_ATTR);
} catch (CoreException e) {
DLTKCore.error("Error initializing project indexer", e); //$NON-NLS-1$
synchronized (ProjectIndexerManager.class) {
indexers.remove(id);
}
return null;
}
}
return projectIndexer;
}
}
private synchronized static void initialize() {
if (indexers != null) {
return;
}
indexers = new HashMap<String, ProjectIndexerDescriptor>();
for (IConfigurationElement element : Platform.getExtensionRegistry()
.getConfigurationElementsFor(EXTPOINT)) {
if (DISABLE_ELEM.equals(element.getName())) {
final String nature = element.getAttribute(NATURE_ATTR);
Set<String> disabledForNature = disabledIndexers.get(nature);
if (disabledForNature == null) {
disabledForNature = new HashSet<String>();
disabledIndexers.put(nature, disabledForNature);
}
disabledForNature.add(element.getAttribute(INDEXER_ATTR));
} else if (ENABLE_ELEM.equals(element.getName())) {
final String nature = element.getAttribute(NATURE_ATTR);
Set<String> enabledForNature = enabledIndexers.get(nature);
if (enabledForNature == null) {
enabledForNature = new HashSet<String>();
enabledIndexers.put(nature, enabledForNature);
}
enabledForNature.add(element.getAttribute(INDEXER_ATTR));
} else if (INDEXER_ELEM.equals(element.getName())) {
final String id = element.getAttribute(ID_ATTR);
if (id == null) {
DLTKCore.warn(NLS
.bind("{0} contributed by {1} does not have \"{2}\" attribute", //$NON-NLS-1$
new Object[] { INDEXER_ELEM,
element.getContributor().getName(),
ID_ATTR }));
continue;
}
if (indexers.containsKey(id)) {
DLTKCore.warn(NLS
.bind("Duplicate {0} contribution from {1} (previous one is from \"{2}\")", //$NON-NLS-1$
new Object[] {
INDEXER_ELEM,
element.getContributor().getName(),
indexers.get(id).element.getContributor()
.getName() }));
continue;
}
indexers.put(id, new ProjectIndexerDescriptor(id, element));
}
}
}
private static boolean enabled = true;
public static boolean isEnabled() {
return enabled;
}
public static void setEnabled(boolean value) {
enabled = value;
}
/**
* Return merged with all elements with nature #
*
* @param natureId
* @return
* @throws CoreException
*/
public static IProjectIndexer[] getIndexers(String natureId) {
initialize();
IProjectIndexer[] nature = getByNature(natureId, natureId);
IProjectIndexer[] all = getByNature("#", natureId); //$NON-NLS-1$
if (all == null) {
return nature;
}
if (nature == null) {
return all;
}
final IProjectIndexer[] result = new IProjectIndexer[nature.length
+ all.length];
System.arraycopy(nature, 0, result, 0, nature.length);
System.arraycopy(all, 0, result, nature.length, all.length);
return result;
}
public static IProjectIndexer[] getAllIndexers() {
initialize();
final Set<String> indexerIds = new HashSet<String>();
for (Set<String> ids : enabledIndexers.values()) {
indexerIds.addAll(ids);
}
return getIndexers(indexerIds, null);
}
private static IProjectIndexer[] getByNature(String natureId,
String disabledNature) {
Set<String> indexerIds = enabledIndexers.get(natureId);
if (indexerIds != null) {
return getIndexers(indexerIds, disabledNature);
} else {
return null;
}
}
private static IProjectIndexer[] getIndexers(Set<String> indexerIds,
String disabledNature) {
final List<IProjectIndexer> result = new ArrayList<IProjectIndexer>(
indexerIds.size());
final Set<String> disabled = disabledIndexers.get(disabledNature);
for (String indexerId : indexerIds) {
if (disabled != null && disabled.contains(indexerId)) {
continue;
}
final ProjectIndexerDescriptor descriptor = indexers.get(indexerId);
if (descriptor != null) {
final IProjectIndexer indexer = descriptor.getObject();
if (indexer != null) {
result.add(indexer);
}
}
}
if (!result.isEmpty()) {
return result.toArray(new IProjectIndexer[result.size()]);
} else {
return null;
}
}
private static IProjectIndexer[] getIndexers(IScriptProject project) {
return getIndexers(project, true);
}
private static IProjectIndexer[] getIndexers(IScriptProject project,
boolean checkEnable) {
if (!enabled) {
return null;
}
if (checkEnable && !isIndexerEnabled(project.getProject())) {
return null;
}
final IDLTKLanguageToolkit toolkit = DLTKLanguageManager
.getLanguageToolkit(project);
if (toolkit == null) {
return null;
}
return getIndexers(toolkit.getNatureId());
}
public static boolean isIndexerEnabled(final IProject project) {
if (!enabled) {
return false;
}
return new ProjectScope(project).getNode(DLTKCore.PLUGIN_ID)
.getBoolean(DLTKCore.INDEXER_ENABLED, true);
}
/**
* Removes the indexes for a given path. This is a no-op if the index did
* not exist.
*
* @param project
*
* @param path
*/
public static void removeLibrary(IScriptProject project, IPath path) {
final IProjectIndexer[] indexers = getIndexers(project);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].removeLibrary(project, path);
}
}
}
/**
* @param projectPath
*/
public static void removeProject(IPath projectPath) {
final IProjectIndexer[] indexers = getAllIndexers();
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].removeProject(projectPath);
}
}
}
/**
* @param project
* @param path
*/
public static void indexLibrary(IScriptProject project, IPath path) {
final IProjectIndexer[] indexers = getIndexers(project);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].indexLibrary(project, path);
}
}
}
/**
* @param project
* @param path
*/
public static void removeProjectFragment(IScriptProject project, IPath path) {
final IProjectIndexer[] indexers = getIndexers(project);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].removeProjectFragment(project, path);
}
}
}
/**
* @param project
* @param path
*/
public static void indexProjectFragment(IScriptProject project, IPath path) {
final IProjectIndexer[] indexers = getIndexers(project);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].indexProjectFragment(project, path);
}
}
}
/**
* @param res
*/
public static void indexProject(IProject project) {
if (isIndexerEnabled(project)) {
indexProject(project, DLTKCore.create(project));
}
}
public static void indexProject(IScriptProject scriptProject) {
final IProject project = scriptProject.getProject();
if (isIndexerEnabled(project)) {
indexProject(project, scriptProject);
}
}
/**
* @param scriptProject
*/
private static void indexProject(IProject project,
IScriptProject scriptProject) {
final IProjectIndexer[] indexers = getIndexers(scriptProject, false);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].indexProject(scriptProject);
}
}
}
/**
* @param project
* @param path
*/
public static void removeSourceModule(IScriptProject project, String path) {
final IProjectIndexer[] indexers = getIndexers(project);
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].removeSourceModule(project, path);
}
}
}
/**
* @param module
* @param toolkit
*/
public static void indexSourceModule(ISourceModule module,
IDLTKLanguageToolkit toolkit) {
if (!enabled) {
return;
}
final IProjectIndexer[] indexers = getIndexers(toolkit.getNatureId());
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].indexSourceModule(module, toolkit);
}
}
}
/**
* @param workingCopy
*/
public static void reconciled(ISourceModule workingCopy) {
final IScriptProject project = workingCopy.getScriptProject();
if (project == null) {
return;
}
if (!isIndexerEnabled(project.getProject())) {
return;
}
final IDLTKLanguageToolkit toolkit = DLTKLanguageManager
.getLanguageToolkit(project);
if (toolkit == null) {
return;
}
final IProjectIndexer[] indexers = getIndexers(toolkit.getNatureId());
if (indexers != null) {
for (int i = 0; i < indexers.length; ++i) {
indexers[i].reconciled(workingCopy, toolkit);
}
}
}
public static void startIndexing() {
final IProjectIndexer[] indexers = getAllIndexers();
if (indexers == null) {
return;
}
boolean wantRefresh = false;
for (int i = 0; i < indexers.length; ++i) {
indexers[i].startIndexing();
wantRefresh |= indexers[i].wantRefreshOnStart();
}
if (wantRefresh) {
final IScriptProject[] projects;
try {
projects = DLTKCore.create(
ResourcesPlugin.getWorkspace().getRoot())
.getScriptProjects();
} catch (Exception e) {
DLTKCore.error(e);
return;
}
for (int i = 0; i < projects.length; ++i) {
final IScriptProject project = projects[i];
final IProjectIndexer[] projectIndexers = getIndexers(project);
if (projectIndexers != null) {
for (IProjectIndexer projectIndexer : projectIndexers) {
if (projectIndexer.wantRefreshOnStart()) {
projectIndexer.indexProject(project);
}
}
}
}
}
}
}