115 lines
3.1 KiB
Java
115 lines
3.1 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
* 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
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*******************************************************************************/
|
|
package com.ibm.wala.util.shrike;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
|
|
import com.ibm.wala.classLoader.ModuleEntry;
|
|
import com.ibm.wala.shrikeCT.ClassReader;
|
|
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
import com.ibm.wala.util.ref.CacheReference;
|
|
|
|
/**
|
|
* A soft handle to a Shrike class reader
|
|
*
|
|
* TODO: implement more effective caching than just soft references TODO: push
|
|
* weakness up the chain the InputStream, etc ... TODO: reduce reliance on
|
|
* reader throughout the analysis packages
|
|
*/
|
|
public class ShrikeClassReaderHandle {
|
|
|
|
private final static boolean DEBUG = false;
|
|
/**
|
|
* The module entry that defines the class file
|
|
*/
|
|
private final ModuleEntry entry;
|
|
|
|
private Object reader;
|
|
|
|
/**
|
|
* The number of times we hydrate the reader
|
|
*/
|
|
private int hydrateCount = 0;
|
|
|
|
public ShrikeClassReaderHandle(ModuleEntry entry) {
|
|
if (entry == null) {
|
|
throw new IllegalArgumentException("null entry");
|
|
}
|
|
this.entry = entry;
|
|
}
|
|
|
|
/**
|
|
* @return an instance of the class reader ... create one if necessary
|
|
* @throw InvalidClassFileException iff Shrike fails to read the class file
|
|
* correctly.
|
|
*/
|
|
public ClassReader get() throws InvalidClassFileException {
|
|
ClassReader result = (ClassReader) CacheReference.get(reader);
|
|
if (result == null) {
|
|
hydrateCount++;
|
|
if (DEBUG) {
|
|
if (hydrateCount > 1) {
|
|
System.err.println(("Hydrate " + entry + " " + hydrateCount));
|
|
try {
|
|
throw new Exception();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
ByteArrayOutputStream S = new ByteArrayOutputStream();
|
|
try {
|
|
InputStream s = entry.getInputStream();
|
|
readBytes(s, S);
|
|
s.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
Assertions.UNREACHABLE();
|
|
}
|
|
result = new ClassReader(S.toByteArray());
|
|
reader = CacheReference.make(result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Read is into bytes
|
|
* @throws IOException
|
|
*/
|
|
private static void readBytes(InputStream is, ByteArrayOutputStream bytes) throws IOException {
|
|
int n = 0;
|
|
byte[] buffer = new byte[1024];
|
|
while (n > -1) {
|
|
n = is.read(buffer, 0, 1024);
|
|
if (n > -1) {
|
|
bytes.write(buffer, 0, n);
|
|
}
|
|
}
|
|
}
|
|
|
|
public String getFileName() {
|
|
return entry.getName();
|
|
}
|
|
|
|
/**
|
|
* Force the reference to be cleared/collected
|
|
*/
|
|
public void clear() {
|
|
reader = null;
|
|
}
|
|
|
|
public ModuleEntry getModuleEntry() {
|
|
return entry;
|
|
}}
|