blob: 43f8ae246d422d1a6110f1f9d81e003d53b3ea9e [file] [log] [blame]
package org.eclipse.jdt.internal.core.newbuilder;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.internal.compiler.util.CharOperation;
import java.io.*;
import java.util.*;
public class NameEnvironment implements INameEnvironment {
ClasspathLocation[] classpathLocations;
String[] initialTypeNames; // assumed that each name is of the form "a/b/ClassName"
String[] additionalSourceFilenames; // assumed that each name is of the form "d:/eclipse/Test/a/b/ClassName.java"
public NameEnvironment(ClasspathLocation[] classpathLocations) {
this.classpathLocations = classpathLocations;
}
public NameEnvironment(IJavaProject javaProject) {
try {
IWorkspaceRoot workspaceRoot = javaProject.getProject().getWorkspace().getRoot();
IResource outputFolder = workspaceRoot.findMember(javaProject.getOutputLocation());
String outputFolderLocation = null;
if (outputFolder != null && outputFolder.exists())
outputFolderLocation = outputFolder.getLocation().toString();
this.classpathLocations = computeLocations(workspaceRoot, javaProject, outputFolderLocation, null, null);
} catch(JavaModelException e) {
this.classpathLocations = new ClasspathLocation[0];
}
}
/* Some examples of resolved class path entries.
* Remember to search class path in the order that it was defined.
*
* 1a. typical project with no source folders:
* /Test[CPE_SOURCE][K_SOURCE] -> D:/eclipse.test/Test
* 1b. project with source folders:
* /Test/src1[CPE_SOURCE][K_SOURCE] -> D:/eclipse.test/Test/src1
* /Test/src2[CPE_SOURCE][K_SOURCE] -> D:/eclipse.test/Test/src2
* NOTE: These can be in any order & separated by prereq projects or libraries
* 1c. project external to workspace (only detectable using getLocation()):
* /Test/src[CPE_SOURCE][K_SOURCE] -> d:/eclipse.zzz/src
* Need to search source folder & output folder TOGETHER
* Use .java file if its more recent than .class file
*
* 2. zip files:
* D:/j9/lib/jclMax/classes.zip[CPE_LIBRARY][K_BINARY][sourcePath:d:/j9/lib/jclMax/source/source.zip]
* -> D:/j9/lib/jclMax/classes.zip
* ALWAYS want to take the library path as is
*
* 3a. prereq project (regardless of whether it has a source or output folder):
* /Test[CPE_PROJECT][K_SOURCE] -> D:/eclipse.test/Test
* ALWAYS want to append the output folder & ONLY search for .class files
*/
public static ClasspathLocation[] computeLocations(
IWorkspaceRoot workspaceRoot,
IJavaProject javaProject,
String outputFolderLocation,
ArrayList sourceFolders,
SimpleLookupTable prereqOutputFolders) throws JavaModelException {
IClasspathEntry[] classpathEntries = ((JavaProject) javaProject).getExpandedClasspath(true, true);
int cpCount = 0;
int max = classpathEntries.length;
ClasspathLocation[] classpathLocations = new ClasspathLocation[max];
boolean firstSourceFolder = true;
nextEntry : for (int i = 0; i < max; i++) {
IClasspathEntry entry = classpathEntries[i];
Object target = JavaModel.getTarget(workspaceRoot, entry.getPath(), true);
if (target == null) continue nextEntry;
if (target instanceof IResource) {
IResource resource = (IResource) target;
switch(entry.getEntryKind()) {
case IClasspathEntry.CPE_SOURCE :
if (outputFolderLocation == null || !(resource instanceof IContainer)) continue nextEntry;
if (sourceFolders != null) { // normal builder mode
sourceFolders.add(resource);
classpathLocations[cpCount++] =
ClasspathLocation.forSourceFolder(resource.getLocation().toString(), outputFolderLocation);
} else if (firstSourceFolder) { // add the output folder only once
firstSourceFolder = false;
classpathLocations[cpCount++] = ClasspathLocation.forBinaryFolder(outputFolderLocation);
}
continue nextEntry;
case IClasspathEntry.CPE_PROJECT :
if (!(resource instanceof IProject)) continue nextEntry;
IProject prereqProject = (IProject) resource;
IPath outputLocation = JavaCore.create(prereqProject).getOutputLocation();
IResource prereqOutputFolder;
if (prereqProject.getFullPath().equals(outputLocation)) {
prereqOutputFolder = prereqProject;
} else {
prereqOutputFolder = workspaceRoot.findMember(outputLocation);
if (prereqOutputFolder == null || !prereqOutputFolder.exists() || !(prereqOutputFolder instanceof IFolder))
continue nextEntry;
}
if (prereqOutputFolders != null)
prereqOutputFolders.put(prereqProject, prereqOutputFolder);
classpathLocations[cpCount++] = ClasspathLocation.forBinaryFolder(prereqOutputFolder.getLocation().toString());
continue nextEntry;
case IClasspathEntry.CPE_LIBRARY :
if (resource instanceof IFile) {
String extension = entry.getPath().getFileExtension();
if (!(JavaBuilder.JAR_EXTENSION.equalsIgnoreCase(extension) || JavaBuilder.ZIP_EXTENSION.equalsIgnoreCase(extension)))
continue nextEntry;
classpathLocations[cpCount++] = ClasspathLocation.forLibrary(resource.getLocation().toString());
} else if (resource instanceof IFolder) {
classpathLocations[cpCount++] = ClasspathLocation.forBinaryFolder(resource.getLocation().toString());
}
continue nextEntry;
}
} else if (target instanceof File) {
String extension = entry.getPath().getFileExtension();
if (!(JavaBuilder.JAR_EXTENSION.equalsIgnoreCase(extension) || JavaBuilder.ZIP_EXTENSION.equalsIgnoreCase(extension)))
continue nextEntry;
classpathLocations[cpCount++] = ClasspathLocation.forLibrary(entry.getPath().toString());
}
}
if (cpCount < max)
System.arraycopy(classpathLocations, 0, (classpathLocations = new ClasspathLocation[cpCount]), 0, cpCount);
return classpathLocations;
}
public static String assembleName(char[] fileName, char[][] packageName, char separator) {
return new String(CharOperation.concatWith(packageName, fileName, separator));
}
public static String assembleName(String fileName, char[][] packageName, char separator) {
return new String(
CharOperation.concatWith(
packageName,
fileName == null ? null : fileName.toCharArray(),
separator));
}
private NameEnvironmentAnswer findClass(char[] name, char[][] packageName) {
String fullName = assembleName(name, packageName, '/');
if (initialTypeNames != null)
for (int i = 0, length = initialTypeNames.length; i < length; i++)
if (fullName.equals(initialTypeNames[i]))
return null; // looking for a file which we know was provided at the beginning of the compilation
for (int i = 0, length = classpathLocations.length; i < length; i++) {
NameEnvironmentAnswer answer = classpathLocations[i].findClass(name, packageName);
if (answer != null) return answer;
}
return null;
}
public NameEnvironmentAnswer findType(char[][] compoundName) {
if (compoundName == null) return null;
return findClass(
compoundName[compoundName.length - 1],
CharOperation.subarray(compoundName, 0, compoundName.length - 1));
}
public NameEnvironmentAnswer findType(char[] name, char[][] compoundName) {
if (name == null) return null;
return findClass(name, compoundName);
}
public boolean isPackage(char[][] compoundName, char[] packageName) {
if (compoundName == null)
compoundName = new char[0][];
for (int i = 0, length = classpathLocations.length; i < length; i++)
if (classpathLocations[i].isPackage(compoundName, packageName))
return true;
return false;
}
public void cleanup() {
for (int i = 0, length = classpathLocations.length; i < length; i++){
classpathLocations[i].cleanup();
}
}
public void setNames(String[] initialTypeNames, String[] additionalSourceFilenames) {
this.initialTypeNames = initialTypeNames;
this.additionalSourceFilenames = additionalSourceFilenames;
for (int i = 0, length = classpathLocations.length; i < length; i++) {
ClasspathLocation classpath = classpathLocations[i];
classpath.reset();
if (classpath instanceof ClasspathMultiDirectory)
((ClasspathMultiDirectory) classpath).nameEnvironment = this;
}
}
}