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
29 String javaProjectName;
31 ClasspathMultiDirectory[] sourceLocations;
33 // ClasspathLocation[] binaryLocations;
34 // keyed by the project relative path of the type (ie. "src1/p1/p2/A.java"),
35 // value is a ReferenceCollection or an
36 // AdditionalTypeCollection
37 // SimpleLookupTable references;
38 // keyed by qualified type name "p1/p2/A", value is the project relative
39 // path which defines this type "src1/p1/p2/A.java"
40 // SimpleLookupTable typeLocators;
44 long lastStructuralBuildTime;
46 SimpleLookupTable structuralBuildTimes;
48 private String[] knownPackageNames; // of the form "p1/p2"
50 static final byte VERSION = 0x0007;
52 static final byte SOURCE_FOLDER = 1;
54 // static final byte BINARY_FOLDER = 2;
55 // static final byte EXTERNAL_JAR = 3;
56 // static final byte INTERNAL_JAR = 4;
61 protected State(PHPBuilder javaBuilder) {
62 this.knownPackageNames = null;
63 this.javaProjectName = javaBuilder.currentProject.getName();
64 this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations;
65 // this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
66 // this.references = new SimpleLookupTable(7);
67 // this.typeLocators = new SimpleLookupTable(7);
69 this.buildNumber = 0; // indicates a full build
70 this.lastStructuralBuildTime = System.currentTimeMillis();
71 this.structuralBuildTimes = new SimpleLookupTable(3);
74 void copyFrom(State lastState) {
76 this.knownPackageNames = null;
77 this.buildNumber = lastState.buildNumber + 1;
78 this.lastStructuralBuildTime = lastState.lastStructuralBuildTime;
79 // this.references = (SimpleLookupTable) lastState.references.clone();
80 // this.typeLocators = (SimpleLookupTable)
81 // lastState.typeLocators.clone();
82 // } catch (CloneNotSupportedException e) {
83 // this.references = new
84 // SimpleLookupTable(lastState.references.elementSize);
85 // Object[] keyTable = lastState.references.keyTable;
86 // Object[] valueTable = lastState.references.valueTable;
87 // for (int i = 0, l = keyTable.length; i < l; i++)
88 // if (keyTable[i] != null)
89 // this.references.put(keyTable[i], valueTable[i]);
91 // this.typeLocators = new
92 // SimpleLookupTable(lastState.typeLocators.elementSize);
93 // keyTable = lastState.typeLocators.keyTable;
94 // valueTable = lastState.typeLocators.valueTable;
95 // for (int i = 0, l = keyTable.length; i < l; i++)
96 // if (keyTable[i] != null)
97 // this.typeLocators.put(keyTable[i], valueTable[i]);
101 // char[][] getDefinedTypeNamesFor(String typeLocator) {
102 // Object c = references.get(typeLocator);
103 // if (c instanceof AdditionalTypeCollection)
104 // return ((AdditionalTypeCollection) c).definedTypeNames;
105 // return null; // means only one type is defined with the same name as the
106 // file... saves space
109 // boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator)
111 // String existing = (String) typeLocators.get(qualifiedTypeName);
112 // return existing != null && !existing.equals(typeLocator);
115 // boolean isKnownPackage(String qualifiedPackageName) {
116 // if (knownPackageNames == null) {
117 // ArrayList names = new ArrayList(typeLocators.elementSize);
118 // Object[] keyTable = typeLocators.keyTable;
119 // for (int i = 0, l = keyTable.length; i < l; i++) {
120 // if (keyTable[i] != null) {
121 // String packageName = (String) keyTable[i]; // is a type name of the form
123 // int last = packageName.lastIndexOf('/');
124 // packageName = last == -1 ? null : packageName.substring(0, last);
125 // while (packageName != null && !names.contains(packageName)) {
126 // names.add(packageName);
127 // last = packageName.lastIndexOf('/');
128 // packageName = last == -1 ? null : packageName.substring(0, last);
132 // knownPackageNames = new String[names.size()];
133 // names.toArray(knownPackageNames);
135 // for (int i = 0, l = knownPackageNames.length; i < l; i++)
136 // if (knownPackageNames[i].equals(qualifiedPackageName))
141 // void record(String typeLocator, char[][][] qualifiedRefs, char[][]
142 // simpleRefs, char[] mainTypeName, ArrayList typeNames) {
143 // if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[])
144 // typeNames.get(0))) {
145 // references.put(typeLocator, new ReferenceCollection(qualifiedRefs,
148 // char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty
149 // when no types are defined
150 // typeNames.toArray(definedTypeNames);
151 // references.put(typeLocator, new
152 // AdditionalTypeCollection(definedTypeNames, qualifiedRefs, simpleRefs));
156 // void recordLocatorForType(String qualifiedTypeName, String typeLocator) {
157 // this.knownPackageNames = null;
158 // typeLocators.put(qualifiedTypeName, typeLocator);
161 void recordStructuralDependency(IProject prereqProject, State prereqState) {
162 if (prereqState != null)
163 structuralBuildTimes.put(prereqProject.getName(), new Long(
164 prereqState.lastStructuralBuildTime));
167 // void removeLocator(String typeLocatorToRemove) {
168 // this.knownPackageNames = null;
169 // references.removeKey(typeLocatorToRemove);
170 // typeLocators.removeValue(typeLocatorToRemove);
173 void removePackage(IResourceDelta sourceDelta) {
174 IResource resource = sourceDelta.getResource();
175 switch (resource.getType()) {
176 case IResource.FOLDER:
177 IResourceDelta[] children = sourceDelta.getAffectedChildren();
178 for (int i = 0, l = children.length; i < l; i++)
179 removePackage(children[i]);
182 IPath typeLocatorPath = resource.getProjectRelativePath();
184 // (ProjectPrefUtil.isJavaFileName(typeLocatorPath.lastSegment()))
185 // removeLocator(typeLocatorPath.toString());
189 // void removeQualifiedTypeName(String qualifiedTypeNameToRemove) {
190 // this.knownPackageNames = null;
191 // typeLocators.removeKey(qualifiedTypeNameToRemove);
194 static State read(IProject project, DataInputStream in) throws IOException {
195 if (PHPBuilder.DEBUG)
196 System.out.println("About to read state..."); //$NON-NLS-1$
197 if (VERSION != in.readByte()) {
198 if (PHPBuilder.DEBUG)
200 .println("Found non-compatible state version... answered null"); //$NON-NLS-1$
204 State newState = new State();
205 newState.javaProjectName = in.readUTF();
206 if (!project.getName().equals(newState.javaProjectName)) {
207 if (PHPBuilder.DEBUG)
209 .println("Project's name does not match... answered null"); //$NON-NLS-1$
212 newState.buildNumber = in.readInt();
213 newState.lastStructuralBuildTime = in.readLong();
216 // int length = in.readInt();
217 // newState.sourceLocations = new ClasspathMultiDirectory[0];
218 // newState.sourceLocations = new ClasspathMultiDirectory[length];
219 // for (int i = 0; i < length; i++) {
220 // IContainer sourceFolder = project, outputFolder = project;
221 // String folderName;
222 // if ((folderName = in.readUTF()).length() > 0) sourceFolder =
223 // project.getFolder(folderName);
224 // if ((folderName = in.readUTF()).length() > 0) outputFolder =
225 // project.getFolder(folderName);
226 // ClasspathMultiDirectory md =
227 // (ClasspathMultiDirectory)
228 // ClasspathLocation.forSourceFolder(sourceFolder, outputFolder,
230 // if (in.readBoolean())
231 // md.hasIndependentOutputFolder = true;
232 // newState.sourceLocations[i] = md;
235 // length = in.readInt();
236 // newState.binaryLocations = new ClasspathLocation[length];
237 // IWorkspaceRoot root = project.getWorkspace().getRoot();
238 // for (int i = 0; i < length; i++) {
239 // switch (in.readByte()) {
240 // case SOURCE_FOLDER :
241 // newState.binaryLocations[i] = newState.sourceLocations[in.readInt()];
243 // case BINARY_FOLDER :
244 // IPath path = new Path(in.readUTF());
245 // IContainer outputFolder = path.segmentCount() == 1
246 // ? (IContainer) root.getProject(path.toString())
247 // : (IContainer) root.getFolder(path);
248 // newState.binaryLocations[i] =
249 // ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean());
251 // case EXTERNAL_JAR :
252 // newState.binaryLocations[i] =
253 // ClasspathLocation.forLibrary(in.readUTF());
255 // case INTERNAL_JAR :
256 // newState.binaryLocations[i] =
257 // ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())));
261 newState.structuralBuildTimes = new SimpleLookupTable(length = in
263 for (int i = 0; i < length; i++)
264 newState.structuralBuildTimes.put(in.readUTF(), new Long(in
267 // String[] internedTypeLocators = new String[length = in.readInt()];
268 // for (int i = 0; i < length; i++)
269 // internedTypeLocators[i] = in.readUTF();
271 // newState.typeLocators = new SimpleLookupTable(length = in.readInt());
272 // for (int i = 0; i < length; i++)
273 // newState.typeLocators.put(in.readUTF(),
274 // internedTypeLocators[in.readInt()]);
276 // char[][] internedSimpleNames =
277 // ReferenceCollection.internSimpleNames(readNames(in), false);
278 // char[][][] internedQualifiedNames = new char[length =
279 // in.readInt()][][];
280 // for (int i = 0; i < length; i++) {
281 // int qLength = in.readInt();
282 // char[][] qName = new char[qLength][];
283 // for (int j = 0; j < qLength; j++)
284 // qName[j] = internedSimpleNames[in.readInt()];
285 // internedQualifiedNames[i] = qName;
287 // internedQualifiedNames =
288 // ReferenceCollection.internQualifiedNames(internedQualifiedNames);
290 // newState.references = new SimpleLookupTable(length = in.readInt());
291 // for (int i = 0; i < length; i++) {
292 // String typeLocator = internedTypeLocators[in.readInt()];
293 // ReferenceCollection collection = null;
294 // switch (in.readByte()) {
296 // char[][] additionalTypeNames = readNames(in);
297 // char[][][] qualifiedNames = new char[in.readInt()][][];
298 // for (int j = 0, m = qualifiedNames.length; j < m; j++)
299 // qualifiedNames[j] = internedQualifiedNames[in.readInt()];
300 // char[][] simpleNames = new char[in.readInt()][];
301 // for (int j = 0, m = simpleNames.length; j < m; j++)
302 // simpleNames[j] = internedSimpleNames[in.readInt()];
303 // collection = new AdditionalTypeCollection(additionalTypeNames,
304 // qualifiedNames, simpleNames);
307 // char[][][] qNames = new char[in.readInt()][][];
308 // for (int j = 0, m = qNames.length; j < m; j++)
309 // qNames[j] = internedQualifiedNames[in.readInt()];
310 // char[][] sNames = new char[in.readInt()][];
311 // for (int j = 0, m = sNames.length; j < m; j++)
312 // sNames[j] = internedSimpleNames[in.readInt()];
313 // collection = new ReferenceCollection(qNames, sNames);
315 // newState.references.put(typeLocator, collection);
317 if (PHPBuilder.DEBUG)
319 .println("Successfully read state for " + newState.javaProjectName); //$NON-NLS-1$
323 private static char[][] readNames(DataInputStream in) throws IOException {
324 int length = in.readInt();
325 char[][] names = new char[length][];
326 for (int i = 0; i < length; i++) {
327 int nLength = in.readInt();
328 char[] name = new char[nLength];
329 for (int j = 0; j < nLength; j++)
330 name[j] = in.readChar();
336 void tagAsNoopBuild() {
337 this.buildNumber = -1; // tag the project since it has no source
338 // folders and can be skipped
341 boolean wasNoopBuild() {
342 return buildNumber == -1;
345 void tagAsStructurallyChanged() {
346 this.lastStructuralBuildTime = System.currentTimeMillis();
349 boolean wasStructurallyChanged(IProject prereqProject, State prereqState) {
350 if (prereqState != null) {
351 Object o = structuralBuildTimes.get(prereqProject.getName());
352 long previous = o == null ? 0 : ((Long) o).longValue();
353 if (previous == prereqState.lastStructuralBuildTime)
359 void write(DataOutputStream out) throws IOException {
365 * byte VERSION String project name int build number int last structural
368 out.writeByte(VERSION);
369 out.writeUTF(javaProjectName);
370 out.writeInt(buildNumber);
371 out.writeLong(lastStructuralBuildTime);
374 * ClasspathMultiDirectory[] int id String path(s)
376 // out.writeInt(length = sourceLocations.length);
377 // for (int i = 0; i < length; i++) {
378 // ClasspathMultiDirectory md = sourceLocations[i];
379 // out.writeUTF(md.sourceFolder.getProjectRelativePath().toString());
380 // out.writeUTF(md.binaryFolder.getProjectRelativePath().toString());
381 // writeNames(md.exclusionPatterns, out);
382 // out.writeBoolean(md.hasIndependentOutputFolder);
385 * ClasspathLocation[] int id String path(s)
387 // out.writeInt(length = binaryLocations.length);
388 // next : for (int i = 0; i < length; i++) {
389 // ClasspathLocation c = binaryLocations[i];
390 // if (c instanceof ClasspathMultiDirectory) {
391 // out.writeByte(SOURCE_FOLDER);
392 // for (int j = 0, m = sourceLocations.length; j < m; j++) {
393 // if (sourceLocations[j] == c) {
398 // } else if (c instanceof ClasspathDirectory) {
399 // out.writeByte(BINARY_FOLDER);
400 // ClasspathDirectory cd = (ClasspathDirectory) c;
401 // out.writeUTF(cd.binaryFolder.getFullPath().toString());
402 // out.writeBoolean(cd.isOutputFolder);
404 // ClasspathJar jar = (ClasspathJar) c;
405 // if (jar.resource == null) {
406 // out.writeByte(EXTERNAL_JAR);
407 // out.writeUTF(jar.zipFilename);
409 // out.writeByte(INTERNAL_JAR);
410 // out.writeUTF(jar.resource.getFullPath().toString());
415 * Structural build numbers table String prereq project name int last
416 * structural build number
418 out.writeInt(length = structuralBuildTimes.elementSize);
420 keyTable = structuralBuildTimes.keyTable;
421 valueTable = structuralBuildTimes.valueTable;
422 for (int i = 0, l = keyTable.length; i < l; i++) {
423 if (keyTable[i] != null) {
425 out.writeUTF((String) keyTable[i]);
426 out.writeLong(((Long) valueTable[i]).longValue());
429 if (PHPBuilder.DEBUG && length != 0)
431 .println("structuralBuildNumbers table is inconsistent"); //$NON-NLS-1$
435 * String[] Interned type locators
437 // out.writeInt(length = references.elementSize);
438 // ArrayList internedTypeLocators = new ArrayList(length);
440 // keyTable = references.keyTable;
441 // for (int i = 0, l = keyTable.length; i < l; i++) {
442 // if (keyTable[i] != null) {
444 // String key = (String) keyTable[i];
445 // out.writeUTF(key);
446 // internedTypeLocators.add(key);
449 // if (PHPBuilder.DEBUG && length != 0)
450 // System.out.println("references table is inconsistent"); //$NON-NLS-1$
453 * Type locators table String type name int interned locator id
455 // out.writeInt(length = typeLocators.elementSize);
457 // keyTable = typeLocators.keyTable;
458 // valueTable = typeLocators.valueTable;
459 // for (int i = 0, l = keyTable.length; i < l; i++) {
460 // if (keyTable[i] != null) {
462 // out.writeUTF((String) keyTable[i]);
463 // out.writeInt(internedTypeLocators.indexOf((String) valueTable[i]));
466 // if (PHPBuilder.DEBUG && length != 0)
467 // System.out.println("typeLocators table is inconsistent");
471 * char[][][] Interned qualified names char[][] Interned simple names
473 // ArrayList internedQualifiedNames = new ArrayList(31);
474 // ArrayList internedSimpleNames = new ArrayList(31);
475 // valueTable = references.valueTable;
476 // for (int i = 0, l = valueTable.length; i < l; i++) {
477 // if (valueTable[i] != null) {
478 // ReferenceCollection collection = (ReferenceCollection) valueTable[i];
479 // char[][][] qNames = collection.qualifiedNameReferences;
480 // for (int j = 0, m = qNames.length; j < m; j++) {
481 // char[][] qName = qNames[j];
482 // if (!internedQualifiedNames.contains(qName)) { // remember the names
483 // have been interned
484 // internedQualifiedNames.add(qName);
485 // for (int k = 0, n = qName.length; k < n; k++) {
486 // char[] sName = qName[k];
487 // if (!internedSimpleNames.contains(sName)) // remember the names have
489 // internedSimpleNames.add(sName);
493 // char[][] sNames = collection.simpleNameReferences;
494 // for (int j = 0, m = sNames.length; j < m; j++) {
495 // char[] sName = sNames[j];
496 // if (!internedSimpleNames.contains(sName)) // remember the names have
498 // internedSimpleNames.add(sName);
502 // char[][] internedArray = new char[internedSimpleNames.size()][];
503 // internedSimpleNames.toArray(internedArray);
504 // writeNames(internedArray, out);
505 // // now write the interned qualified names as arrays of interned
507 // out.writeInt(length = internedQualifiedNames.size());
508 // for (int i = 0; i < length; i++) {
509 // char[][] qName = (char[][]) internedQualifiedNames.get(i);
510 // int qLength = qName.length;
511 // out.writeInt(qLength);
512 // for (int j = 0; j < qLength; j++)
513 // out.writeInt(internedSimpleNames.indexOf(qName[j]));
517 // * References table int interned locator id ReferenceCollection
519 // out.writeInt(length = references.elementSize);
521 // keyTable = references.keyTable;
522 // for (int i = 0, l = keyTable.length; i < l; i++) {
523 // if (keyTable[i] != null) {
525 // out.writeInt(internedTypeLocators.indexOf((String) keyTable[i]));
526 // ReferenceCollection collection = (ReferenceCollection) valueTable[i];
527 // if (collection instanceof AdditionalTypeCollection) {
529 // AdditionalTypeCollection atc = (AdditionalTypeCollection) collection;
530 // writeNames(atc.definedTypeNames, out);
534 // char[][][] qNames = collection.qualifiedNameReferences;
535 // int qLength = qNames.length;
536 // out.writeInt(qLength);
537 // for (int j = 0; j < qLength; j++)
538 // out.writeInt(internedQualifiedNames.indexOf(qNames[j]));
539 // char[][] sNames = collection.simpleNameReferences;
540 // int sLength = sNames.length;
541 // out.writeInt(sLength);
542 // for (int j = 0; j < sLength; j++)
543 // out.writeInt(internedSimpleNames.indexOf(sNames[j]));
546 // if (PHPBuilder.DEBUG && length != 0)
547 // System.out.println("references table is inconsistent"); //$NON-NLS-1$
551 private void writeNames(char[][] names, DataOutputStream out)
553 int length = names == null ? 0 : names.length;
554 out.writeInt(length);
555 for (int i = 0; i < length; i++) {
556 char[] name = names[i];
557 int nLength = name.length;
558 out.writeInt(nLength);
559 for (int j = 0; j < nLength; j++)
560 out.writeChar(name[j]);
565 * Returns a string representation of the receiver.
567 public String toString() {
568 return "State for " + javaProjectName //$NON-NLS-1$
569 + " (#" + buildNumber //$NON-NLS-1$
570 + " @ " + new Date(lastStructuralBuildTime) //$NON-NLS-1$
575 * Debug helper void dump() { System.out.println("State for " +
576 * javaProjectName + " (" + buildNumber + " @ " + new
577 * Date(lastStructuralBuildTime) + ")"); System.out.println("\tClass path
578 * source locations:"); for (int i = 0, l = sourceLocations.length; i < l;
579 * i++) System.out.println("\t\t" + sourceLocations[i]);
580 * System.out.println("\tClass path binary locations:"); for (int i = 0, l =
581 * binaryLocations.length; i < l; i++) System.out.println("\t\t" +
582 * binaryLocations[i]);
584 * System.out.print("\tStructural build numbers table:"); if
585 * (structuralBuildTimes.elementSize == 0) { System.out.print(" <empty> "); }
586 * else { Object[] keyTable = structuralBuildTimes.keyTable; Object[]
587 * valueTable = structuralBuildTimes.valueTable; for (int i = 0, l =
588 * keyTable.length; i < l; i++) if (keyTable[i] != null)
589 * System.out.print("\n\t\t" + keyTable[i].toString() + " -> " +
590 * valueTable[i].toString()); }
592 * System.out.print("\tType locators table:"); if (typeLocators.elementSize ==
593 * 0) { System.out.print(" <empty> "); } else { Object[] keyTable =
594 * typeLocators.keyTable; Object[] valueTable = typeLocators.valueTable; for
595 * (int i = 0, l = keyTable.length; i < l; i++) if (keyTable[i] != null)
596 * System.out.print("\n\t\t" + keyTable[i].toString() + " -> " +
597 * valueTable[i].toString()); }
599 * System.out.print("\n\tReferences table:"); if (references.elementSize ==
600 * 0) { System.out.print(" <empty> "); } else { Object[] keyTable =
601 * references.keyTable; Object[] valueTable = references.valueTable; for
602 * (int i = 0, l = keyTable.length; i < l; i++) { if (keyTable[i] != null) {
603 * System.out.print("\n\t\t" + keyTable[i].toString()); ReferenceCollection
604 * c = (ReferenceCollection) valueTable[i]; char[][][] qRefs =
605 * c.qualifiedNameReferences; System.out.print("\n\t\t\tqualified:"); if
606 * (qRefs.length == 0) System.out.print(" <empty> "); else for (int j = 0, m =
607 * qRefs.length; j < m; j++) System.out.print(" '" +
608 * CharOperation.toString(qRefs[j]) + "'"); char[][] sRefs =
609 * c.simpleNameReferences; System.out.print("\n\t\t\tsimple:"); if
610 * (sRefs.length == 0) System.out.print(" <empty> "); else for (int j = 0, m =
611 * sRefs.length; j < m; j++) System.out.print(" " + new String(sRefs[j]));
612 * if (c instanceof AdditionalTypeCollection) { char[][] names =
613 * ((AdditionalTypeCollection) c).definedTypeNames;
614 * System.out.print("\n\t\t\tadditional type names:"); for (int j = 0, m =
615 * names.length; j < m; j++) System.out.print(" " + new String(names[j])); } } } }
616 * System.out.print("\n\n"); }