18a7a1ba75d4a95a7a06e9570bc31e6ff6404710
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / batch / ClasspathDirectory.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.batch;
12
13 import java.io.File;
14 import java.util.Hashtable;
15
16 import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileReader;
17 import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
18
19 public class ClasspathDirectory implements FileSystem.Classpath {
20
21 String path;
22 Hashtable directoryCache;
23 String[] missingPackageHolder = new String[1];
24 String encoding;
25 public int mode; // ability to only consider one kind of files (source vs. binaries), by default use both
26
27 public static final int SOURCE = 1;
28 public static final int BINARY = 2;
29
30 ClasspathDirectory(File directory, String encoding, int mode) {
31         this.mode = mode;
32         this.path = directory.getAbsolutePath();
33         if (!path.endsWith(File.separator))
34                 this.path += File.separator;
35         this.directoryCache = new Hashtable(11);
36         this.encoding = encoding;
37 }
38
39 ClasspathDirectory(File directory, String encoding) {
40         this(directory, encoding, SOURCE | BINARY); // by default consider both sources and binaries
41 }
42
43 String[] directoryList(String qualifiedPackageName) {
44         String[] dirList = (String[]) directoryCache.get(qualifiedPackageName);
45         if (dirList == missingPackageHolder) return null; // package exists in another classpath directory or jar
46         if (dirList != null) return dirList;
47
48         File dir = new File(path + qualifiedPackageName);
49         notFound : if (dir != null && dir.isDirectory()) {
50                 // must protect against a case insensitive File call
51                 // walk the qualifiedPackageName backwards looking for an uppercase character before the '/'
52                 int index = qualifiedPackageName.length();
53                 int last = qualifiedPackageName.lastIndexOf(File.separatorChar);
54                 while (--index > last && !Character.isUpperCase(qualifiedPackageName.charAt(index))) {}
55                 if (index > last) {
56                         if (last == -1) {
57                                 if (!doesFileExist(qualifiedPackageName, ""))  //$NON-NLS-1$ 
58                                         break notFound;
59                         } else {
60                                 String packageName = qualifiedPackageName.substring(last + 1);
61                                 String parentPackage = qualifiedPackageName.substring(0, last);
62                                 if (!doesFileExist(packageName, parentPackage))
63                                         break notFound;
64                         }
65                 }
66                 if ((dirList = dir.list()) == null)
67                         dirList = new String[0];
68                 directoryCache.put(qualifiedPackageName, dirList);
69                 return dirList;
70         }
71         directoryCache.put(qualifiedPackageName, missingPackageHolder);
72         return null;
73 }
74 boolean doesFileExist(String fileName, String qualifiedPackageName) {
75         String[] dirList = directoryList(qualifiedPackageName);
76         if (dirList == null) return false; // most common case
77
78         for (int i = dirList.length; --i >= 0;)
79                 if (fileName.equals(dirList[i]))
80                         return true;
81         return false;
82 }
83 public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
84         if (!isPackage(qualifiedPackageName)) return null; // most common case
85
86         String fileName = new String(typeName);
87         boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + ".class", qualifiedPackageName); //$NON-NLS-1$
88         boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + ".java", qualifiedPackageName); //$NON-NLS-1$
89         if (sourceExists) {
90                 String fullSourcePath = path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + ".java"; //$NON-NLS-1$
91                 if (!binaryExists)
92                         return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
93
94                 String fullBinaryPath = path + qualifiedBinaryFileName;
95                 long binaryModified = new File(fullBinaryPath).lastModified();
96                 long sourceModified = new File(fullSourcePath).lastModified();
97                 if (sourceModified > binaryModified)
98                         return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
99         }
100         if (binaryExists) {
101                 try {
102                         ClassFileReader reader = ClassFileReader.read(path + qualifiedBinaryFileName);
103                         if (reader != null) return new NameEnvironmentAnswer(reader);
104                 } catch (Exception e) {} // treat as if file is missing
105         }
106         return null;
107 }
108 public boolean isPackage(String qualifiedPackageName) {
109         return directoryList(qualifiedPackageName) != null;
110 }
111 public void reset() {
112         this.directoryCache = new Hashtable(11);
113 }
114 public String toString() {
115         return "ClasspathDirectory " + path; //$NON-NLS-1$
116 }
117 }