/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core.builder; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Date; import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; //import org.eclipse.core.runtime.IPath; public class State { // NOTE: this state cannot contain types that are not defined in this // project String javaProjectName; ClasspathMultiDirectory[] sourceLocations; // ClasspathLocation[] binaryLocations; // keyed by the project relative path of the type (ie. "src1/p1/p2/A.java"), // value is a ReferenceCollection or an // AdditionalTypeCollection // SimpleLookupTable references; // keyed by qualified type name "p1/p2/A", value is the project relative // path which defines this type "src1/p1/p2/A.java" // SimpleLookupTable typeLocators; int buildNumber; long lastStructuralBuildTime; SimpleLookupTable structuralBuildTimes; //private String[] knownPackageNames; // of the form "p1/p2" static final byte VERSION = 0x0007; static final byte SOURCE_FOLDER = 1; // static final byte BINARY_FOLDER = 2; // static final byte EXTERNAL_JAR = 3; // static final byte INTERNAL_JAR = 4; State() { } protected State(PHPBuilder javaBuilder) { //this.knownPackageNames = null; this.javaProjectName = javaBuilder.currentProject.getName(); this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations; // this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations; // this.references = new SimpleLookupTable(7); // this.typeLocators = new SimpleLookupTable(7); this.buildNumber = 0; // indicates a full build this.lastStructuralBuildTime = System.currentTimeMillis(); this.structuralBuildTimes = new SimpleLookupTable(3); } void copyFrom(State lastState) { // try { //this.knownPackageNames = null; this.buildNumber = lastState.buildNumber + 1; this.lastStructuralBuildTime = lastState.lastStructuralBuildTime; // this.references = (SimpleLookupTable) lastState.references.clone(); // this.typeLocators = (SimpleLookupTable) // lastState.typeLocators.clone(); // } catch (CloneNotSupportedException e) { // this.references = new // SimpleLookupTable(lastState.references.elementSize); // Object[] keyTable = lastState.references.keyTable; // Object[] valueTable = lastState.references.valueTable; // for (int i = 0, l = keyTable.length; i < l; i++) // if (keyTable[i] != null) // this.references.put(keyTable[i], valueTable[i]); // // this.typeLocators = new // SimpleLookupTable(lastState.typeLocators.elementSize); // keyTable = lastState.typeLocators.keyTable; // valueTable = lastState.typeLocators.valueTable; // for (int i = 0, l = keyTable.length; i < l; i++) // if (keyTable[i] != null) // this.typeLocators.put(keyTable[i], valueTable[i]); // } } // char[][] getDefinedTypeNamesFor(String typeLocator) { // Object c = references.get(typeLocator); // if (c instanceof AdditionalTypeCollection) // return ((AdditionalTypeCollection) c).definedTypeNames; // return null; // means only one type is defined with the same name as the // file... saves space // } // boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator) // { // String existing = (String) typeLocators.get(qualifiedTypeName); // return existing != null && !existing.equals(typeLocator); // } // boolean isKnownPackage(String qualifiedPackageName) { // if (knownPackageNames == null) { // ArrayList names = new ArrayList(typeLocators.elementSize); // Object[] keyTable = typeLocators.keyTable; // for (int i = 0, l = keyTable.length; i < l; i++) { // if (keyTable[i] != null) { // String packageName = (String) keyTable[i]; // is a type name of the form // p1/p2/A // int last = packageName.lastIndexOf('/'); // packageName = last == -1 ? null : packageName.substring(0, last); // while (packageName != null && !names.contains(packageName)) { // names.add(packageName); // last = packageName.lastIndexOf('/'); // packageName = last == -1 ? null : packageName.substring(0, last); // } // } // } // knownPackageNames = new String[names.size()]; // names.toArray(knownPackageNames); // } // for (int i = 0, l = knownPackageNames.length; i < l; i++) // if (knownPackageNames[i].equals(qualifiedPackageName)) // return true; // return false; // } // void record(String typeLocator, char[][][] qualifiedRefs, char[][] // simpleRefs, char[] mainTypeName, ArrayList typeNames) { // if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[]) // typeNames.get(0))) { // references.put(typeLocator, new ReferenceCollection(qualifiedRefs, // simpleRefs)); // } else { // char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty // when no types are defined // typeNames.toArray(definedTypeNames); // references.put(typeLocator, new // AdditionalTypeCollection(definedTypeNames, qualifiedRefs, simpleRefs)); // } // } // // void recordLocatorForType(String qualifiedTypeName, String typeLocator) { // this.knownPackageNames = null; // typeLocators.put(qualifiedTypeName, typeLocator); // } void recordStructuralDependency(IProject prereqProject, State prereqState) { if (prereqState != null) structuralBuildTimes.put(prereqProject.getName(), new Long( prereqState.lastStructuralBuildTime)); } // void removeLocator(String typeLocatorToRemove) { // this.knownPackageNames = null; // references.removeKey(typeLocatorToRemove); // typeLocators.removeValue(typeLocatorToRemove); // } void removePackage(IResourceDelta sourceDelta) { IResource resource = sourceDelta.getResource(); switch (resource.getType()) { case IResource.FOLDER: IResourceDelta[] children = sourceDelta.getAffectedChildren(); for (int i = 0, l = children.length; i < l; i++) removePackage(children[i]); return; case IResource.FILE: //IPath typeLocatorPath = resource.getProjectRelativePath(); // if // (ProjectPrefUtil.isJavaFileName(typeLocatorPath.lastSegment())) // removeLocator(typeLocatorPath.toString()); } } // void removeQualifiedTypeName(String qualifiedTypeNameToRemove) { // this.knownPackageNames = null; // typeLocators.removeKey(qualifiedTypeNameToRemove); // } static State read(IProject project, DataInputStream in) throws IOException { if (PHPBuilder.DEBUG) System.out.println("About to read state..."); //$NON-NLS-1$ if (VERSION != in.readByte()) { if (PHPBuilder.DEBUG) System.out .println("Found non-compatible state version... answered null"); //$NON-NLS-1$ return null; } State newState = new State(); newState.javaProjectName = in.readUTF(); if (!project.getName().equals(newState.javaProjectName)) { if (PHPBuilder.DEBUG) System.out .println("Project's name does not match... answered null"); //$NON-NLS-1$ return null; } newState.buildNumber = in.readInt(); newState.lastStructuralBuildTime = in.readLong(); int length; // int length = in.readInt(); // newState.sourceLocations = new ClasspathMultiDirectory[0]; // newState.sourceLocations = new ClasspathMultiDirectory[length]; // for (int i = 0; i < length; i++) { // IContainer sourceFolder = project, outputFolder = project; // String folderName; // if ((folderName = in.readUTF()).length() > 0) sourceFolder = // project.getFolder(folderName); // if ((folderName = in.readUTF()).length() > 0) outputFolder = // project.getFolder(folderName); // ClasspathMultiDirectory md = // (ClasspathMultiDirectory) // ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, // readNames(in)); // if (in.readBoolean()) // md.hasIndependentOutputFolder = true; // newState.sourceLocations[i] = md; // } // length = in.readInt(); // newState.binaryLocations = new ClasspathLocation[length]; // IWorkspaceRoot root = project.getWorkspace().getRoot(); // for (int i = 0; i < length; i++) { // switch (in.readByte()) { // case SOURCE_FOLDER : // newState.binaryLocations[i] = newState.sourceLocations[in.readInt()]; // break; // case BINARY_FOLDER : // IPath path = new Path(in.readUTF()); // IContainer outputFolder = path.segmentCount() == 1 // ? (IContainer) root.getProject(path.toString()) // : (IContainer) root.getFolder(path); // newState.binaryLocations[i] = // ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean()); // break; // case EXTERNAL_JAR : // newState.binaryLocations[i] = // ClasspathLocation.forLibrary(in.readUTF()); // break; // case INTERNAL_JAR : // newState.binaryLocations[i] = // ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF()))); // } // } newState.structuralBuildTimes = new SimpleLookupTable(length = in .readInt()); for (int i = 0; i < length; i++) newState.structuralBuildTimes.put(in.readUTF(), new Long(in .readLong())); // String[] internedTypeLocators = new String[length = in.readInt()]; // for (int i = 0; i < length; i++) // internedTypeLocators[i] = in.readUTF(); // newState.typeLocators = new SimpleLookupTable(length = in.readInt()); // for (int i = 0; i < length; i++) // newState.typeLocators.put(in.readUTF(), // internedTypeLocators[in.readInt()]); // char[][] internedSimpleNames = // ReferenceCollection.internSimpleNames(readNames(in), false); // char[][][] internedQualifiedNames = new char[length = // in.readInt()][][]; // for (int i = 0; i < length; i++) { // int qLength = in.readInt(); // char[][] qName = new char[qLength][]; // for (int j = 0; j < qLength; j++) // qName[j] = internedSimpleNames[in.readInt()]; // internedQualifiedNames[i] = qName; // } // internedQualifiedNames = // ReferenceCollection.internQualifiedNames(internedQualifiedNames); // // newState.references = new SimpleLookupTable(length = in.readInt()); // for (int i = 0; i < length; i++) { // String typeLocator = internedTypeLocators[in.readInt()]; // ReferenceCollection collection = null; // switch (in.readByte()) { // case 1 : // char[][] additionalTypeNames = readNames(in); // char[][][] qualifiedNames = new char[in.readInt()][][]; // for (int j = 0, m = qualifiedNames.length; j < m; j++) // qualifiedNames[j] = internedQualifiedNames[in.readInt()]; // char[][] simpleNames = new char[in.readInt()][]; // for (int j = 0, m = simpleNames.length; j < m; j++) // simpleNames[j] = internedSimpleNames[in.readInt()]; // collection = new AdditionalTypeCollection(additionalTypeNames, // qualifiedNames, simpleNames); // break; // case 2 : // char[][][] qNames = new char[in.readInt()][][]; // for (int j = 0, m = qNames.length; j < m; j++) // qNames[j] = internedQualifiedNames[in.readInt()]; // char[][] sNames = new char[in.readInt()][]; // for (int j = 0, m = sNames.length; j < m; j++) // sNames[j] = internedSimpleNames[in.readInt()]; // collection = new ReferenceCollection(qNames, sNames); // } // newState.references.put(typeLocator, collection); // } if (PHPBuilder.DEBUG) System.out .println("Successfully read state for " + newState.javaProjectName); //$NON-NLS-1$ return newState; } // private static char[][] readNames(DataInputStream in) throws IOException { // int length = in.readInt(); // char[][] names = new char[length][]; // for (int i = 0; i < length; i++) { // int nLength = in.readInt(); // char[] name = new char[nLength]; // for (int j = 0; j < nLength; j++) // name[j] = in.readChar(); // names[i] = name; // } // return names; // } void tagAsNoopBuild() { this.buildNumber = -1; // tag the project since it has no source // folders and can be skipped } boolean wasNoopBuild() { return buildNumber == -1; } void tagAsStructurallyChanged() { this.lastStructuralBuildTime = System.currentTimeMillis(); } boolean wasStructurallyChanged(IProject prereqProject, State prereqState) { if (prereqState != null) { Object o = structuralBuildTimes.get(prereqProject.getName()); long previous = o == null ? 0 : ((Long) o).longValue(); if (previous == prereqState.lastStructuralBuildTime) return false; } return true; } void write(DataOutputStream out) throws IOException { int length; Object[] keyTable; Object[] valueTable; /* * byte VERSION String project name int build number int last structural * build number */ out.writeByte(VERSION); out.writeUTF(javaProjectName); out.writeInt(buildNumber); out.writeLong(lastStructuralBuildTime); /* * ClasspathMultiDirectory[] int id String path(s) */ // out.writeInt(length = sourceLocations.length); // for (int i = 0; i < length; i++) { // ClasspathMultiDirectory md = sourceLocations[i]; // out.writeUTF(md.sourceFolder.getProjectRelativePath().toString()); // out.writeUTF(md.binaryFolder.getProjectRelativePath().toString()); // writeNames(md.exclusionPatterns, out); // out.writeBoolean(md.hasIndependentOutputFolder); // } /* * ClasspathLocation[] int id String path(s) */ // out.writeInt(length = binaryLocations.length); // next : for (int i = 0; i < length; i++) { // ClasspathLocation c = binaryLocations[i]; // if (c instanceof ClasspathMultiDirectory) { // out.writeByte(SOURCE_FOLDER); // for (int j = 0, m = sourceLocations.length; j < m; j++) { // if (sourceLocations[j] == c) { // out.writeInt(j); // continue next; // } // } // } else if (c instanceof ClasspathDirectory) { // out.writeByte(BINARY_FOLDER); // ClasspathDirectory cd = (ClasspathDirectory) c; // out.writeUTF(cd.binaryFolder.getFullPath().toString()); // out.writeBoolean(cd.isOutputFolder); // } else { // ClasspathJar jar = (ClasspathJar) c; // if (jar.resource == null) { // out.writeByte(EXTERNAL_JAR); // out.writeUTF(jar.zipFilename); // } else { // out.writeByte(INTERNAL_JAR); // out.writeUTF(jar.resource.getFullPath().toString()); // } // } // } /* * Structural build numbers table String prereq project name int last * structural build number */ out.writeInt(length = structuralBuildTimes.elementSize); if (length > 0) { keyTable = structuralBuildTimes.keyTable; valueTable = structuralBuildTimes.valueTable; for (int i = 0, l = keyTable.length; i < l; i++) { if (keyTable[i] != null) { length--; out.writeUTF((String) keyTable[i]); out.writeLong(((Long) valueTable[i]).longValue()); } } if (PHPBuilder.DEBUG && length != 0) System.out .println("structuralBuildNumbers table is inconsistent"); //$NON-NLS-1$ } /* * String[] Interned type locators */ // out.writeInt(length = references.elementSize); // ArrayList internedTypeLocators = new ArrayList(length); // if (length > 0) { // keyTable = references.keyTable; // for (int i = 0, l = keyTable.length; i < l; i++) { // if (keyTable[i] != null) { // length--; // String key = (String) keyTable[i]; // out.writeUTF(key); // internedTypeLocators.add(key); // } // } // if (PHPBuilder.DEBUG && length != 0) // System.out.println("references table is inconsistent"); //$NON-NLS-1$ // } /* * Type locators table String type name int interned locator id */ // out.writeInt(length = typeLocators.elementSize); // if (length > 0) { // keyTable = typeLocators.keyTable; // valueTable = typeLocators.valueTable; // for (int i = 0, l = keyTable.length; i < l; i++) { // if (keyTable[i] != null) { // length--; // out.writeUTF((String) keyTable[i]); // out.writeInt(internedTypeLocators.indexOf((String) valueTable[i])); // } // } // if (PHPBuilder.DEBUG && length != 0) // System.out.println("typeLocators table is inconsistent"); // //$NON-NLS-1$ // } /* * char[][][] Interned qualified names char[][] Interned simple names */ // ArrayList internedQualifiedNames = new ArrayList(31); // ArrayList internedSimpleNames = new ArrayList(31); // valueTable = references.valueTable; // for (int i = 0, l = valueTable.length; i < l; i++) { // if (valueTable[i] != null) { // ReferenceCollection collection = (ReferenceCollection) valueTable[i]; // char[][][] qNames = collection.qualifiedNameReferences; // for (int j = 0, m = qNames.length; j < m; j++) { // char[][] qName = qNames[j]; // if (!internedQualifiedNames.contains(qName)) { // remember the names // have been interned // internedQualifiedNames.add(qName); // for (int k = 0, n = qName.length; k < n; k++) { // char[] sName = qName[k]; // if (!internedSimpleNames.contains(sName)) // remember the names have // been interned // internedSimpleNames.add(sName); // } // } // } // char[][] sNames = collection.simpleNameReferences; // for (int j = 0, m = sNames.length; j < m; j++) { // char[] sName = sNames[j]; // if (!internedSimpleNames.contains(sName)) // remember the names have // been interned // internedSimpleNames.add(sName); // } // } // } // char[][] internedArray = new char[internedSimpleNames.size()][]; // internedSimpleNames.toArray(internedArray); // writeNames(internedArray, out); // // now write the interned qualified names as arrays of interned // simple names // out.writeInt(length = internedQualifiedNames.size()); // for (int i = 0; i < length; i++) { // char[][] qName = (char[][]) internedQualifiedNames.get(i); // int qLength = qName.length; // out.writeInt(qLength); // for (int j = 0; j < qLength; j++) // out.writeInt(internedSimpleNames.indexOf(qName[j])); // } // // /* // * References table int interned locator id ReferenceCollection // */ // out.writeInt(length = references.elementSize); // if (length > 0) { // keyTable = references.keyTable; // for (int i = 0, l = keyTable.length; i < l; i++) { // if (keyTable[i] != null) { // length--; // out.writeInt(internedTypeLocators.indexOf((String) keyTable[i])); // ReferenceCollection collection = (ReferenceCollection) valueTable[i]; // if (collection instanceof AdditionalTypeCollection) { // out.writeByte(1); // AdditionalTypeCollection atc = (AdditionalTypeCollection) collection; // writeNames(atc.definedTypeNames, out); // } else { // out.writeByte(2); // } // char[][][] qNames = collection.qualifiedNameReferences; // int qLength = qNames.length; // out.writeInt(qLength); // for (int j = 0; j < qLength; j++) // out.writeInt(internedQualifiedNames.indexOf(qNames[j])); // char[][] sNames = collection.simpleNameReferences; // int sLength = sNames.length; // out.writeInt(sLength); // for (int j = 0; j < sLength; j++) // out.writeInt(internedSimpleNames.indexOf(sNames[j])); // } // } // if (PHPBuilder.DEBUG && length != 0) // System.out.println("references table is inconsistent"); //$NON-NLS-1$ // } } // private void writeNames(char[][] names, DataOutputStream out) // throws IOException { // int length = names == null ? 0 : names.length; // out.writeInt(length); // for (int i = 0; i < length; i++) { // char[] name = names[i]; // int nLength = name.length; // out.writeInt(nLength); // for (int j = 0; j < nLength; j++) // out.writeChar(name[j]); // } // } /** * Returns a string representation of the receiver. */ public String toString() { return "State for " + javaProjectName //$NON-NLS-1$ + " (#" + buildNumber //$NON-NLS-1$ + " @ " + new Date(lastStructuralBuildTime) //$NON-NLS-1$ + ")"; //$NON-NLS-1$ } /* * Debug helper void dump() { System.out.println("State for " + * javaProjectName + " (" + buildNumber + " @ " + new * Date(lastStructuralBuildTime) + ")"); System.out.println("\tClass path * source locations:"); for (int i = 0, l = sourceLocations.length; i < l; * i++) System.out.println("\t\t" + sourceLocations[i]); * System.out.println("\tClass path binary locations:"); for (int i = 0, l = * binaryLocations.length; i < l; i++) System.out.println("\t\t" + * binaryLocations[i]); * * System.out.print("\tStructural build numbers table:"); if * (structuralBuildTimes.elementSize == 0) { System.out.print(" "); } * else { Object[] keyTable = structuralBuildTimes.keyTable; Object[] * valueTable = structuralBuildTimes.valueTable; for (int i = 0, l = * keyTable.length; i < l; i++) if (keyTable[i] != null) * System.out.print("\n\t\t" + keyTable[i].toString() + " -> " + * valueTable[i].toString()); } * * System.out.print("\tType locators table:"); if (typeLocators.elementSize == * 0) { System.out.print(" "); } else { Object[] keyTable = * typeLocators.keyTable; Object[] valueTable = typeLocators.valueTable; for * (int i = 0, l = keyTable.length; i < l; i++) if (keyTable[i] != null) * System.out.print("\n\t\t" + keyTable[i].toString() + " -> " + * valueTable[i].toString()); } * * System.out.print("\n\tReferences table:"); if (references.elementSize == * 0) { System.out.print(" "); } else { Object[] keyTable = * references.keyTable; Object[] valueTable = references.valueTable; for * (int i = 0, l = keyTable.length; i < l; i++) { if (keyTable[i] != null) { * System.out.print("\n\t\t" + keyTable[i].toString()); ReferenceCollection * c = (ReferenceCollection) valueTable[i]; char[][][] qRefs = * c.qualifiedNameReferences; System.out.print("\n\t\t\tqualified:"); if * (qRefs.length == 0) System.out.print(" "); else for (int j = 0, m = * qRefs.length; j < m; j++) System.out.print(" '" + * CharOperation.toString(qRefs[j]) + "'"); char[][] sRefs = * c.simpleNameReferences; System.out.print("\n\t\t\tsimple:"); if * (sRefs.length == 0) System.out.print(" "); else for (int j = 0, m = * sRefs.length; j < m; j++) System.out.print(" " + new String(sRefs[j])); * if (c instanceof AdditionalTypeCollection) { char[][] names = * ((AdditionalTypeCollection) c).definedTypeNames; * System.out.print("\n\t\t\tadditional type names:"); for (int j = 0, m = * names.length; j < m; j++) System.out.print(" " + new String(names[j])); } } } } * System.out.print("\n\n"); } */ }