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.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.*;
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.JavaModelManager;
import java.io.*;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@SuppressWarnings({"rawtypes", "unchecked"})
public class State {
String javaProjectName;
public ClasspathMultiDirectory[] sourceLocations;
public ClasspathMultiDirectory[] testSourceLocations;
ClasspathLocation[] binaryLocations;
ClasspathLocation[] testBinaryLocations;
SimpleLookupTable references;
public SimpleLookupTable typeLocators;
int buildNumber;
long lastStructuralBuildTime;
SimpleLookupTable structuralBuildTimes;
private String[] knownPackageNames;
private long previousStructuralBuildTime;
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100;
public static final byte VERSION = 0x0022;
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(JavaBuilder javaBuilder) {
this.knownPackageNames = null;
this.previousStructuralBuildTime = -1;
this.structurallyChangedTypes = null;
this.javaProjectName = javaBuilder.currentProject.getName();
this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations;
this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
this.testSourceLocations = javaBuilder.testNameEnvironment.sourceLocations;
this.testBinaryLocations = javaBuilder.testNameEnvironment.binaryLocations;
this.references = new SimpleLookupTable(7);
this.typeLocators = new SimpleLookupTable(7);
this.buildNumber = 0;
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;
}
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) {
LinkedHashSet<String> names = new LinkedHashSet<>(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];
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()][];
typeNames.toArray(definedTypeNames);
this.references.put(typeLocator, new AdditionalTypeCollection(definedTypeNames, qualifiedRefs, simpleRefs, rootRefs));
}
}
void recordLocatorForType(String qualifiedTypeName, String typeLocator) {
this.knownPackageNames = null;
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)
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, CoreException {
if (JavaBuilder.DEBUG)
System.out.println("About to read state " + project.getName());
if (VERSION != in.readByte()) {
if (JavaBuilder.DEBUG)
System.out.println("Found non-compatible state version... answered null for " + project.getName());
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");
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());
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()), in.readBoolean());
break;
case EXTERNAL_JAR :
String jarPath = in.readUTF();
if (Util.isJrt(jarPath)) {
newState.binaryLocations[i] = ClasspathLocation.forJrtSystem(jarPath, readRestriction(in), new Path(in.readUTF()), in.readUTF());
} else {
newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
}
break;
case INTERNAL_JAR :
newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
break;
}
ClasspathLocation loc = newState.binaryLocations[i];
char[] patchName = readName(in);
loc.patchModuleName = patchName.length > 0 ? new String(patchName) : null;
int limitSize = in.readInt();
if (limitSize != 0) {
loc.limitModuleNames = new LinkedHashSet<>(limitSize);
for (int j = 0; j < limitSize; j++) {
loc.limitModuleNames.add(in.readUTF());
}
} else {
loc.limitModuleNames = null;
}
IUpdatableModule.UpdatesByKind updates = new IUpdatableModule.UpdatesByKind();
List<Consumer<IUpdatableModule>> packageUpdates = null;
int packageUpdatesSize = in.readInt();
if (packageUpdatesSize != 0) {
packageUpdates = updates.getList(UpdateKind.PACKAGE, true);
for (int j = 0; j < packageUpdatesSize; j++) {
char[] pkgName = readName(in);
char[][] targets = readNames(in);
packageUpdates.add(new AddExports(pkgName, targets));
}
}
List<Consumer<IUpdatableModule>> moduleUpdates = null;
int moduleUpdatesSize = in.readInt();
if (moduleUpdatesSize != 0) {
moduleUpdates = updates.getList(UpdateKind.MODULE, true);
char[] modName = readName(in);
moduleUpdates.add(new AddReads(modName));
}
if (packageUpdates != null || moduleUpdates != null)
loc.updates = updates;
}
length = in.readInt();
newState.testSourceLocations = 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());
if (in.readBoolean())
md.hasIndependentOutputFolder = true;
newState.testSourceLocations[i] = md;
}
length = in.readInt();
newState.testBinaryLocations = new ClasspathLocation[length];
for (int i = 0; i < length; i++) {
switch (in.readByte()) {
case SOURCE_FOLDER :
newState.testBinaryLocations[i] = newState.testSourceLocations[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.testBinaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(),
readRestriction(in), new Path(in.readUTF()), in.readBoolean());
break;
case EXTERNAL_JAR :
String jarPath = in.readUTF();
if (Util.isJrt(jarPath)) {
newState.testBinaryLocations[i] = ClasspathLocation.forJrtSystem(jarPath, readRestriction(in), new Path(in.readUTF()), in.readUTF());
} else {
newState.testBinaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
}
break;
case INTERNAL_JAR :
newState.testBinaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
break;
}
}
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 , false );
char[][] internedSimpleNames = ReferenceCollection.internSimpleNames(readNames(in), false , 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 , 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);
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;
AccessRule[] accessRules = new AccessRule[length];
JavaModelManager manager = JavaModelManager.getJavaModelManager();
for (int i = 0; i < length; i++) {
char[] pattern = readName(in);
int problemId = in.readInt();
accessRules[i] = manager.getAccessRuleForProblemId(pattern,problemId);
}
return new AccessRuleSet(accessRules, in.readByte(), manager.intern(in.readUTF()));
}
void tagAsNoopBuild() {
this.buildNumber = -1;
}
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;
else
this.structurallyChangedTypes.add(typeName);
}
}
void write(DataOutputStream out) throws IOException {
int length;
Object[] keyTable;
Object[] valueTable;
out.writeByte(VERSION);
out.writeUTF(this.javaProjectName);
out.writeInt(this.buildNumber);
out.writeLong(this.lastStructuralBuildTime);
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);
}
out.writeInt(length = this.binaryLocations.length);
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);
}
}
} 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 : "");
out.writeBoolean(cd.isOnModulePath);
} 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 : "");
out.writeBoolean(jar.isOnModulePath);
out.writeUTF(jar.compliance == null ? "" : jar.compliance);
} else if (c instanceof ClasspathJrt) {
ClasspathJrt jrt = (ClasspathJrt) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : "");
out.writeUTF("");
} else {
ClasspathJrtWithReleaseOption jrt = (ClasspathJrtWithReleaseOption) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : "");
out.writeUTF(jrt.release);
}
char[] patchName = c.patchModuleName == null ? CharOperation.NO_CHAR : c.patchModuleName.toCharArray();
writeName(patchName, out);
if (c.limitModuleNames != null) {
out.writeInt(c.limitModuleNames.size());
for (String name : c.limitModuleNames) {
out.writeUTF(name);
}
} else {
out.writeInt(0);
}
if (c.updates != null) {
List<Consumer<IUpdatableModule>> pu = c.updates.getList(UpdateKind.PACKAGE, false);
if (pu != null) {
Map<String, List<Consumer<IUpdatableModule>>> map = pu.stream().
collect(Collectors.groupingBy(
update -> CharOperation.charToString(((IUpdatableModule.AddExports)update).getName())));
out.writeInt(map.size());
map.entrySet().stream().forEach(entry -> {
String pkgName = entry.getKey();
try {
writeName(pkgName.toCharArray(), out);
char[][] targetModules = entry.getValue().stream()
.map(consumer -> ((IUpdatableModule.AddExports) consumer).getTargetModules())
.filter(targets -> targets != null)
.reduce((f,s) -> CharOperation.arrayConcat(f,s))
.orElse(null);
writeNames(targetModules, out);
} catch (IOException e) {
}
});
} else {
out.writeInt(0);
}
List<Consumer<IUpdatableModule>> mu = c.updates.getList(UpdateKind.MODULE, false);
if (mu != null) {
out.writeInt(mu.size());
for (Consumer<IUpdatableModule> cons : mu) {
AddReads m = (AddReads) cons;
writeName(m.getTarget(), out);
}
} else {
out.writeInt(0);
}
} else {
out.writeInt(0);
out.writeInt(0);
}
}
out.writeInt(length = this.testSourceLocations.length);
for (int i = 0; i < length; i++) {
ClasspathMultiDirectory md = this.testSourceLocations[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);
}
out.writeInt(length = this.testBinaryLocations.length);
next : for (int i = 0; i < length; i++) {
ClasspathLocation c = this.testBinaryLocations[i];
if (c instanceof ClasspathMultiDirectory) {
out.writeByte(SOURCE_FOLDER);
for (int j = 0, m = this.testSourceLocations.length; j < m; j++) {
if (this.testSourceLocations[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 : "");
out.writeBoolean(cd.isOnModulePath);
} 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 : "");
out.writeBoolean(jar.isOnModulePath);
out.writeUTF(jar.compliance != null ? jar.compliance : "");
} else if (c instanceof ClasspathJrt) {
ClasspathJrt jrt = (ClasspathJrt) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : "");
out.writeUTF("");
} else {
ClasspathJrtWithReleaseOption jrt = (ClasspathJrtWithReleaseOption) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : "");
out.writeUTF(jrt.release);
}
}
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");
}
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");
}
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");
}
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))
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)) {
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))
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))
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);
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);
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());
}
}
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");
}
}
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);
}
}
}
@Override
public String toString() {
return "State for " + this.javaProjectName
+ " (#" + this.buildNumber
+ " @ " + new Date(this.lastStructuralBuildTime)
+ ")";
}
}