blob: e75e2064181db45a066bfa7dafe71a2295f7b227 [file] [log] [blame]
/* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved
*
* This program is distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
package org.pantsbuild.jmake;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* This class creates the internal representation of the project database from a byte array.
*
* @author Misha Dmitriev
* 2 March 2005
*/
public class BinaryProjectDatabaseReader extends BinaryFileReader {
private String stringTable[];
private Map<String,PCDEntry> pcd;
private int nOfEntries;
private int pdbFormat; // Currently supported values: 0x01030300 (jmake 1.3.3 and newer versions); 1 (all older versions)
// These are defined in Utils as PDB_FORMAT_CODE_LATEST and PDB_FORMAT_CODE_OLD
public Map<String,PCDEntry> readProjectDatabaseFromFile(File infile) {
byte buf[] = Utils.readFileIntoBuffer(infile);
return readProjectDatabase(buf, infile.toString());
}
public Map<String,PCDEntry> readProjectDatabase(byte[] pdbFile,
String pdbFileFullPath) {
initBuf(pdbFile, pdbFileFullPath);
readPreamble();
readStringTable();
pcd = new LinkedHashMap<String,PCDEntry>(nOfEntries * 4 / 3);
for (int i = 0; i < nOfEntries; i++) {
PCDEntry entry = readPCDEntry();
pcd.put(entry.className, entry);
}
stringTable = null; // Help the GC
return pcd;
}
private void readPreamble() {
if (buf.length < Utils.magicLength + 8) {
pdbCorruptedException("file too short");
}
for (int i = 0; i < Utils.magicLength; i++) {
if (buf[i] != Utils.MAGIC[i]) {
pdbCorruptedException("wrong project database header");
}
}
curBufPos += Utils.magicLength;
pdbFormat = nextInt();
if (pdbFormat != Utils.PDB_FORMAT_CODE_OLD && pdbFormat != Utils.PDB_FORMAT_CODE_LATEST) {
pdbCorruptedException("wrong version number");
}
int pdbSize = nextInt();
if (buf.length != Utils.MAGIC.length + 8 + pdbSize) {
pdbCorruptedException("file size does not match stored value");
}
nOfEntries = nextInt();
}
private void readStringTable() {
int size = nextInt();
stringTable = new String[size];
for (int i = 0; i < size; i++) {
stringTable[i] = nextString();
}
}
private PCDEntry readPCDEntry() {
String className = nextStringRef();
String javaFileFullPath = nextStringRef();
long classFileLastModified = nextLong();
long classFileFingerprint = nextLong();
ClassInfo classInfo = readClassInfo();
return new PCDEntry(className, javaFileFullPath, classFileLastModified, classFileFingerprint, classInfo);
}
private ClassInfo readClassInfo() {
int i, j, len;
ClassInfo res = new ClassInfo();
res.name = nextStringRef();
if (pdbFormat >= Utils.PDB_FORMAT_CODE_133) {
res.javacTargetRelease = nextInt();
} else {
res.javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST;
}
len = nextChar();
if (len > 0) {
String cpoolRefsToClasses[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToClasses[i] = nextStringRef();
}
res.cpoolRefsToClasses = cpoolRefsToClasses;
boolean isRefClassArray[] = new boolean[len];
for (i = 0; i < len; i++) {
isRefClassArray[i] = (buf[curBufPos++] != 0);
}
res.isRefClassArray = isRefClassArray;
}
len = nextChar();
if (len > 0) {
String cpoolRefsToFieldClasses[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToFieldClasses[i] = nextStringRef();
}
res.cpoolRefsToFieldClasses = cpoolRefsToFieldClasses;
String cpoolRefsToFieldNames[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToFieldNames[i] = nextStringRef();
}
res.cpoolRefsToFieldNames = cpoolRefsToFieldNames;
String cpoolRefsToFieldSignatures[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToFieldSignatures[i] = nextStringRef();
}
res.cpoolRefsToFieldSignatures = cpoolRefsToFieldSignatures;
}
len = nextChar();
if (len > 0) {
String cpoolRefsToMethodClasses[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToMethodClasses[i] = nextStringRef();
}
res.cpoolRefsToMethodClasses = cpoolRefsToMethodClasses;
String cpoolRefsToMethodNames[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToMethodNames[i] = nextStringRef();
}
res.cpoolRefsToMethodNames = cpoolRefsToMethodNames;
String cpoolRefsToMethodSignatures[] = new String[len];
for (i = 0; i < len; i++) {
cpoolRefsToMethodSignatures[i] = nextStringRef();
}
res.cpoolRefsToMethodSignatures = cpoolRefsToMethodSignatures;
}
res.accessFlags = nextChar();
res.isNonMemberNestedClass = (buf[curBufPos++] != 0);
if (!"java/lang/Object".equals(res.name)) {
res.superName = nextStringRef();
}
len = nextChar();
if (len > 0) {
String interfaces[] = new String[len];
for (i = 0; i < len; i++) {
interfaces[i] = nextStringRef();
}
res.interfaces = interfaces;
}
len = nextChar();
if (len > 0) {
String fieldNames[] = new String[len];
for (i = 0; i < len; i++) {
fieldNames[i] = nextStringRef();
}
res.fieldNames = fieldNames;
String fieldSignatures[] = new String[len];
for (i = 0; i < len; i++) {
fieldSignatures[i] = nextStringRef();
}
res.fieldSignatures = fieldSignatures;
char fieldAccessFlags[] = new char[len];
for (i = 0; i < len; i++) {
fieldAccessFlags[i] = nextChar();
}
res.fieldAccessFlags = fieldAccessFlags;
}
len = nextChar();
if (len > 0) {
Object primitiveConstantInitValues[] = new Object[len];
for (i = 0; i < len; i++) {
byte code = buf[curBufPos++];
switch (code) {
case 1:
primitiveConstantInitValues[i] = nextStringRef();
break;
case 2:
primitiveConstantInitValues[i] = Integer.valueOf(nextInt());
break;
case 3:
primitiveConstantInitValues[i] = Long.valueOf(nextLong());
break;
case 4:
primitiveConstantInitValues[i] = Float.valueOf(nextFloat());
break;
case 5:
primitiveConstantInitValues[i] =
Double.valueOf(nextDouble());
break;
default: // Nothing to do
}
}
res.primitiveConstantInitValues = primitiveConstantInitValues;
}
len = nextChar();
if (len > 0) {
String methodNames[] = new String[len];
for (i = 0; i < len; i++) {
methodNames[i] = nextStringRef();
}
res.methodNames = methodNames;
String methodSignatures[] = new String[len];
for (i = 0; i < len; i++) {
methodSignatures[i] = nextStringRef();
}
res.methodSignatures = methodSignatures;
char methodAccessFlags[] = new char[len];
for (i = 0; i < len; i++) {
methodAccessFlags[i] = nextChar();
}
res.methodAccessFlags = methodAccessFlags;
}
len = nextChar();
if (len > 0) {
String checkedExceptions[][] = new String[len][];
for (i = 0; i < len; i++) {
int len1 = nextChar();
if (len1 > 0) {
checkedExceptions[i] = new String[len1];
for (j = 0; j < len1; j++) {
checkedExceptions[i][j] = nextStringRef();
}
}
}
res.checkedExceptions = checkedExceptions;
}
len = nextChar();
if (len > 0) {
String nestedClasses[] = new String[len];
for (i = 0; i < len; i++) {
nestedClasses[i] = nextStringRef();
}
res.nestedClasses = nestedClasses;
}
res.initializeImmediateTransientFields();
return res;
}
private String nextString() {
int length = nextChar();
if (buf.length < curBufPos + length) {
pdbCorruptedException("data error");
}
String res = (new String(buf, curBufPos, length)).intern();
curBufPos += length;
return res;
}
private String nextStringRef() {
return stringTable[nextInt()];
}
private void pdbCorruptedException(String message) {
throw new PrivateException(new PublicExceptions.PDBCorruptedException(message));
}
}