KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > batch > FileSystem


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.batch;
12
13 import java.io.File JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Set JavaDoc;
19
20 import org.eclipse.jdt.core.compiler.CharOperation;
21 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
22 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
23 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
24 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
25 import org.eclipse.jdt.internal.compiler.util.Util;
26
27 public class FileSystem implements INameEnvironment, SuffixConstants {
28     public interface Classpath {
29         char[][][] findTypeNames(String JavaDoc qualifiedPackageName);
30         NameEnvironmentAnswer findClass(char[] typeName, String JavaDoc qualifiedPackageName, String JavaDoc qualifiedBinaryFileName);
31         NameEnvironmentAnswer findClass(char[] typeName, String JavaDoc qualifiedPackageName, String JavaDoc qualifiedBinaryFileName, boolean asBinaryOnly);
32         boolean isPackage(String JavaDoc qualifiedPackageName);
33         /**
34          * This method resets the environment. The resulting state is equivalent to
35          * a new name environment without creating a new object.
36          */

37         void reset();
38         /**
39          * Return a normalized path for file based classpath entries. This is an absolute path
40          * ending with a file separator for directories, an absolute path deprived from the '.jar'
41          * (resp. '.zip') extension for jar (resp. zip) files.
42          * @return a normalized path for file based classpath entries
43          */

44         char[] normalizedPath();
45         /**
46          * Return the path for file based classpath entries. This is an absolute path
47          * ending with a file separator for directories, an absolute path including the '.jar'
48          * (resp. '.zip') extension for jar (resp. zip) files.
49          * @return the path for file based classpath entries
50          */

51         String JavaDoc getPath();
52         /**
53          * Initialize the entry
54          */

55         void initialize() throws IOException JavaDoc;
56     }
57
58     /**
59      * This class is defined how to normalize the classpath entries.
60      * It removes duplicate entries.
61      */

62     public static class ClasspathNormalizer {
63         /**
64          * Returns the normalized classpath entries (no duplicate).
65          * <p>The given classpath entries are FileSystem.Classpath. We check the getPath() in order to find
66          * duplicate entries.</p>
67          *
68          * @param classpaths the given classpath entries
69          * @return the normalized classpath entries
70          */

71         public static ArrayList JavaDoc normalize(ArrayList JavaDoc classpaths) {
72             ArrayList JavaDoc normalizedClasspath = new ArrayList JavaDoc();
73             HashSet JavaDoc cache = new HashSet JavaDoc();
74             for (Iterator JavaDoc iterator = classpaths.iterator(); iterator.hasNext(); ) {
75                 FileSystem.Classpath classpath = (FileSystem.Classpath) iterator.next();
76                 String JavaDoc path = classpath.getPath();
77                 if (!cache.contains(path)) {
78                     normalizedClasspath.add(classpath);
79                     cache.add(path);
80                 }
81             }
82             return normalizedClasspath;
83         }
84     }
85
86     Classpath[] classpaths;
87     Set JavaDoc knownFileNames;
88
89 /*
90     classPathNames is a collection is Strings representing the full path of each class path
91     initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
92 */

93 public FileSystem(String JavaDoc[] classpathNames, String JavaDoc[] initialFileNames, String JavaDoc encoding) {
94     final int classpathSize = classpathNames.length;
95     this.classpaths = new Classpath[classpathSize];
96     int counter = 0;
97     for (int i = 0; i < classpathSize; i++) {
98         Classpath classpath = getClasspath(classpathNames[i], encoding, null);
99         try {
100             classpath.initialize();
101             this.classpaths[counter++] = classpath;
102         } catch (IOException JavaDoc e) {
103             // ignore
104
}
105     }
106     if (counter != classpathSize) {
107         System.arraycopy(this.classpaths, 0, (this.classpaths = new Classpath[counter]), 0, counter);
108     }
109     initializeKnownFileNames(initialFileNames);
110 }
111 FileSystem(Classpath[] paths, String JavaDoc[] initialFileNames) {
112     final int length = paths.length;
113     int counter = 0;
114     this.classpaths = new FileSystem.Classpath[length];
115     for (int i = 0; i < length; i++) {
116         final Classpath classpath = paths[i];
117         try {
118             classpath.initialize();
119             this.classpaths[counter++] = classpath;
120         } catch(IOException JavaDoc exception) {
121             // ignore
122
}
123     }
124     if (counter != length) {
125         // should not happen
126
System.arraycopy(this.classpaths, 0, (this.classpaths = new FileSystem.Classpath[counter]), 0, counter);
127     }
128     initializeKnownFileNames(initialFileNames);
129 }
130 public static Classpath getClasspath(String JavaDoc classpathName, String JavaDoc encoding, AccessRuleSet accessRuleSet) {
131     return getClasspath(classpathName, encoding, false, accessRuleSet, null);
132 }
133 public static Classpath getClasspath(String JavaDoc classpathName, String JavaDoc encoding,
134         boolean isSourceOnly, AccessRuleSet accessRuleSet,
135         String JavaDoc destinationPath) {
136     Classpath result = null;
137     File JavaDoc file = new File JavaDoc(convertPathSeparators(classpathName));
138     if (file.isDirectory()) {
139         if (file.exists()) {
140             result = new ClasspathDirectory(file, encoding,
141                     isSourceOnly ? ClasspathLocation.SOURCE :
142                         ClasspathLocation.SOURCE | ClasspathLocation.BINARY,
143                     accessRuleSet,
144                     destinationPath == null || destinationPath == Main.NONE ?
145                         destinationPath : // keep == comparison valid
146
convertPathSeparators(destinationPath));
147         }
148     } else {
149         String JavaDoc lowercaseClasspathName = classpathName.toLowerCase();
150         if (lowercaseClasspathName.endsWith(SUFFIX_STRING_jar)
151                 || lowercaseClasspathName.endsWith(SUFFIX_STRING_zip)) {
152             if (isSourceOnly) {
153                 // source only mode
154
result = new ClasspathSourceJar(file, true, accessRuleSet,
155                     encoding,
156                     destinationPath == null || destinationPath == Main.NONE ?
157                         destinationPath : // keep == comparison valid
158
convertPathSeparators(destinationPath));
159             } else if (destinationPath == null) {
160                 // class file only mode
161
result = new ClasspathJar(file, true, accessRuleSet, null);
162             }
163         }
164     }
165     return result;
166 }
167 private void initializeKnownFileNames(String JavaDoc[] initialFileNames) {
168     if (initialFileNames == null) {
169         this.knownFileNames = new HashSet JavaDoc(0);
170         return;
171     }
172     this.knownFileNames = new HashSet JavaDoc(initialFileNames.length * 2);
173     for (int i = initialFileNames.length; --i >= 0;) {
174         char[] fileName = initialFileNames[i].toCharArray();
175         char[] matchingPathName = null;
176         final int lastIndexOf = CharOperation.lastIndexOf('.', fileName);
177         if (lastIndexOf != -1) {
178             fileName = CharOperation.subarray(fileName, 0, lastIndexOf);
179         }
180         CharOperation.replace(fileName, '\\', '/');
181         for (int j = 0; j < classpaths.length; j++){
182             char[] matchCandidate = this.classpaths[j].normalizedPath();
183             if (this.classpaths[j] instanceof ClasspathDirectory &&
184                     CharOperation.prefixEquals(matchCandidate, fileName) &&
185                     (matchingPathName == null ||
186                             matchCandidate.length < matchingPathName.length))
187                 matchingPathName = matchCandidate;
188         }
189         if (matchingPathName == null) {
190             this.knownFileNames.add(new String JavaDoc(fileName)); // leave as is...
191
} else {
192             this.knownFileNames.add(new String JavaDoc(CharOperation.subarray(fileName, matchingPathName.length, fileName.length)));
193         }
194         matchingPathName = null;
195     }
196 }
197 public void cleanup() {
198     for (int i = 0, max = this.classpaths.length; i < max; i++)
199         this.classpaths[i].reset();
200 }
201 private static String JavaDoc convertPathSeparators(String JavaDoc path) {
202     return File.separatorChar == '/'
203         ? path.replace('\\', '/')
204          : path.replace('/', '\\');
205 }
206 private NameEnvironmentAnswer findClass(String JavaDoc qualifiedTypeName, char[] typeName, boolean asBinaryOnly){
207     if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation
208

209     String JavaDoc qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
210     String JavaDoc qualifiedPackageName =
211         qualifiedTypeName.length() == typeName.length
212             ? Util.EMPTY_STRING
213             : qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
214     String JavaDoc qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
215     NameEnvironmentAnswer suggestedAnswer = null;
216     if (qualifiedPackageName == qp2) {
217         for (int i = 0, length = this.classpaths.length; i < length; i++) {
218             NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly);
219             if (answer != null) {
220                 if (!answer.ignoreIfBetter()) {
221                     if (answer.isBetter(suggestedAnswer))
222                         return answer;
223                 } else if (answer.isBetter(suggestedAnswer))
224                     // remember suggestion and keep looking
225
suggestedAnswer = answer;
226             }
227         }
228     } else {
229         String JavaDoc qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
230         for (int i = 0, length = this.classpaths.length; i < length; i++) {
231             Classpath p = this.classpaths[i];
232             NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
233                 ? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName, asBinaryOnly)
234                 : p.findClass(typeName, qp2, qb2, asBinaryOnly);
235             if (answer != null) {
236                 if (!answer.ignoreIfBetter()) {
237                     if (answer.isBetter(suggestedAnswer))
238                         return answer;
239                 } else if (answer.isBetter(suggestedAnswer))
240                     // remember suggestion and keep looking
241
suggestedAnswer = answer;
242             }
243         }
244     }
245     if (suggestedAnswer != null)
246         // no better answer was found
247
return suggestedAnswer;
248     return null;
249 }
250 public NameEnvironmentAnswer findType(char[][] compoundName) {
251     if (compoundName != null)
252         return findClass(
253             new String JavaDoc(CharOperation.concatWith(compoundName, '/')),
254             compoundName[compoundName.length - 1],
255             false);
256     return null;
257 }
258 public char[][][] findTypeNames(char[][] packageName) {
259     char[][][] result = null;
260     if (packageName != null) {
261         String JavaDoc qualifiedPackageName = new String JavaDoc(CharOperation.concatWith(packageName, '/'));
262         String JavaDoc qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
263         if (qualifiedPackageName == qualifiedPackageName2) {
264             for (int i = 0, length = this.classpaths.length; i < length; i++) {
265                 char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName);
266                 if (answers != null) {
267                     // concat with previous answers
268
if (result == null) {
269                         result = answers;
270                     } else {
271                         int resultLength = result.length;
272                         int answersLength = answers.length;
273                         System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
274                         System.arraycopy(answers, 0, result, resultLength, answersLength);
275                     }
276                 }
277             }
278         } else {
279             for (int i = 0, length = this.classpaths.length; i < length; i++) {
280                 Classpath p = this.classpaths[i];
281                 char[][][] answers = (p instanceof ClasspathJar)
282                     ? p.findTypeNames(qualifiedPackageName)
283                     : p.findTypeNames(qualifiedPackageName2);
284                 if (answers != null) {
285                     // concat with previous answers
286
if (result == null) {
287                         result = answers;
288                     } else {
289                         int resultLength = result.length;
290                         int answersLength = answers.length;
291                         System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
292                         System.arraycopy(answers, 0, result, resultLength, answersLength);
293                     }
294                 }
295             }
296         }
297     }
298     return result;
299 }
300 public NameEnvironmentAnswer findType(char[][] compoundName, boolean asBinaryOnly) {
301     if (compoundName != null)
302         return findClass(
303             new String JavaDoc(CharOperation.concatWith(compoundName, '/')),
304             compoundName[compoundName.length - 1],
305             asBinaryOnly);
306     return null;
307 }
308 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
309     if (typeName != null)
310         return findClass(
311             new String JavaDoc(CharOperation.concatWith(packageName, typeName, '/')),
312             typeName,
313             false);
314     return null;
315 }
316 public boolean isPackage(char[][] compoundName, char[] packageName) {
317     String JavaDoc qualifiedPackageName = new String JavaDoc(CharOperation.concatWith(compoundName, packageName, '/'));
318     String JavaDoc qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
319     if (qualifiedPackageName == qp2) {
320         for (int i = 0, length = this.classpaths.length; i < length; i++)
321             if (this.classpaths[i].isPackage(qualifiedPackageName))
322                 return true;
323     } else {
324         for (int i = 0, length = this.classpaths.length; i < length; i++) {
325             Classpath p = this.classpaths[i];
326             if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2))
327                 return true;
328         }
329     }
330     return false;
331 }
332 }
333
Popular Tags