X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/State.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/State.java new file mode 100644 index 0000000..754ecbe --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/State.java @@ -0,0 +1,612 @@ +/******************************************************************************* + * 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.phpeclipse.builder; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; + +import net.sourceforge.phpdt.internal.core.Util; +import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +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 (Util.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 (JavaBuilder.DEBUG) +// System.out.println("About to read state..."); //$NON-NLS-1$ + if (VERSION != in.readByte()) { +// if (JavaBuilder.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 (JavaBuilder.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 = in.readInt(); + 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 (JavaBuilder.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 (JavaBuilder.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 (JavaBuilder.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 (JavaBuilder.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 (JavaBuilder.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"); +} +*/ +}