first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / batch / FileSystem.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.io.IOException;
15 import java.util.zip.ZipFile;
16
17 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
18 import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
19 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
20
21 public class FileSystem implements INameEnvironment  {
22         Classpath[] classpaths;
23         String[] knownFileNames;
24
25         interface Classpath {
26                 NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
27                 boolean isPackage(String qualifiedPackageName); 
28                 /**
29                  * This method resets the environment. The resulting state is equivalent to
30                  * a new name environment without creating a new object.
31                  */
32                 void reset();
33         }
34 /*
35         classPathNames is a collection is Strings representing the full path of each class path
36         initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
37 */
38
39 public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding) {
40         this(classpathNames, initialFileNames, encoding, null);
41 }
42 public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding, int[] classpathDirectoryModes) {
43         int classpathSize = classpathNames.length;
44         classpaths = new Classpath[classpathSize];
45         String[] pathNames = new String[classpathSize];
46         int problemsOccured = 0;
47         for (int i = 0; i < classpathSize; i++) {
48                 try {
49                         File file = new File(convertPathSeparators(classpathNames[i]));
50                         if (file.isDirectory()) {
51                                 if (file.exists()) {
52                                         if (classpathDirectoryModes == null){
53                                                 classpaths[i] = new ClasspathDirectory(file, encoding);
54                                         } else {
55                                                 classpaths[i] = new ClasspathDirectory(file, encoding, classpathDirectoryModes[i]);
56                                         }
57                                         pathNames[i] = ((ClasspathDirectory) classpaths[i]).path;
58                                 }
59                         } else if (classpathNames[i].endsWith(".jar") | (classpathNames[i].endsWith(".zip"))) { //$NON-NLS-2$ //$NON-NLS-1$
60                                 classpaths[i] = this.getClasspathJar(file); // will throw an IOException if file does not exist
61                                 pathNames[i] = classpathNames[i].substring(0, classpathNames[i].lastIndexOf('.'));
62                         }
63                 } catch (IOException e) {
64                         classpaths[i] = null;
65                 }
66                 if (classpaths[i] == null)
67                         problemsOccured++;
68         }
69         if (problemsOccured > 0) {
70                 Classpath[] newPaths = new Classpath[classpathSize - problemsOccured];
71                 String[] newNames = new String[classpathSize - problemsOccured];
72                 for (int i = 0, current = 0; i < classpathSize; i++)
73                         if (classpaths[i] != null) {
74                                 newPaths[current] = classpaths[i];
75                                 newNames[current++] = pathNames[i];
76                         }
77                 classpathSize = newPaths.length;
78                 classpaths = newPaths;
79                 pathNames = newNames;
80         }
81
82         knownFileNames = new String[initialFileNames.length];
83         for (int i = initialFileNames.length; --i >= 0;) {
84                 String fileName = initialFileNames[i];
85                 String matchingPathName = null;
86                 if (fileName.lastIndexOf(".") != -1) //$NON-NLS-1$
87                         fileName = fileName.substring(0, fileName.lastIndexOf('.')); // remove trailing ".java"
88
89                 fileName = convertPathSeparators(fileName);
90                 for (int j = 0; j < classpathSize; j++)
91                         if (fileName.startsWith(pathNames[j]))
92                                 matchingPathName = pathNames[j];
93                 if (matchingPathName == null)
94                         knownFileNames[i] = fileName; // leave as is...
95                 else
96                         knownFileNames[i] = fileName.substring(matchingPathName.length());
97         }
98 }
99 public void cleanup() {
100         for (int i = 0, max = classpaths.length; i < max; i++)
101                 classpaths[i].reset();
102 }
103 private String convertPathSeparators(String path) {
104         return File.separatorChar == '/'
105                 ? path.replace('\\', '/')
106                  : path.replace('/', '\\');
107 }
108 private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName){
109         for (int i = 0, length = knownFileNames.length; i < length; i++)
110                 if (qualifiedTypeName.equals(knownFileNames[i]))
111                         return null; // looking for a file which we know was provided at the beginning of the compilation
112
113         String qualifiedBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
114         String qualifiedPackageName =
115                 qualifiedTypeName.length() == typeName.length
116                         ? "" //$NON-NLS-1$
117                         : qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
118         String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
119         if (qualifiedPackageName == qp2) {
120                 for (int i = 0, length = classpaths.length; i < length; i++) {
121                         NameEnvironmentAnswer answer = classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
122                         if (answer != null) return answer;
123                 }
124         } else {
125                 String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
126                 for (int i = 0, length = classpaths.length; i < length; i++) {
127                         Classpath p = classpaths[i];
128                         NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
129                                 ? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName)
130                                 : p.findClass(typeName, qp2, qb2);
131                         if (answer != null) return answer;
132                 }
133         }
134         return null;
135 }
136 public NameEnvironmentAnswer findType(char[][] compoundName) {
137         if (compoundName != null)
138                 return findClass(
139                         new String(CharOperation.concatWith(compoundName, '/')),
140                         compoundName[compoundName.length - 1]);
141         return null;
142 }
143 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
144         if (typeName != null)
145                 return findClass(
146                         new String(CharOperation.concatWith(packageName, typeName, '/')),
147                         typeName);
148         return null;
149 }
150 public ClasspathJar getClasspathJar(File file) throws IOException {
151         return new ClasspathJar(new ZipFile(file), true);
152 }
153 public boolean isPackage(char[][] compoundName, char[] packageName) {
154         String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
155         String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
156         if (qualifiedPackageName == qp2) {
157                 for (int i = 0, length = classpaths.length; i < length; i++)
158                         if (classpaths[i].isPackage(qualifiedPackageName))
159                                 return true;
160         } else {
161                 for (int i = 0, length = classpaths.length; i < length; i++) {
162                         Classpath p = classpaths[i];
163                         if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2))
164                                 return true;
165                 }
166         }
167         return false;
168 }
169 }