1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.builder;
13 import java.io.DataInputStream;
14 import java.io.DataOutputStream;
15 import java.io.IOException;
16 import java.util.Date;
18 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
20 import org.eclipse.core.resources.IProject;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.resources.IResourceDelta;
23 import org.eclipse.core.runtime.IPath;
26 // NOTE: this state cannot contain types that are not defined in this project
28 String javaProjectName;
29 ClasspathMultiDirectory[] sourceLocations;
30 //ClasspathLocation[] binaryLocations;
31 // keyed by the project relative path of the type (ie. "src1/p1/p2/A.java"), value is a ReferenceCollection or an
32 // AdditionalTypeCollection
33 // SimpleLookupTable references;
34 // keyed by qualified type name "p1/p2/A", value is the project relative path which defines this type "src1/p1/p2/A.java"
35 // SimpleLookupTable typeLocators;
38 long lastStructuralBuildTime;
39 SimpleLookupTable structuralBuildTimes;
41 private String[] knownPackageNames; // of the form "p1/p2"
43 static final byte VERSION = 0x0007;
45 static final byte SOURCE_FOLDER = 1;
46 // static final byte BINARY_FOLDER = 2;
47 // static final byte EXTERNAL_JAR = 3;
48 // static final byte INTERNAL_JAR = 4;
53 protected State(PHPBuilder javaBuilder) {
54 this.knownPackageNames = null;
55 this.javaProjectName = javaBuilder.currentProject.getName();
56 this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations;
57 // this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
58 // this.references = new SimpleLookupTable(7);
59 // this.typeLocators = new SimpleLookupTable(7);
61 this.buildNumber = 0; // indicates a full build
62 this.lastStructuralBuildTime = System.currentTimeMillis();
63 this.structuralBuildTimes = new SimpleLookupTable(3);
66 void copyFrom(State lastState) {
68 this.knownPackageNames = null;
69 this.buildNumber = lastState.buildNumber + 1;
70 this.lastStructuralBuildTime = lastState.lastStructuralBuildTime;
71 // this.references = (SimpleLookupTable) lastState.references.clone();
72 // this.typeLocators = (SimpleLookupTable) lastState.typeLocators.clone();
73 // } catch (CloneNotSupportedException e) {
74 // this.references = new SimpleLookupTable(lastState.references.elementSize);
75 // Object[] keyTable = lastState.references.keyTable;
76 // Object[] valueTable = lastState.references.valueTable;
77 // for (int i = 0, l = keyTable.length; i < l; i++)
78 // if (keyTable[i] != null)
79 // this.references.put(keyTable[i], valueTable[i]);
81 // this.typeLocators = new SimpleLookupTable(lastState.typeLocators.elementSize);
82 // keyTable = lastState.typeLocators.keyTable;
83 // valueTable = lastState.typeLocators.valueTable;
84 // for (int i = 0, l = keyTable.length; i < l; i++)
85 // if (keyTable[i] != null)
86 // this.typeLocators.put(keyTable[i], valueTable[i]);
90 // char[][] getDefinedTypeNamesFor(String typeLocator) {
91 // Object c = references.get(typeLocator);
92 // if (c instanceof AdditionalTypeCollection)
93 // return ((AdditionalTypeCollection) c).definedTypeNames;
94 // return null; // means only one type is defined with the same name as the file... saves space
97 // boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator) {
98 // String existing = (String) typeLocators.get(qualifiedTypeName);
99 // return existing != null && !existing.equals(typeLocator);
102 // boolean isKnownPackage(String qualifiedPackageName) {
103 // if (knownPackageNames == null) {
104 // ArrayList names = new ArrayList(typeLocators.elementSize);
105 // Object[] keyTable = typeLocators.keyTable;
106 // for (int i = 0, l = keyTable.length; i < l; i++) {
107 // if (keyTable[i] != null) {
108 // String packageName = (String) keyTable[i]; // is a type name of the form p1/p2/A
109 // int last = packageName.lastIndexOf('/');
110 // packageName = last == -1 ? null : packageName.substring(0, last);
111 // while (packageName != null && !names.contains(packageName)) {
112 // names.add(packageName);
113 // last = packageName.lastIndexOf('/');
114 // packageName = last == -1 ? null : packageName.substring(0, last);
118 // knownPackageNames = new String[names.size()];
119 // names.toArray(knownPackageNames);
121 // for (int i = 0, l = knownPackageNames.length; i < l; i++)
122 // if (knownPackageNames[i].equals(qualifiedPackageName))
127 // void record(String typeLocator, char[][][] qualifiedRefs, char[][] simpleRefs, char[] mainTypeName, ArrayList typeNames) {
128 // if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[]) typeNames.get(0))) {
129 // references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs));
131 // char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty when no types are defined
132 // typeNames.toArray(definedTypeNames);
133 // references.put(typeLocator, new AdditionalTypeCollection(definedTypeNames, qualifiedRefs, simpleRefs));
137 // void recordLocatorForType(String qualifiedTypeName, String typeLocator) {
138 // this.knownPackageNames = null;
139 // typeLocators.put(qualifiedTypeName, typeLocator);
142 void recordStructuralDependency(IProject prereqProject, State prereqState) {
143 if (prereqState != null)
144 structuralBuildTimes.put(prereqProject.getName(), new Long(prereqState.lastStructuralBuildTime));
147 // void removeLocator(String typeLocatorToRemove) {
148 // this.knownPackageNames = null;
149 // references.removeKey(typeLocatorToRemove);
150 // typeLocators.removeValue(typeLocatorToRemove);
153 void removePackage(IResourceDelta sourceDelta) {
154 IResource resource = sourceDelta.getResource();
155 switch (resource.getType()) {
156 case IResource.FOLDER :
157 IResourceDelta[] children = sourceDelta.getAffectedChildren();
158 for (int i = 0, l = children.length; i < l; i++)
159 removePackage(children[i]);
161 case IResource.FILE :
162 IPath typeLocatorPath = resource.getProjectRelativePath();
163 // if (Util.isJavaFileName(typeLocatorPath.lastSegment()))
164 // removeLocator(typeLocatorPath.toString());
168 // void removeQualifiedTypeName(String qualifiedTypeNameToRemove) {
169 // this.knownPackageNames = null;
170 // typeLocators.removeKey(qualifiedTypeNameToRemove);
173 static State read(IProject project, DataInputStream in) throws IOException {
174 if (PHPBuilder.DEBUG)
175 System.out.println("About to read state..."); //$NON-NLS-1$
176 if (VERSION != in.readByte()) {
177 if (PHPBuilder.DEBUG)
178 System.out.println("Found non-compatible state version... answered null"); //$NON-NLS-1$
182 State newState = new State();
183 newState.javaProjectName = in.readUTF();
184 if (!project.getName().equals(newState.javaProjectName)) {
185 if (PHPBuilder.DEBUG)
186 System.out.println("Project's name does not match... answered null"); //$NON-NLS-1$
189 newState.buildNumber = in.readInt();
190 newState.lastStructuralBuildTime = in.readLong();
193 // int length = in.readInt();
194 // newState.sourceLocations = new ClasspathMultiDirectory[0];
195 // newState.sourceLocations = new ClasspathMultiDirectory[length];
196 // for (int i = 0; i < length; i++) {
197 // IContainer sourceFolder = project, outputFolder = project;
198 // String folderName;
199 // if ((folderName = in.readUTF()).length() > 0) sourceFolder = project.getFolder(folderName);
200 // if ((folderName = in.readUTF()).length() > 0) outputFolder = project.getFolder(folderName);
201 // ClasspathMultiDirectory md =
202 // (ClasspathMultiDirectory) ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, readNames(in));
203 // if (in.readBoolean())
204 // md.hasIndependentOutputFolder = true;
205 // newState.sourceLocations[i] = md;
208 // length = in.readInt();
209 // newState.binaryLocations = new ClasspathLocation[length];
210 // IWorkspaceRoot root = project.getWorkspace().getRoot();
211 // for (int i = 0; i < length; i++) {
212 // switch (in.readByte()) {
213 // case SOURCE_FOLDER :
214 // newState.binaryLocations[i] = newState.sourceLocations[in.readInt()];
216 // case BINARY_FOLDER :
217 // IPath path = new Path(in.readUTF());
218 // IContainer outputFolder = path.segmentCount() == 1
219 // ? (IContainer) root.getProject(path.toString())
220 // : (IContainer) root.getFolder(path);
221 // newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean());
223 // case EXTERNAL_JAR :
224 // newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF());
226 // case INTERNAL_JAR :
227 // newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())));
231 newState.structuralBuildTimes = new SimpleLookupTable(length = in.readInt());
232 for (int i = 0; i < length; i++)
233 newState.structuralBuildTimes.put(in.readUTF(), new Long(in.readLong()));
235 // String[] internedTypeLocators = new String[length = in.readInt()];
236 // for (int i = 0; i < length; i++)
237 // internedTypeLocators[i] = in.readUTF();
239 // newState.typeLocators = new SimpleLookupTable(length = in.readInt());
240 // for (int i = 0; i < length; i++)
241 // newState.typeLocators.put(in.readUTF(), internedTypeLocators[in.readInt()]);
243 // char[][] internedSimpleNames = ReferenceCollection.internSimpleNames(readNames(in), false);
244 // char[][][] internedQualifiedNames = new char[length = in.readInt()][][];
245 // for (int i = 0; i < length; i++) {
246 // int qLength = in.readInt();
247 // char[][] qName = new char[qLength][];
248 // for (int j = 0; j < qLength; j++)
249 // qName[j] = internedSimpleNames[in.readInt()];
250 // internedQualifiedNames[i] = qName;
252 // internedQualifiedNames = ReferenceCollection.internQualifiedNames(internedQualifiedNames);
254 // newState.references = new SimpleLookupTable(length = in.readInt());
255 // for (int i = 0; i < length; i++) {
256 // String typeLocator = internedTypeLocators[in.readInt()];
257 // ReferenceCollection collection = null;
258 // switch (in.readByte()) {
260 // char[][] additionalTypeNames = readNames(in);
261 // char[][][] qualifiedNames = new char[in.readInt()][][];
262 // for (int j = 0, m = qualifiedNames.length; j < m; j++)
263 // qualifiedNames[j] = internedQualifiedNames[in.readInt()];
264 // char[][] simpleNames = new char[in.readInt()][];
265 // for (int j = 0, m = simpleNames.length; j < m; j++)
266 // simpleNames[j] = internedSimpleNames[in.readInt()];
267 // collection = new AdditionalTypeCollection(additionalTypeNames, qualifiedNames, simpleNames);
270 // char[][][] qNames = new char[in.readInt()][][];
271 // for (int j = 0, m = qNames.length; j < m; j++)
272 // qNames[j] = internedQualifiedNames[in.readInt()];
273 // char[][] sNames = new char[in.readInt()][];
274 // for (int j = 0, m = sNames.length; j < m; j++)
275 // sNames[j] = internedSimpleNames[in.readInt()];
276 // collection = new ReferenceCollection(qNames, sNames);
278 // newState.references.put(typeLocator, collection);
280 if (PHPBuilder.DEBUG)
281 System.out.println("Successfully read state for " + newState.javaProjectName); //$NON-NLS-1$
285 private static char[][] readNames(DataInputStream in) throws IOException {
286 int length = in.readInt();
287 char[][] names = new char[length][];
288 for (int i = 0; i < length; i++) {
289 int nLength = in.readInt();
290 char[] name = new char[nLength];
291 for (int j = 0; j < nLength; j++)
292 name[j] = in.readChar();
298 void tagAsNoopBuild() {
299 this.buildNumber = -1; // tag the project since it has no source folders and can be skipped
302 boolean wasNoopBuild() {
303 return buildNumber == -1;
306 void tagAsStructurallyChanged() {
307 this.lastStructuralBuildTime = System.currentTimeMillis();
310 boolean wasStructurallyChanged(IProject prereqProject, State prereqState) {
311 if (prereqState != null) {
312 Object o = structuralBuildTimes.get(prereqProject.getName());
313 long previous = o == null ? 0 : ((Long) o).longValue();
314 if (previous == prereqState.lastStructuralBuildTime)
320 void write(DataOutputStream out) throws IOException {
326 * byte VERSION String project name int build number int last structural build number
328 out.writeByte(VERSION);
329 out.writeUTF(javaProjectName);
330 out.writeInt(buildNumber);
331 out.writeLong(lastStructuralBuildTime);
334 * ClasspathMultiDirectory[] int id String path(s)
336 // out.writeInt(length = sourceLocations.length);
337 // for (int i = 0; i < length; i++) {
338 // ClasspathMultiDirectory md = sourceLocations[i];
339 // out.writeUTF(md.sourceFolder.getProjectRelativePath().toString());
340 // out.writeUTF(md.binaryFolder.getProjectRelativePath().toString());
341 // writeNames(md.exclusionPatterns, out);
342 // out.writeBoolean(md.hasIndependentOutputFolder);
346 * ClasspathLocation[] int id String path(s)
348 // out.writeInt(length = binaryLocations.length);
349 // next : for (int i = 0; i < length; i++) {
350 // ClasspathLocation c = binaryLocations[i];
351 // if (c instanceof ClasspathMultiDirectory) {
352 // out.writeByte(SOURCE_FOLDER);
353 // for (int j = 0, m = sourceLocations.length; j < m; j++) {
354 // if (sourceLocations[j] == c) {
359 // } else if (c instanceof ClasspathDirectory) {
360 // out.writeByte(BINARY_FOLDER);
361 // ClasspathDirectory cd = (ClasspathDirectory) c;
362 // out.writeUTF(cd.binaryFolder.getFullPath().toString());
363 // out.writeBoolean(cd.isOutputFolder);
365 // ClasspathJar jar = (ClasspathJar) c;
366 // if (jar.resource == null) {
367 // out.writeByte(EXTERNAL_JAR);
368 // out.writeUTF(jar.zipFilename);
370 // out.writeByte(INTERNAL_JAR);
371 // out.writeUTF(jar.resource.getFullPath().toString());
377 * Structural build numbers table String prereq project name int last structural build number
379 out.writeInt(length = structuralBuildTimes.elementSize);
381 keyTable = structuralBuildTimes.keyTable;
382 valueTable = structuralBuildTimes.valueTable;
383 for (int i = 0, l = keyTable.length; i < l; i++) {
384 if (keyTable[i] != null) {
386 out.writeUTF((String) keyTable[i]);
387 out.writeLong(((Long) valueTable[i]).longValue());
390 if (PHPBuilder.DEBUG && length != 0)
391 System.out.println("structuralBuildNumbers table is inconsistent"); //$NON-NLS-1$
395 * String[] Interned type locators
397 // out.writeInt(length = references.elementSize);
398 // ArrayList internedTypeLocators = new ArrayList(length);
400 // keyTable = references.keyTable;
401 // for (int i = 0, l = keyTable.length; i < l; i++) {
402 // if (keyTable[i] != null) {
404 // String key = (String) keyTable[i];
405 // out.writeUTF(key);
406 // internedTypeLocators.add(key);
409 // if (PHPBuilder.DEBUG && length != 0)
410 // System.out.println("references table is inconsistent"); //$NON-NLS-1$
414 * Type locators table String type name int interned locator id
416 // out.writeInt(length = typeLocators.elementSize);
418 // keyTable = typeLocators.keyTable;
419 // valueTable = typeLocators.valueTable;
420 // for (int i = 0, l = keyTable.length; i < l; i++) {
421 // if (keyTable[i] != null) {
423 // out.writeUTF((String) keyTable[i]);
424 // out.writeInt(internedTypeLocators.indexOf((String) valueTable[i]));
427 // if (PHPBuilder.DEBUG && length != 0)
428 // System.out.println("typeLocators table is inconsistent"); //$NON-NLS-1$
432 * char[][][] Interned qualified names char[][] Interned simple names
434 // ArrayList internedQualifiedNames = new ArrayList(31);
435 // ArrayList internedSimpleNames = new ArrayList(31);
436 // valueTable = references.valueTable;
437 // for (int i = 0, l = valueTable.length; i < l; i++) {
438 // if (valueTable[i] != null) {
439 // ReferenceCollection collection = (ReferenceCollection) valueTable[i];
440 // char[][][] qNames = collection.qualifiedNameReferences;
441 // for (int j = 0, m = qNames.length; j < m; j++) {
442 // char[][] qName = qNames[j];
443 // if (!internedQualifiedNames.contains(qName)) { // remember the names have been interned
444 // internedQualifiedNames.add(qName);
445 // for (int k = 0, n = qName.length; k < n; k++) {
446 // char[] sName = qName[k];
447 // if (!internedSimpleNames.contains(sName)) // remember the names have been interned
448 // internedSimpleNames.add(sName);
452 // char[][] sNames = collection.simpleNameReferences;
453 // for (int j = 0, m = sNames.length; j < m; j++) {
454 // char[] sName = sNames[j];
455 // if (!internedSimpleNames.contains(sName)) // remember the names have been interned
456 // internedSimpleNames.add(sName);
460 // char[][] internedArray = new char[internedSimpleNames.size()][];
461 // internedSimpleNames.toArray(internedArray);
462 // writeNames(internedArray, out);
463 // // now write the interned qualified names as arrays of interned simple names
464 // out.writeInt(length = internedQualifiedNames.size());
465 // for (int i = 0; i < length; i++) {
466 // char[][] qName = (char[][]) internedQualifiedNames.get(i);
467 // int qLength = qName.length;
468 // out.writeInt(qLength);
469 // for (int j = 0; j < qLength; j++)
470 // out.writeInt(internedSimpleNames.indexOf(qName[j]));
474 // * References table int interned locator id ReferenceCollection
476 // out.writeInt(length = references.elementSize);
478 // keyTable = references.keyTable;
479 // for (int i = 0, l = keyTable.length; i < l; i++) {
480 // if (keyTable[i] != null) {
482 // out.writeInt(internedTypeLocators.indexOf((String) keyTable[i]));
483 // ReferenceCollection collection = (ReferenceCollection) valueTable[i];
484 // if (collection instanceof AdditionalTypeCollection) {
486 // AdditionalTypeCollection atc = (AdditionalTypeCollection) collection;
487 // writeNames(atc.definedTypeNames, out);
491 // char[][][] qNames = collection.qualifiedNameReferences;
492 // int qLength = qNames.length;
493 // out.writeInt(qLength);
494 // for (int j = 0; j < qLength; j++)
495 // out.writeInt(internedQualifiedNames.indexOf(qNames[j]));
496 // char[][] sNames = collection.simpleNameReferences;
497 // int sLength = sNames.length;
498 // out.writeInt(sLength);
499 // for (int j = 0; j < sLength; j++)
500 // out.writeInt(internedSimpleNames.indexOf(sNames[j]));
503 // if (PHPBuilder.DEBUG && length != 0)
504 // System.out.println("references table is inconsistent"); //$NON-NLS-1$
508 private void writeNames(char[][] names, DataOutputStream out) throws IOException {
509 int length = names == null ? 0 : names.length;
510 out.writeInt(length);
511 for (int i = 0; i < length; i++) {
512 char[] name = names[i];
513 int nLength = name.length;
514 out.writeInt(nLength);
515 for (int j = 0; j < nLength; j++)
516 out.writeChar(name[j]);
521 * Returns a string representation of the receiver.
523 public String toString() {
524 return "State for " + javaProjectName //$NON-NLS-1$
525 +" (#" + buildNumber //$NON-NLS-1$
526 +" @ " + new Date(lastStructuralBuildTime) //$NON-NLS-1$
531 * Debug helper void dump() { System.out.println("State for " + javaProjectName + " (" + buildNumber + " @ " + new
532 * Date(lastStructuralBuildTime) + ")"); System.out.println("\tClass path source locations:"); for (int i = 0, l =
533 * sourceLocations.length; i < l; i++) System.out.println("\t\t" + sourceLocations[i]); System.out.println("\tClass path binary
534 * locations:"); for (int i = 0, l = binaryLocations.length; i < l; i++) System.out.println("\t\t" + binaryLocations[i]);
536 * System.out.print("\tStructural build numbers table:"); if (structuralBuildTimes.elementSize == 0) { System.out.print(" <empty>
537 * "); } else { Object[] keyTable = structuralBuildTimes.keyTable; Object[] valueTable = structuralBuildTimes.valueTable; for
538 * (int i = 0, l = keyTable.length; i < l; i++) if (keyTable[i] != null) System.out.print("\n\t\t" + keyTable[i].toString() + " -> " +
539 * valueTable[i].toString()); }
541 * System.out.print("\tType locators table:"); if (typeLocators.elementSize == 0) { System.out.print(" <empty> "); } else {
542 * Object[] keyTable = typeLocators.keyTable; Object[] valueTable = typeLocators.valueTable; for (int i = 0, l = keyTable.length;
543 * i < l; i++) if (keyTable[i] != null) System.out.print("\n\t\t" + keyTable[i].toString() + " -> " + valueTable[i].toString()); }
545 * System.out.print("\n\tReferences table:"); if (references.elementSize == 0) { System.out.print(" <empty> "); } else { Object[]
546 * keyTable = references.keyTable; Object[] valueTable = references.valueTable; for (int i = 0, l = keyTable.length; i
547 * < l; i++) { if (keyTable[i] != null) { System.out.print("\n\t\t" + keyTable[i].toString()); ReferenceCollection c =
548 * (ReferenceCollection) valueTable[i]; char[][][] qRefs = c.qualifiedNameReferences; System.out.print("\n\t\t\tqualified:"); if
549 * (qRefs.length == 0) System.out.print(" <empty> "); else for (int j = 0, m = qRefs.length; j < m; j++) System.out.print(" '" +
550 * CharOperation.toString(qRefs[j]) + "'"); char[][] sRefs = c.simpleNameReferences; System.out.print("\n\t\t\tsimple:"); if
551 * (sRefs.length == 0) System.out.print(" <empty> "); else for (int j = 0, m = sRefs.length; j < m; j++) System.out.print(" " +
552 * new String(sRefs[j])); if (c instanceof AdditionalTypeCollection) { char[][] names = ((AdditionalTypeCollection)
553 * c).definedTypeNames; System.out.print("\n\t\t\tadditional type names:"); for (int j = 0, m = names.length; j < m; j++)
554 * System.out.print(" " + new String(names[j])); } } } } System.out.print("\n\n"); }