Read jar files from input stream as a fallback. Do not rely on existsing files.
This commit is contained in:
parent
69846ed275
commit
cb02231692
|
@ -0,0 +1,252 @@
|
|||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.io.FileSuffixes;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.Warnings;
|
||||
|
||||
/**
|
||||
* Read in a jar file from an input stream. Most parts are copied from the NestedJarFileModule class
|
||||
* and adapted to work with an input stream.
|
||||
* @author Juergen Graf <juergen.graf@gmail.com>
|
||||
*/
|
||||
public class JarStreamModule implements Module {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final JarInputStream stream;
|
||||
|
||||
/**
|
||||
* For efficiency, we cache the byte[] holding each ZipEntry's contents; this will help avoid multiple unzipping TODO: use a soft
|
||||
* reference?
|
||||
*/
|
||||
private HashMap<String, byte[]> cache = null;
|
||||
|
||||
public JarStreamModule(JarInputStream stream) {
|
||||
if (stream == null) {
|
||||
throw new IllegalArgumentException("null stream");
|
||||
}
|
||||
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public InputStream getInputStream(String name) {
|
||||
populateCache();
|
||||
byte[] b = cache.get(name);
|
||||
return new ByteArrayInputStream(b);
|
||||
}
|
||||
|
||||
private void populateCache() {
|
||||
if (cache != null) {
|
||||
return;
|
||||
}
|
||||
cache = HashMapFactory.make();
|
||||
try {
|
||||
for (ZipEntry z = stream.getNextEntry(); z != null; z = stream.getNextEntry()) {
|
||||
final String name = z.getName();
|
||||
if (DEBUG) {
|
||||
System.err.println(("got entry: " + name));
|
||||
}
|
||||
if (FileSuffixes.isClassFile(name) || FileSuffixes.isSourceFile(name)) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] temp = new byte[1024];
|
||||
int n = stream.read(temp);
|
||||
while (n != -1) {
|
||||
out.write(temp, 0, n);
|
||||
n = stream.read(temp);
|
||||
}
|
||||
byte[] bb = out.toByteArray();
|
||||
cache.put(name, bb);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// just go with what we have
|
||||
Warnings.add(new Warning() {
|
||||
|
||||
@Override
|
||||
public String getMsg() {
|
||||
return "could not read contents of jar input stream.";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected long getEntrySize(String name) {
|
||||
populateCache();
|
||||
byte[] b = cache.get(name);
|
||||
return b.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.Module#getEntries()
|
||||
*/
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
populateCache();
|
||||
final Iterator<String> it = cache.keySet().iterator();
|
||||
return new Iterator<ModuleEntry>() {
|
||||
String next = null;
|
||||
{
|
||||
advance();
|
||||
}
|
||||
|
||||
private void advance() {
|
||||
if (it.hasNext()) {
|
||||
next = it.next();
|
||||
} else {
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public ModuleEntry next() {
|
||||
ModuleEntry result = new Entry(next);
|
||||
advance();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink an entry in a nested jar file.
|
||||
*/
|
||||
private class Entry implements ModuleEntry {
|
||||
|
||||
private final String name;
|
||||
|
||||
Entry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isClassFile()
|
||||
*/
|
||||
public boolean isClassFile() {
|
||||
return FileSuffixes.isClassFile(getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return JarStreamModule.this.getInputStream(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isModuleFile()
|
||||
*/
|
||||
public boolean isModuleFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#asModule()
|
||||
*/
|
||||
public Module asModule() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "nested entry: " + name;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getClassName()
|
||||
*/
|
||||
public String getClassName() {
|
||||
return FileSuffixes.stripSuffix(getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isSourceFile()
|
||||
*/
|
||||
public boolean isSourceFile() {
|
||||
return FileSuffixes.isSourceFile(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + getOuterType().hashCode();
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Entry other = (Entry) obj;
|
||||
if (!getOuterType().equals(other.getOuterType()))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private JarStreamModule getOuterType() {
|
||||
return JarStreamModule.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Jar input stream " + stream.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (stream.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
JarStreamModule other = (JarStreamModule) obj;
|
||||
return stream.equals(other.stream);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,11 +17,14 @@ import java.io.InputStream;
|
|||
import java.net.JarURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import com.ibm.wala.classLoader.JarFileModule;
|
||||
import com.ibm.wala.classLoader.JarStreamModule;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.classLoader.NestedJarFileModule;
|
||||
|
||||
|
@ -153,9 +156,15 @@ public class FileProvider {
|
|||
JarEntry entry = jc.getJarEntry();
|
||||
JarFileModule parent = new JarFileModule(f);
|
||||
return new NestedJarFileModule(parent, entry);
|
||||
} else {
|
||||
/** BEGIN Custom change: try to load from input stream as fallback */
|
||||
} else if (url.getProtocol().equals("file")) {
|
||||
String filePath = filePathFromURL(url);
|
||||
return new JarFileModule(new JarFile(filePath, false));
|
||||
} else {
|
||||
final URLConnection in = url.openConnection();
|
||||
final JarInputStream jarIn = new JarInputStream(in.getInputStream());
|
||||
return new JarStreamModule(jarIn);
|
||||
/** END Custom change: try to load from input stream as fallback */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue