001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.core.search.matching;
011:
012: import java.util.HashMap;
013: import java.util.zip.ZipFile;
014:
015: import org.eclipse.core.resources.IContainer;
016: import org.eclipse.core.resources.IWorkspaceRoot;
017: import org.eclipse.core.runtime.CoreException;
018: import org.eclipse.core.runtime.IPath; //import org.eclipse.jdt.core.*;
019: import org.eclipse.jdt.core.*;
020: import org.eclipse.jdt.core.IJavaProject;
021: import org.eclipse.jdt.core.IPackageFragmentRoot;
022: import org.eclipse.jdt.core.JavaModelException; //import org.eclipse.jdt.core.JavaCore;
023: import org.eclipse.jdt.core.compiler.CharOperation;
024: import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
025: import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
026: import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
027: import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
028: import org.eclipse.jdt.internal.core.ClasspathEntry;
029: import org.eclipse.jdt.internal.core.JavaModel;
030: import org.eclipse.jdt.internal.core.JavaModelManager;
031: import org.eclipse.jdt.internal.core.JavaProject;
032: import org.eclipse.jdt.internal.core.PackageFragmentRoot;
033: import org.eclipse.jdt.internal.core.builder.ClasspathJar;
034: import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
035: import org.eclipse.jdt.internal.core.util.Util;
036:
037: /*
038: * A name environment based on the classpath of a Java project.
039: */
040: public class JavaSearchNameEnvironment implements INameEnvironment,
041: SuffixConstants {
042:
043: ClasspathLocation[] locations;
044:
045: /*
046: * A map from the fully qualified slash-separated name of the main type (String) to the working copy
047: */
048: HashMap workingCopies;
049:
050: public JavaSearchNameEnvironment(IJavaProject javaProject,
051: org.eclipse.jdt.core.ICompilationUnit[] copies) {
052: computeClasspathLocations(javaProject.getProject()
053: .getWorkspace().getRoot(), (JavaProject) javaProject);
054: try {
055: int length = copies == null ? 0 : copies.length;
056: this .workingCopies = new HashMap(length);
057: if (copies != null) {
058: for (int i = 0; i < length; i++) {
059: org.eclipse.jdt.core.ICompilationUnit workingCopy = copies[i];
060: IPackageDeclaration[] pkgs = workingCopy
061: .getPackageDeclarations();
062: String pkg = pkgs.length > 0 ? pkgs[0]
063: .getElementName() : ""; //$NON-NLS-1$
064: String cuName = workingCopy.getElementName();
065: String mainTypeName = Util
066: .getNameWithoutJavaLikeExtension(cuName);
067: String qualifiedMainTypeName = pkg.length() == 0 ? mainTypeName
068: : pkg.replace('.', '/') + '/'
069: + mainTypeName;
070: this .workingCopies.put(qualifiedMainTypeName,
071: workingCopy);
072: }
073: }
074: } catch (JavaModelException e) {
075: // working copy doesn't exist: cannot happen
076: }
077: }
078:
079: public void cleanup() {
080: for (int i = 0, length = this .locations.length; i < length; i++) {
081: this .locations[i].cleanup();
082: }
083: }
084:
085: private void computeClasspathLocations(
086: IWorkspaceRoot workspaceRoot, JavaProject javaProject) {
087:
088: IPackageFragmentRoot[] roots = null;
089: try {
090: roots = javaProject.getAllPackageFragmentRoots();
091: } catch (JavaModelException e) {
092: // project doesn't exist
093: this .locations = new ClasspathLocation[0];
094: return;
095: }
096: int length = roots.length;
097: ClasspathLocation[] cpLocations = new ClasspathLocation[length];
098: int index = 0;
099: JavaModelManager manager = JavaModelManager
100: .getJavaModelManager();
101: for (int i = 0; i < length; i++) {
102: PackageFragmentRoot root = (PackageFragmentRoot) roots[i];
103: IPath path = root.getPath();
104: try {
105: if (root.isArchive()) {
106: ZipFile zipFile = manager.getZipFile(path);
107: cpLocations[index++] = new ClasspathJar(zipFile,
108: ((ClasspathEntry) root
109: .getRawClasspathEntry())
110: .getAccessRuleSet());
111: } else {
112: Object target = JavaModel.getTarget(workspaceRoot,
113: path, false);
114: if (target == null) {
115: // target doesn't exist any longer
116: // just resize cpLocations
117: System
118: .arraycopy(
119: cpLocations,
120: 0,
121: cpLocations = new ClasspathLocation[cpLocations.length - 1],
122: 0, index);
123: } else if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
124: cpLocations[index++] = new ClasspathSourceDirectory(
125: (IContainer) target, root
126: .fullExclusionPatternChars(),
127: root.fullInclusionPatternChars());
128: } else {
129: cpLocations[index++] = ClasspathLocation
130: .forBinaryFolder(
131: (IContainer) target,
132: false,
133: ((ClasspathEntry) root
134: .getRawClasspathEntry())
135: .getAccessRuleSet());
136: }
137: }
138: } catch (CoreException e1) {
139: // problem opening zip file or getting root kind
140: // consider root corrupt and ignore
141: // just resize cpLocations
142: System
143: .arraycopy(
144: cpLocations,
145: 0,
146: cpLocations = new ClasspathLocation[cpLocations.length - 1],
147: 0, index);
148: }
149: }
150: this .locations = cpLocations;
151: }
152:
153: private NameEnvironmentAnswer findClass(String qualifiedTypeName,
154: char[] typeName) {
155: String binaryFileName = null, qBinaryFileName = null, sourceFileName = null, qSourceFileName = null, qPackageName = null;
156: NameEnvironmentAnswer suggestedAnswer = null;
157: for (int i = 0, length = this .locations.length; i < length; i++) {
158: ClasspathLocation location = this .locations[i];
159: NameEnvironmentAnswer answer;
160: if (location instanceof ClasspathSourceDirectory) {
161: if (sourceFileName == null) {
162: qSourceFileName = qualifiedTypeName; // doesn't include the file extension
163: sourceFileName = qSourceFileName;
164: qPackageName = ""; //$NON-NLS-1$
165: if (qualifiedTypeName.length() > typeName.length) {
166: int typeNameStart = qSourceFileName.length()
167: - typeName.length;
168: qPackageName = qSourceFileName.substring(0,
169: typeNameStart - 1);
170: sourceFileName = qSourceFileName
171: .substring(typeNameStart);
172: }
173: }
174: ICompilationUnit workingCopy = (ICompilationUnit) this .workingCopies
175: .get(qualifiedTypeName);
176: if (workingCopy != null) {
177: answer = new NameEnvironmentAnswer(workingCopy,
178: null /*no access restriction*/);
179: } else {
180: answer = location.findClass(sourceFileName, // doesn't include the file extension
181: qPackageName, qSourceFileName); // doesn't include the file extension
182: }
183: } else {
184: if (binaryFileName == null) {
185: qBinaryFileName = qualifiedTypeName
186: + SUFFIX_STRING_class;
187: binaryFileName = qBinaryFileName;
188: qPackageName = ""; //$NON-NLS-1$
189: if (qualifiedTypeName.length() > typeName.length) {
190: int typeNameStart = qBinaryFileName.length()
191: - typeName.length - 6; // size of ".class"
192: qPackageName = qBinaryFileName.substring(0,
193: typeNameStart - 1);
194: binaryFileName = qBinaryFileName
195: .substring(typeNameStart);
196: }
197: }
198: answer = location.findClass(binaryFileName,
199: qPackageName, qBinaryFileName);
200: }
201: if (answer != null) {
202: if (!answer.ignoreIfBetter()) {
203: if (answer.isBetter(suggestedAnswer))
204: return answer;
205: } else if (answer.isBetter(suggestedAnswer))
206: // remember suggestion and keep looking
207: suggestedAnswer = answer;
208: }
209: }
210: if (suggestedAnswer != null)
211: // no better answer was found
212: return suggestedAnswer;
213: return null;
214: }
215:
216: public NameEnvironmentAnswer findType(char[] typeName,
217: char[][] packageName) {
218: if (typeName != null)
219: return findClass(new String(CharOperation.concatWith(
220: packageName, typeName, '/')), typeName);
221: return null;
222: }
223:
224: public NameEnvironmentAnswer findType(char[][] compoundName) {
225: if (compoundName != null)
226: return findClass(new String(CharOperation.concatWith(
227: compoundName, '/')),
228: compoundName[compoundName.length - 1]);
229: return null;
230: }
231:
232: public boolean isPackage(char[][] compoundName, char[] packageName) {
233: return isPackage(new String(CharOperation.concatWith(
234: compoundName, packageName, '/')));
235: }
236:
237: public boolean isPackage(String qualifiedPackageName) {
238: for (int i = 0, length = this .locations.length; i < length; i++)
239: if (this .locations[i].isPackage(qualifiedPackageName))
240: return true;
241: return false;
242: }
243:
244: }
|