| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * This is an implementation of an early-draft specification developed under the Java |
| * Community Process (JCP) and is made available for testing and evaluation purposes |
| * only. The code is not compatible with any specification of the JCP. |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Stephan Herrmann - Contribution for |
| * Bug 440477 - [null] Infrastructure for feeding external annotations into compilation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.builder; |
| |
| import org.eclipse.core.resources.*; |
| import org.eclipse.core.runtime.*; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; |
| import org.eclipse.jdt.internal.compiler.env.INameEnvironment; |
| import org.eclipse.jdt.internal.compiler.env.AccessRule; |
| import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; |
| import org.eclipse.jdt.internal.compiler.util.Util; |
| import org.eclipse.jdt.internal.core.ClasspathAccessRule; |
| import org.eclipse.jdt.internal.core.JavaModelManager; |
| |
| import java.io.*; |
| import java.util.*; |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| public class State { |
| // NOTE: this state cannot contain types that are not defined in this project |
| |
| String javaProjectName; |
| public ClasspathMultiDirectory[] sourceLocations; |
| ClasspathLocation[] binaryLocations; |
| INameEnvironment environment; |
| // keyed by the project relative path of the type (i.e. "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" |
| public SimpleLookupTable typeLocators; |
| |
| int buildNumber; |
| long lastStructuralBuildTime; |
| SimpleLookupTable structuralBuildTimes; |
| |
| private String[] knownPackageNames; // of the form "p1/p2" |
| |
| private long previousStructuralBuildTime; |
| private StringSet structurallyChangedTypes; |
| public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed |
| |
| public static final byte VERSION = 0x001E; |
| |
| 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() { |
| // constructor with no argument |
| } |
| |
| protected State(JavaBuilder javaBuilder) { |
| this.knownPackageNames = null; |
| this.previousStructuralBuildTime = -1; |
| this.structurallyChangedTypes = null; |
| this.javaProjectName = javaBuilder.currentProject.getName(); |
| this.environment = javaBuilder.nameEnvironment; |
| 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 = computeStructuralBuildTime(javaBuilder.lastState == null ? 0 : javaBuilder.lastState.lastStructuralBuildTime); |
| this.structuralBuildTimes = new SimpleLookupTable(3); |
| } |
| |
| long computeStructuralBuildTime(long previousTime) { |
| long newTime = System.currentTimeMillis(); |
| if (newTime <= previousTime) |
| newTime = previousTime + 1; |
| return newTime; |
| } |
| |
| void copyFrom(State lastState) { |
| this.knownPackageNames = null; |
| this.previousStructuralBuildTime = lastState.previousStructuralBuildTime; |
| this.structurallyChangedTypes = lastState.structurallyChangedTypes; |
| this.buildNumber = lastState.buildNumber + 1; |
| this.lastStructuralBuildTime = lastState.lastStructuralBuildTime; |
| this.structuralBuildTimes = lastState.structuralBuildTimes; |
| |
| try { |
| 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]); |
| } |
| } |
| public char[][] getDefinedTypeNamesFor(String typeLocator) { |
| Object c = this.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 |
| } |
| |
| public SimpleLookupTable getReferences() { |
| return this.references; |
| } |
| |
| StringSet getStructurallyChangedTypes(State prereqState) { |
| if (prereqState != null && prereqState.previousStructuralBuildTime > 0) { |
| Object o = this.structuralBuildTimes.get(prereqState.javaProjectName); |
| long previous = o == null ? 0 : ((Long) o).longValue(); |
| if (previous == prereqState.previousStructuralBuildTime) |
| return prereqState.structurallyChangedTypes; |
| } |
| return null; |
| } |
| |
| public boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator) { |
| String existing = (String) this.typeLocators.get(qualifiedTypeName); |
| return existing != null && !existing.equals(typeLocator); |
| } |
| |
| public boolean isKnownPackage(String qualifiedPackageName) { |
| if (this.knownPackageNames == null) { |
| ArrayList names = new ArrayList(this.typeLocators.elementSize); |
| Object[] keyTable = this.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); |
| } |
| } |
| } |
| this.knownPackageNames = new String[names.size()]; |
| names.toArray(this.knownPackageNames); |
| } |
| for (int i = 0, l = this.knownPackageNames.length; i < l; i++) |
| if (this.knownPackageNames[i].equals(qualifiedPackageName)) |
| return true; |
| return false; |
| } |
| |
| public boolean isKnownType(String qualifiedTypeName) { |
| return this.typeLocators.containsKey(qualifiedTypeName); |
| } |
| |
| boolean isSourceFolderEmpty(IContainer sourceFolder) { |
| String sourceFolderName = sourceFolder.getProjectRelativePath().addTrailingSeparator().toString(); |
| Object[] table = this.typeLocators.valueTable; |
| for (int i = 0, l = table.length; i < l; i++) |
| if (table[i] != null && ((String) table[i]).startsWith(sourceFolderName)) |
| return false; |
| return true; |
| } |
| |
| void record(String typeLocator, char[][][] qualifiedRefs, char[][] simpleRefs, char[][] rootRefs, char[] mainTypeName, ArrayList typeNames) { |
| if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[]) typeNames.get(0))) { |
| this.references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs, rootRefs)); |
| } else { |
| char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty when no types are defined |
| typeNames.toArray(definedTypeNames); |
| this.references.put(typeLocator, new AdditionalTypeCollection(definedTypeNames, qualifiedRefs, simpleRefs, rootRefs)); |
| } |
| } |
| |
| void recordLocatorForType(String qualifiedTypeName, String typeLocator) { |
| this.knownPackageNames = null; |
| // in the common case, the qualifiedTypeName is a substring of the typeLocator so share the char[] by using String.substring() |
| int start = typeLocator.indexOf(qualifiedTypeName, 0); |
| if (start > 0) |
| qualifiedTypeName = typeLocator.substring(start, start + qualifiedTypeName.length()); |
| this.typeLocators.put(qualifiedTypeName, typeLocator); |
| } |
| |
| void recordStructuralDependency(IProject prereqProject, State prereqState) { |
| if (prereqState != null) |
| if (prereqState.lastStructuralBuildTime > 0) // can skip if 0 (full build) since its assumed to be 0 if unknown |
| this.structuralBuildTimes.put(prereqProject.getName(), Long.valueOf(prereqState.lastStructuralBuildTime)); |
| } |
| |
| void removeLocator(String typeLocatorToRemove) { |
| this.knownPackageNames = null; |
| this.references.removeKey(typeLocatorToRemove); |
| this.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 (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(typeLocatorPath.lastSegment())) |
| removeLocator(typeLocatorPath.toString()); |
| } |
| } |
| |
| void removeQualifiedTypeName(String qualifiedTypeNameToRemove) { |
| this.knownPackageNames = null; |
| this.typeLocators.removeKey(qualifiedTypeNameToRemove); |
| } |
| |
| static State read(IProject project, DataInputStream in) throws IOException { |
| if (JavaBuilder.DEBUG) |
| System.out.println("About to read state " + project.getName()); //$NON-NLS-1$ |
| if (VERSION != in.readByte()) { |
| if (JavaBuilder.DEBUG) |
| System.out.println("Found non-compatible state version... answered null for " + project.getName()); //$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), readNames(in), in.readBoolean(), newState.environment); |
| 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(), |
| readRestriction(in), new Path(in.readUTF()), newState.environment, in.readBoolean()); |
| break; |
| case EXTERNAL_JAR : |
| String jarPath = in.readUTF(); |
| newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(), |
| readRestriction(in), new Path(in.readUTF()), newState.environment, Util.isJrt(jarPath) ? false : in.readBoolean()); |
| break; |
| case INTERNAL_JAR : |
| newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), |
| readRestriction(in), new Path(in.readUTF()), newState.environment, in.readBoolean()); |
| } |
| } |
| |
| newState.structuralBuildTimes = new SimpleLookupTable(length = in.readInt()); |
| for (int i = 0; i < length; i++) |
| newState.structuralBuildTimes.put(in.readUTF(), Long.valueOf(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.recordLocatorForType(in.readUTF(), internedTypeLocators[in.readInt()]); |
| |
| char[][] internedRootNames = ReferenceCollection.internSimpleNames(readNames(in), false); |
| 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, false); |
| |
| 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()]; |
| char[][] rootNames = new char[in.readInt()][]; |
| for (int j = 0, m = rootNames.length; j < m; j++) |
| rootNames[j] = internedRootNames[in.readInt()]; |
| collection = new AdditionalTypeCollection(additionalTypeNames, qualifiedNames, simpleNames, rootNames); |
| 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()]; |
| char[][] rNames = new char[in.readInt()][]; |
| for (int j = 0, m = rNames.length; j < m; j++) |
| rNames[j] = internedRootNames[in.readInt()]; |
| collection = new ReferenceCollection(qNames, sNames, rNames); |
| } |
| 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[] readName(DataInputStream in) throws IOException { |
| int nLength = in.readInt(); |
| char[] name = new char[nLength]; |
| for (int j = 0; j < nLength; j++) |
| name[j] = in.readChar(); |
| return name; |
| } |
| |
| private static char[][] readNames(DataInputStream in) throws IOException { |
| int length = in.readInt(); |
| char[][] names = new char[length][]; |
| for (int i = 0; i < length; i++) |
| names[i] = readName(in); |
| return names; |
| } |
| |
| private static AccessRuleSet readRestriction(DataInputStream in) throws IOException { |
| int length = in.readInt(); |
| if (length == 0) return null; // no restriction specified |
| AccessRule[] accessRules = new AccessRule[length]; |
| for (int i = 0; i < length; i++) { |
| char[] pattern = readName(in); |
| int problemId = in.readInt(); |
| accessRules[i] = new ClasspathAccessRule(pattern, problemId); |
| } |
| JavaModelManager manager = JavaModelManager.getJavaModelManager(); |
| return new AccessRuleSet(accessRules, in.readByte(), manager.intern(in.readUTF())); |
| } |
| |
| void tagAsNoopBuild() { |
| this.buildNumber = -1; // tag the project since it has no source folders and can be skipped |
| } |
| |
| boolean wasNoopBuild() { |
| return this.buildNumber == -1; |
| } |
| |
| void tagAsStructurallyChanged() { |
| this.previousStructuralBuildTime = this.lastStructuralBuildTime; |
| this.structurallyChangedTypes = new StringSet(7); |
| this.lastStructuralBuildTime = computeStructuralBuildTime(this.previousStructuralBuildTime); |
| } |
| |
| boolean wasStructurallyChanged(IProject prereqProject, State prereqState) { |
| if (prereqState != null) { |
| Object o = this.structuralBuildTimes.get(prereqProject.getName()); |
| long previous = o == null ? 0 : ((Long) o).longValue(); |
| if (previous == prereqState.lastStructuralBuildTime) return false; |
| } |
| return true; |
| } |
| |
| void wasStructurallyChanged(String typeName) { |
| if (this.structurallyChangedTypes != null) { |
| if (this.structurallyChangedTypes.elementSize > MaxStructurallyChangedTypes) |
| this.structurallyChangedTypes = null; // too many to keep track of |
| else |
| this.structurallyChangedTypes.add(typeName); |
| } |
| } |
| |
| 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(this.javaProjectName); |
| out.writeInt(this.buildNumber); |
| out.writeLong(this.lastStructuralBuildTime); |
| |
| /* |
| * ClasspathMultiDirectory[] |
| * int id |
| * String path(s) |
| */ |
| out.writeInt(length = this.sourceLocations.length); |
| for (int i = 0; i < length; i++) { |
| ClasspathMultiDirectory md = this.sourceLocations[i]; |
| out.writeUTF(md.sourceFolder.getProjectRelativePath().toString()); |
| out.writeUTF(md.binaryFolder.getProjectRelativePath().toString()); |
| writeNames(md.inclusionPatterns, out); |
| writeNames(md.exclusionPatterns, out); |
| out.writeBoolean(md.ignoreOptionalProblems); |
| out.writeBoolean(md.hasIndependentOutputFolder); |
| } |
| |
| /* |
| * ClasspathLocation[] |
| * int id |
| * String path(s) |
| */ |
| out.writeInt(length = this.binaryLocations.length); |
| next : for (int i = 0; i < length; i++) { |
| ClasspathLocation c = this.binaryLocations[i]; |
| if (c instanceof ClasspathMultiDirectory) { |
| out.writeByte(SOURCE_FOLDER); |
| for (int j = 0, m = this.sourceLocations.length; j < m; j++) { |
| if (this.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); |
| writeRestriction(cd.accessRuleSet, out); |
| out.writeUTF(cd.externalAnnotationPath != null ? cd.externalAnnotationPath : ""); //$NON-NLS-1$ |
| out.writeBoolean(cd.isAutomaticModule()); |
| } else if (c instanceof ClasspathJar) { |
| ClasspathJar jar = (ClasspathJar) c; |
| if (jar.resource == null) { |
| out.writeByte(EXTERNAL_JAR); |
| out.writeUTF(jar.zipFilename); |
| out.writeLong(jar.lastModified()); |
| } else { |
| out.writeByte(INTERNAL_JAR); |
| out.writeUTF(jar.resource.getFullPath().toString()); |
| } |
| writeRestriction(jar.accessRuleSet, out); |
| out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$ |
| out.writeBoolean(jar.isAutomaticModule()); |
| } else { |
| ClasspathJrt jrt = (ClasspathJrt) c; |
| out.writeByte(EXTERNAL_JAR); |
| out.writeUTF(jrt.zipFilename); |
| out.writeLong(-1); |
| writeRestriction(null, out); |
| out.writeUTF(""); //$NON-NLS-1$ |
| } |
| } |
| |
| /* |
| * Structural build numbers table |
| * String prereq project name |
| * int last structural build number |
| */ |
| out.writeInt(length = this.structuralBuildTimes.elementSize); |
| if (length > 0) { |
| keyTable = this.structuralBuildTimes.keyTable; |
| valueTable = this.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 = this.references.elementSize); |
| SimpleLookupTable internedTypeLocators = new SimpleLookupTable(length); |
| if (length > 0) { |
| keyTable = this.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.put(key, Integer.valueOf(internedTypeLocators.elementSize)); |
| } |
| } |
| 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 = this.typeLocators.elementSize); |
| if (length > 0) { |
| keyTable = this.typeLocators.keyTable; |
| valueTable = this.typeLocators.valueTable; |
| for (int i = 0, l = keyTable.length; i < l; i++) { |
| if (keyTable[i] != null) { |
| length--; |
| out.writeUTF((String) keyTable[i]); |
| Integer index = (Integer) internedTypeLocators.get(valueTable[i]); |
| out.writeInt(index.intValue()); |
| } |
| } |
| if (JavaBuilder.DEBUG && length != 0) |
| System.out.println("typeLocators table is inconsistent"); //$NON-NLS-1$ |
| } |
| |
| /* |
| * char[][] Interned root names |
| * char[][][] Interned qualified names |
| * char[][] Interned simple names |
| */ |
| SimpleLookupTable internedRootNames = new SimpleLookupTable(3); |
| SimpleLookupTable internedQualifiedNames = new SimpleLookupTable(31); |
| SimpleLookupTable internedSimpleNames = new SimpleLookupTable(31); |
| valueTable = this.references.valueTable; |
| for (int i = 0, l = valueTable.length; i < l; i++) { |
| if (valueTable[i] != null) { |
| ReferenceCollection collection = (ReferenceCollection) valueTable[i]; |
| char[][] rNames = collection.rootReferences; |
| for (int j = 0, m = rNames.length; j < m; j++) { |
| char[] rName = rNames[j]; |
| if (!internedRootNames.containsKey(rName)) // remember the names have been interned |
| internedRootNames.put(rName, Integer.valueOf(internedRootNames.elementSize)); |
| } |
| char[][][] qNames = collection.qualifiedNameReferences; |
| for (int j = 0, m = qNames.length; j < m; j++) { |
| char[][] qName = qNames[j]; |
| if (!internedQualifiedNames.containsKey(qName)) { // remember the names have been interned |
| internedQualifiedNames.put(qName, Integer.valueOf(internedQualifiedNames.elementSize)); |
| for (int k = 0, n = qName.length; k < n; k++) { |
| char[] sName = qName[k]; |
| if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned |
| internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize)); |
| } |
| } |
| } |
| char[][] sNames = collection.simpleNameReferences; |
| for (int j = 0, m = sNames.length; j < m; j++) { |
| char[] sName = sNames[j]; |
| if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned |
| internedSimpleNames.put(sName, Integer.valueOf(internedSimpleNames.elementSize)); |
| } |
| } |
| } |
| char[][] internedArray = new char[internedRootNames.elementSize][]; |
| Object[] rootNames = internedRootNames.keyTable; |
| Object[] positions = internedRootNames.valueTable; |
| for (int i = positions.length; --i >= 0; ) { |
| if (positions[i] != null) { |
| int index = ((Integer) positions[i]).intValue(); |
| internedArray[index] = (char[]) rootNames[i]; |
| } |
| } |
| writeNames(internedArray, out); |
| // now write the interned simple names |
| internedArray = new char[internedSimpleNames.elementSize][]; |
| Object[] simpleNames = internedSimpleNames.keyTable; |
| positions = internedSimpleNames.valueTable; |
| for (int i = positions.length; --i >= 0; ) { |
| if (positions[i] != null) { |
| int index = ((Integer) positions[i]).intValue(); |
| internedArray[index] = (char[]) simpleNames[i]; |
| } |
| } |
| writeNames(internedArray, out); |
| // now write the interned qualified names as arrays of interned simple names |
| char[][][] internedQArray = new char[internedQualifiedNames.elementSize][][]; |
| Object[] qualifiedNames = internedQualifiedNames.keyTable; |
| positions = internedQualifiedNames.valueTable; |
| for (int i = positions.length; --i >= 0; ) { |
| if (positions[i] != null) { |
| int index = ((Integer) positions[i]).intValue(); |
| internedQArray[index] = (char[][]) qualifiedNames[i]; |
| } |
| } |
| out.writeInt(length = internedQArray.length); |
| for (int i = 0; i < length; i++) { |
| char[][] qName = internedQArray[i]; |
| int qLength = qName.length; |
| out.writeInt(qLength); |
| for (int j = 0; j < qLength; j++) { |
| Integer index = (Integer) internedSimpleNames.get(qName[j]); |
| out.writeInt(index.intValue()); |
| } |
| } |
| |
| /* |
| * References table |
| * int interned locator id |
| * ReferenceCollection |
| */ |
| out.writeInt(length = this.references.elementSize); |
| if (length > 0) { |
| keyTable = this.references.keyTable; |
| for (int i = 0, l = keyTable.length; i < l; i++) { |
| if (keyTable[i] != null) { |
| length--; |
| Integer index = (Integer) internedTypeLocators.get(keyTable[i]); |
| out.writeInt(index.intValue()); |
| 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++) { |
| index = (Integer) internedQualifiedNames.get(qNames[j]); |
| out.writeInt(index.intValue()); |
| } |
| char[][] sNames = collection.simpleNameReferences; |
| int sLength = sNames.length; |
| out.writeInt(sLength); |
| for (int j = 0; j < sLength; j++) { |
| index = (Integer) internedSimpleNames.get(sNames[j]); |
| out.writeInt(index.intValue()); |
| } |
| char[][] rNames = collection.rootReferences; |
| int rLength = rNames.length; |
| out.writeInt(rLength); |
| for (int j = 0; j < rLength; j++) { |
| index = (Integer) internedRootNames.get(rNames[j]); |
| out.writeInt(index.intValue()); |
| } |
| } |
| } |
| if (JavaBuilder.DEBUG && length != 0) |
| System.out.println("references table is inconsistent"); //$NON-NLS-1$ |
| } |
| } |
| |
| private void writeName(char[] name, DataOutputStream out) throws IOException { |
| int nLength = name.length; |
| out.writeInt(nLength); |
| for (int j = 0; j < nLength; j++) |
| out.writeChar(name[j]); |
| } |
| |
| 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++) |
| writeName(names[i], out); |
| } |
| |
| private void writeRestriction(AccessRuleSet accessRuleSet, DataOutputStream out) throws IOException { |
| if (accessRuleSet == null) { |
| out.writeInt(0); |
| } else { |
| AccessRule[] accessRules = accessRuleSet.getAccessRules(); |
| int length = accessRules.length; |
| out.writeInt(length); |
| if (length != 0) { |
| for (int i = 0; i < length; i++) { |
| AccessRule accessRule = accessRules[i]; |
| writeName(accessRule.pattern, out); |
| out.writeInt(accessRule.problemId); |
| } |
| out.writeByte(accessRuleSet.classpathEntryType); |
| out.writeUTF(accessRuleSet.classpathEntryName); |
| } |
| } |
| } |
| |
| /** |
| * Returns a string representation of the receiver. |
| */ |
| public String toString() { |
| return "State for " + this.javaProjectName //$NON-NLS-1$ |
| + " (#" + this.buildNumber //$NON-NLS-1$ |
| + " @ " + new Date(this.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(" <empty>"); |
| } 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(" <empty>"); |
| } 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(" <empty>"); |
| } 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(" <empty>"); |
| 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(" <empty>"); |
| 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"); |
| } |
| */ |
| } |