blob: ca3bb9aa6f920704ee67bad6f3b003024614b1f8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
/**
* Info for IJavaProject.
* <p>
* Note: <code>getChildren()</code> returns all of the <code>IPackageFragmentRoots</code>
* specified on the classpath for the project. This can include roots external to the
* project. See <code>JavaProject#getAllPackageFragmentRoots()</code> and
* <code>JavaProject#getPackageFragmentRoots()</code>. To get only the <code>IPackageFragmentRoots</code>
* that are internal to the project, use <code>JavaProject#getChildren()</code>.
*/
/* package */
class JavaProjectElementInfo extends OpenableElementInfo {
static class ProjectCache {
ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, HashtableOfArrayToObject allPkgFragmentsCache, Map pathToResolvedEntries) {
this.allPkgFragmentRootsCache = allPkgFragmentRootsCache;
this.allPkgFragmentsCache = allPkgFragmentsCache;
this.pathToResolvedEntries = pathToResolvedEntries;
}
/*
* A cache of all package fragment roots of this project.
*/
public IPackageFragmentRoot[] allPkgFragmentRootsCache;
/*
* A cache of all package fragments in this project.
* (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name)
*/
public HashtableOfArrayToObject allPkgFragmentsCache;
public Map pathToResolvedEntries;
}
/**
* A array with all the non-java resources contained by this PackageFragment
*/
private Object[] nonJavaResources;
ProjectCache projectCache;
/**
* Create and initialize a new instance of the receiver
*/
public JavaProjectElementInfo() {
this.nonJavaResources = null;
}
/**
* Compute the non-java resources contained in this java project.
*/
private Object[] computeNonJavaResources(JavaProject project) {
// determine if src == project and/or if bin == project
IPath projectPath = project.getProject().getFullPath();
boolean srcIsProject = false;
boolean binIsProject = false;
char[][] inclusionPatterns = null;
char[][] exclusionPatterns = null;
IClasspathEntry[] classpath = null;
IPath projectOutput = null;
try {
classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
for (int i = 0; i < classpath.length; i++) {
IClasspathEntry entry = classpath[i];
if (projectPath.equals(entry.getPath())) {
srcIsProject = true;
inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
break;
}
}
projectOutput = project.getOutputLocation();
binIsProject = projectPath.equals(projectOutput);
} catch (JavaModelException e) {
// ignore
}
Object[] resources = new IResource[5];
int resourcesCounter = 0;
try {
IResource[] members = ((IContainer) project.getResource()).members();
for (int i = 0, max = members.length; i < max; i++) {
IResource res = members[i];
switch (res.getType()) {
case IResource.FILE :
IPath resFullPath = res.getFullPath();
String resName = res.getName();
// ignore a jar file on the classpath
if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
break;
}
// ignore .java file if src == project
if (srcIsProject
&& Util.isValidCompilationUnitName(resName)
&& !Util.isExcluded(res, inclusionPatterns, exclusionPatterns)) {
break;
}
// ignore .class file if bin == project
if (binIsProject && Util.isValidClassFileName(resName)) {
break;
}
// else add non java resource
if (resources.length == resourcesCounter) {
// resize
System.arraycopy(
resources,
0,
(resources = new IResource[resourcesCounter * 2]),
0,
resourcesCounter);
}
resources[resourcesCounter++] = res;
break;
case IResource.FOLDER :
resFullPath = res.getFullPath();
// ignore non-excluded folders on the classpath or that correspond to an output location
if ((srcIsProject && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns) && Util.isValidFolderNameForPackage(res.getName()))
|| this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
break;
}
// else add non java resource
if (resources.length == resourcesCounter) {
// resize
System.arraycopy(
resources,
0,
(resources = new IResource[resourcesCounter * 2]),
0,
resourcesCounter);
}
resources[resourcesCounter++] = res;
}
}
if (resources.length != resourcesCounter) {
System.arraycopy(
resources,
0,
(resources = new IResource[resourcesCounter]),
0,
resourcesCounter);
}
} catch (CoreException e) {
resources = NO_NON_JAVA_RESOURCES;
resourcesCounter = 0;
}
return resources;
}
ProjectCache getProjectCache(JavaProject project) {
ProjectCache cache = this.projectCache;
if (cache == null) {
IPackageFragmentRoot[] roots;
Map reverseMap = new HashMap(3);
try {
roots = project.getAllPackageFragmentRoots(reverseMap);
} catch (JavaModelException e) {
// project does not exist: cannot happen since this is the info of the project
roots = new IPackageFragmentRoot[0];
reverseMap.clear();
}
HashtableOfArrayToObject fragmentsCache = new HashtableOfArrayToObject();
for (int i = 0, length = roots.length; i < length; i++) {
IPackageFragmentRoot root = roots[i];
IJavaElement[] frags = null;
try {
frags = root.getChildren();
} catch (JavaModelException e) {
// root doesn't exist: ignore
continue;
}
for (int j = 0, length2 = frags.length; j < length2; j++) {
PackageFragment fragment= (PackageFragment) frags[j];
String[] pkgName = fragment.names;
Object existing = fragmentsCache.get(pkgName);
if (existing == null) {
fragmentsCache.put(pkgName, root);
} else {
if (existing instanceof PackageFragmentRoot) {
fragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
} else {
IPackageFragmentRoot[] entry= (IPackageFragmentRoot[]) existing;
IPackageFragmentRoot[] copy= new IPackageFragmentRoot[entry.length + 1];
System.arraycopy(entry, 0, copy, 0, entry.length);
copy[entry.length]= root;
fragmentsCache.put(pkgName, copy);
}
}
}
}
cache = new ProjectCache(roots, fragmentsCache, reverseMap);
this.projectCache = cache;
}
return cache;
}
/**
* Returns an array of non-java resources contained in the receiver.
*/
Object[] getNonJavaResources(JavaProject project) {
if (this.nonJavaResources == null) {
this.nonJavaResources = computeNonJavaResources(project);
}
return this.nonJavaResources;
}
/*
* Returns whether the given path is a classpath entry or an output location.
*/
private boolean isClasspathEntryOrOutputLocation(IPath path, IClasspathEntry[] resolvedClasspath, IPath projectOutput) {
if (projectOutput.equals(path)) return true;
for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
IClasspathEntry entry = resolvedClasspath[i];
if (entry.getPath().equals(path)) {
return true;
}
IPath output;
if ((output = entry.getOutputLocation()) != null && output.equals(path)) {
return true;
}
}
return false;
}
/*
* Creates a new name lookup for this project info.
* The given project is assumed to be the handle of this info.
* This name lookup first looks in the given working copies.
*/
NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies) {
ProjectCache cache = getProjectCache(project);
return new NameLookup(cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.pathToResolvedEntries);
}
/*
* Reset the package fragment roots and package fragment caches
*/
void resetCaches() {
this.projectCache = null;
}
/**
* Set the fNonJavaResources to res value
*/
void setNonJavaResources(Object[] resources) {
this.nonJavaResources = resources;
}
}