improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / batch / ClasspathDirectory.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.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.env.NameEnvironmentAnswer;
17 import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
18
19 public class ClasspathDirectory implements FileSystem.Classpath, SuffixConstants {
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 (!this.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[]) this.directoryCache.get(qualifiedPackageName);
45         if (dirList == this.missingPackageHolder) return null; // package exists in another classpath directory or jar
46         if (dirList != null) return dirList;
47
48         File dir = new File(this.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))){/*empty*/}
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                 this.directoryCache.put(qualifiedPackageName, dirList);
69                 return dirList;
70         }
71         this.directoryCache.put(qualifiedPackageName, this.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 + SUFFIX_STRING_class, qualifiedPackageName);
88         boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + SUFFIX_STRING_php, qualifiedPackageName);
89         if (sourceExists) {
90                 String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_php;
91 //              if (!binaryExists)
92                         return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
93
94 //              String fullBinaryPath = this.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(this.path + qualifiedBinaryFileName);
103 //                      if (reader != null) return new NameEnvironmentAnswer(reader);
104 //              } catch (Exception e) { 
105 //                      // treat as if file is missing
106 //              }
107 //      }
108         return null;
109 }
110 public boolean isPackage(String qualifiedPackageName) {
111         return directoryList(qualifiedPackageName) != null;
112 }
113 public void reset() {
114         this.directoryCache = new Hashtable(11);
115 }
116 public String toString() {
117         return "ClasspathDirectory " + this.path; //$NON-NLS-1$
118 }
119 }