blob: 7113d5ab1de00e2ccb6430723e2827a9e535878d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 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
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.internal.dialogs;
import java.util.ArrayList;
import java.util.HashSet;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
/**
* This class was derived from JavaSearchScope as that class did not have a
* provision to exclude classpath entries that are not exported A Java-specific
* scope for searching relative to one or more java elements.
*/
public class TypeJavaSearchScope implements IJavaSearchScope {
private boolean includeExportedClassPathEntriesOnly = true;
private ArrayList elements;
/*
* The paths of the resources in this search scope (or the classpath
* entries' paths if the resources are projects)
*/
private IPath[] paths;
private boolean[] pathWithSubFolders;
private int pathsCount;
private IPath[] enclosingProjectsAndJars;
public TypeJavaSearchScope() {
this.initialize();
// disabled for now as this could be expensive
// JavaModelManager.getJavaModelManager().rememberScope(this);
}
private void addEnclosingProjectOrJar(IPath path) {
int length = this.enclosingProjectsAndJars.length;
for (int i = 0; i < length; i++) {
if (this.enclosingProjectsAndJars[i].equals(path))
return;
}
System.arraycopy(this.enclosingProjectsAndJars, 0, this.enclosingProjectsAndJars = new IPath[length + 1], 0, length);
this.enclosingProjectsAndJars[length] = path;
}
/**
* Method addProject. This method adds all the classpath entries for the
* current project to the search scope.
*
* @param javaProject
* @param includesPrereqProjects
* @param visitedProjects
* @throws JavaModelException
*/
public void addProject(IJavaProject javaProject, boolean includesPrereqProjects, HashSet visitedProjects) throws JavaModelException {
IProject project = javaProject.getProject();
if (!project.isAccessible() || !visitedProjects.add(project))
return;
this.addEnclosingProjectOrJar(project.getFullPath());
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
IJavaModel model = javaProject.getJavaModel();
for (int i = 0, length = entries.length; i < length; i++) {
IClasspathEntry entry = entries[i];
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY :
IPath path = entry.getPath();
this.add(path, true);
this.addEnclosingProjectOrJar(path);
break;
case IClasspathEntry.CPE_PROJECT :
if (includesPrereqProjects) {
this.add(model.getJavaProject(entry.getPath().lastSegment()), true, visitedProjects);
}
break;
case IClasspathEntry.CPE_SOURCE :
this.add(entry.getPath(), true);
break;
}
}
}
/**
* Method add. This method filters out all the classpath entries of the
* project which are not exported.
*
* @param javaProject
* @param includesPrereqProjects
* @param visitedProjects
* @throws JavaModelException
*/
public void add(IJavaProject javaProject, boolean includesPrereqProjects, HashSet visitedProjects) throws JavaModelException {
IProject project = javaProject.getProject();
if (!project.isAccessible() || !visitedProjects.add(project))
return;
this.addEnclosingProjectOrJar(project.getFullPath());
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
IJavaModel model = javaProject.getJavaModel();
for (int i = 0, length = entries.length; i < length; i++) {
IClasspathEntry entry = entries[i];
if (includeExportedClassPathEntriesOnly()) {
if (!entry.isExported() && entry.getEntryKind() != IClasspathEntry.CPE_SOURCE)
continue;
}
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY :
IPath path = entry.getPath();
this.add(path, true);
this.addEnclosingProjectOrJar(path);
break;
case IClasspathEntry.CPE_PROJECT :
if (includesPrereqProjects) {
this.add(model.getJavaProject(entry.getPath().lastSegment()), true, visitedProjects);
}
break;
case IClasspathEntry.CPE_SOURCE :
this.add(entry.getPath(), true);
break;
}
}
}
public void add(IJavaElement element) throws JavaModelException {
IPackageFragmentRoot root = null;
switch (element.getElementType()) {
case IJavaElement.JAVA_MODEL :
// a workspace sope should be used
break;
case IJavaElement.JAVA_PROJECT :
this.add((IJavaProject) element, true, new HashSet(2));
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT :
root = (IPackageFragmentRoot) element;
this.add(root.getPath(), true);
break;
case IJavaElement.PACKAGE_FRAGMENT :
root = (IPackageFragmentRoot) element.getParent();
if (root.isArchive()) {
this.add(root.getPath().append(new Path(element.getElementName().replace('.', '/'))), false);
} else {
IResource resource = element.getUnderlyingResource();
if (resource != null && resource.isAccessible()) {
this.add(resource.getFullPath(), false);
}
}
break;
default :
// remember sub-cu (or sub-class file) java elements
if (element instanceof IMember) {
if (this.elements == null) {
this.elements = new ArrayList();
}
this.elements.add(element);
}
this.add(this.fullPath(element), true);
// find package fragment root including this java element
IJavaElement parent = element.getParent();
while (parent != null && !(parent instanceof IPackageFragmentRoot)) {
parent = parent.getParent();
}
if (parent instanceof IPackageFragmentRoot) {
root = (IPackageFragmentRoot) parent;
}
}
if (root != null) {
if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
this.addEnclosingProjectOrJar(root.getPath());
} else {
this.addEnclosingProjectOrJar(root.getJavaProject().getProject().getFullPath());
}
}
}
/**
* Adds the given path to this search scope. Remember if subfolders need to
* be included as well.
*/
private void add(IPath path, boolean withSubFolders) {
if (this.paths.length == this.pathsCount) {
System.arraycopy(this.paths, 0, this.paths = new IPath[this.pathsCount * 2], 0, this.pathsCount);
System.arraycopy(this.pathWithSubFolders, 0, this.pathWithSubFolders = new boolean[this.pathsCount * 2], 0, this.pathsCount);
}
this.paths[this.pathsCount] = path;
this.pathWithSubFolders[this.pathsCount++] = withSubFolders;
}
/*
* (non-Javadoc)
*
* @see IJavaSearchScope#encloses(String)
*/
public boolean encloses(String resourcePathString) {
IPath resourcePath;
int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
if (separatorIndex != -1) {
resourcePath = new Path(resourcePathString.substring(0, separatorIndex)).append(new Path(resourcePathString.substring(separatorIndex + 1)));
} else {
resourcePath = new Path(resourcePathString);
}
return this.encloses(resourcePath);
}
/**
* Returns whether this search scope encloses the given path.
*/
private boolean encloses(IPath path) {
for (int i = 0; i < this.pathsCount; i++) {
if (this.pathWithSubFolders[i]) {
if (this.paths[i].isPrefixOf(path)) {
return true;
}
} else {
IPath scopePath = this.paths[i];
if (scopePath.isPrefixOf(path) && (scopePath.segmentCount() == path.segmentCount() - 1)) {
return true;
}
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see IJavaSearchScope#encloses(IJavaElement)
*/
public boolean encloses(IJavaElement element) {
if (this.elements != null) {
for (int i = 0, length = this.elements.size(); i < length; i++) {
IJavaElement scopeElement = (IJavaElement) this.elements.get(i);
IJavaElement searchedElement = element;
while (searchedElement != null) {
if (searchedElement.equals(scopeElement)) {
return true;
}
searchedElement = searchedElement.getParent();
}
}
return false;
}
return this.encloses(this.fullPath(element));
}
/*
* (non-Javadoc)
*
* @see IJavaSearchScope#enclosingProjectsAndJars()
*/
public IPath[] enclosingProjectsAndJars() {
return this.enclosingProjectsAndJars;
}
private IPath fullPath(IJavaElement element) {
if (element instanceof IPackageFragmentRoot) {
return ((IPackageFragmentRoot) element).getPath();
}
IJavaElement parent = element.getParent();
IPath parentPath = parent == null ? null : this.fullPath(parent);
IPath childPath;
if (element instanceof IPackageFragment) {
childPath = new Path(element.getElementName().replace('.', '/'));
} else if (element instanceof IOpenable) {
childPath = new Path(element.getElementName());
} else {
return parentPath;
}
return parentPath == null ? childPath : parentPath.append(childPath);
}
protected void initialize() {
this.paths = new IPath[1];
this.pathWithSubFolders = new boolean[1];
this.pathsCount = 0;
this.enclosingProjectsAndJars = new IPath[0];
}
/**
* Gets the includeExportedClassPathEntriesOnly.
*
* @return Returns a boolean
*/
public boolean includeExportedClassPathEntriesOnly() {
return includeExportedClassPathEntriesOnly;
}
/**
* Sets the includeExportedClassPathEntriesOnly.
*
* @param includeExportedClassPathEntriesOnly
* The includeExportedClassPathEntriesOnly to set
*/
public void setIncludeExportedClassPathEntriesOnly(boolean includeExportedClassPathEntriesOnly) {
this.includeExportedClassPathEntriesOnly = includeExportedClassPathEntriesOnly;
}
/**
* @see IJavaSearchScope#includesBinaries()
* @deprecated
*/
public boolean includesBinaries() {
return true;
}
/**
* @see IJavaSearchScope#includesClasspaths()
* @deprecated
*/
public boolean includesClasspaths() {
return true;
}
/**
* @see IJavaSearchScope#setIncludesBinaries(boolean)
* @deprecated
*/
public void setIncludesBinaries(boolean includesBinaries) {
//Default nothing
}
/**
* @see IJavaSearchScope#setIncludesClasspaths(boolean)
* @deprecated
*/
public void setIncludesClasspaths(boolean includesClasspaths) {
//Default nothing
}
}