/******************************************************************************* * Copyright © 2000, 2013 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 Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.core.internal.model.indexing; import java.util.ArrayList; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.edt.ide.core.internal.model.EGLProject; import org.eclipse.edt.ide.core.internal.model.index.IIndex; import org.eclipse.edt.ide.core.model.EGLModelException; import org.eclipse.edt.ide.core.model.IEGLElement; import org.eclipse.edt.ide.core.model.IEGLModel; import org.eclipse.edt.ide.core.model.IEGLPathEntry; import org.eclipse.edt.ide.core.model.IEGLProject; /** * Selects the indexes that correspond to projects in a given search scope * and that are dependent on a given focus element. */ public class IndexSelector { // IEGLSearchScope searchXScope; IEGLElement focus; IndexManager indexManager; IPath[] indexKeys; // cache of the keys for looking index up boolean isPolymorphicSearch; IPath[] projectsAndJars; public IndexSelector( IPath[] enclosingProjects, // IEGLSearchScope searchScope, IEGLElement focus, boolean isPolymorphicSearch, IndexManager indexManager) { // this.searchScope = searchScope; projectsAndJars = enclosingProjects; this.focus = focus; this.indexManager = indexManager; this.isPolymorphicSearch = isPolymorphicSearch; } /** * Returns whether elements of the given project or jar can see the given focus (an IEGLProject or * a JarPackageFragmentRot) either because the focus is part of the project or the jar, or because it is * accessible throught the project's classpath */ public static boolean canSeeFocus(IEGLElement focus, boolean isPolymorphicSearch, IPath projectOrJarPath) { try { IEGLModel model = focus.getEGLModel(); IEGLProject project = getEGLProject(projectOrJarPath, model); if (project == null) { // projectOrJarPath is a jar // it can see the focus only if it is on the classpath of a project that can see the focus IEGLProject[] allProjects = model.getEGLProjects(); for (int i = 0, length = allProjects.length; i < length; i++) { IEGLProject otherProject = allProjects[i]; IEGLPathEntry[] entries = otherProject.getResolvedEGLPath(true); for (int j = 0, length2 = entries.length; j < length2; j++) { IEGLPathEntry entry = entries[j]; if ((entry.getEntryKind() == IEGLPathEntry.CPE_LIBRARY) && entry.getPath().equals(projectOrJarPath)) { if (canSeeFocus(focus, isPolymorphicSearch, otherProject.getPath())) { return true; } } } } return false; } else { // projectOrJarPath is a project // EGLTODO: Support JarPackageFragmentRoot? //EGLProject focusProject = focus instanceof JarPackageFragmentRoot ? (EGLProject)focus.getParent() : (EGLProject)focus; EGLProject focusProject = (EGLProject)focus; if (isPolymorphicSearch) { // look for refering project IEGLPathEntry[] entries = focusProject.getExpandedEGLPath(true); for (int i = 0, length = entries.length; i < length; i++) { IEGLPathEntry entry = entries[i]; if ((entry.getEntryKind() == IEGLPathEntry.CPE_PROJECT) && entry.getPath().equals(projectOrJarPath)) { return true; } } } // EGLTODO: Support JarPackageFragmentRoot? // if (focus instanceof JarPackageFragmentRoot) { // // focus is part of a jar // IPath focusPath = focus.getPath(); // IEGLPathEntry[] entries = ((EGLProject)project).getExpandedEGLPath(true); // for (int i = 0, length = entries.length; i < length; i++) { // IEGLPathEntry entry = entries[i]; // if ((entry.getEntryKind() == IEGLPathEntry.CPE_LIBRARY) // && entry.getPath().equals(focusPath)) { // return true; // } // } // return false; // } else { // focus is part of a project if (focus.equals(project)) { return true; } else { // look for dependent projects IPath focusPath = focusProject.getProject().getFullPath(); IEGLPathEntry[] entries = ((EGLProject)project).getExpandedEGLPath(true); for (int i = 0, length = entries.length; i < length; i++) { IEGLPathEntry entry = entries[i]; if ((entry.getEntryKind() == IEGLPathEntry.CPE_PROJECT) && entry.getPath().equals(focusPath)) { return true; } } return false; } // } } } catch (EGLModelException e) { return false; } } /* * Compute the list of paths which are keying index files. */ private void initializeIndexKeys() { ArrayList requiredIndexKeys = new ArrayList(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IEGLElement projectOrJarFocus = this.focus == null ? null : getProjectOrJar(this.focus); for (int i = 0; i < projectsAndJars.length; i++) { IPath location; IPath path = projectsAndJars[i]; if ((!root.getProject(path.lastSegment()).exists()) // if project does not exist && path.segmentCount() > 1 && ((location = root.getFile(path).getLocation()) == null || !new java.io.File(location.toOSString()).exists()) // and internal jar file does not exist && !new java.io.File(path.toOSString()).exists()) { // and external jar file does not exist continue; } if (projectOrJarFocus == null || canSeeFocus(projectOrJarFocus, this.isPolymorphicSearch, path)) { if (requiredIndexKeys.indexOf(path) == -1) { requiredIndexKeys.add(path); } } } this.indexKeys = new IPath[requiredIndexKeys.size()]; requiredIndexKeys.toArray(this.indexKeys); } public IIndex[] getIndexes() { if (this.indexKeys == null) { this.initializeIndexKeys(); } // acquire the in-memory indexes on the fly int length = this.indexKeys.length; IIndex[] indexes = new IIndex[length]; int count = 0; for (int i = 0; i < length; i++){ // may trigger some index recreation work IIndex index = indexManager.getIndex(indexKeys[i], true /*reuse index file*/, false /*do not create if none*/); if (index != null) indexes[count++] = index; // only consider indexes which are ready yet } if (count != length) { System.arraycopy(indexes, 0, indexes=new IIndex[count], 0, count); } return indexes; } /** * Returns the java project that corresponds to the given path. * Returns null if the path doesn't correspond to a project. */ private static IEGLProject getEGLProject(IPath path, IEGLModel model) { IEGLProject project = model.getEGLProject(path.lastSegment()); if (project.exists()) { return project; } else { return null; } } public static IEGLElement getProjectOrJar(IEGLElement element) { // EGLTODO: Support JarPackageFragmentRoot? while (!(element instanceof IEGLProject)){ // && !(element instanceof JarPackageFragmentRoot)) { element = element.getParent(); } return element; } }