blob: b901ce373493dde1e6116f19bec832ff7cef00f9 [file] [log] [blame]
package org.apache.felix.ipojo.plugin;
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
public class Jar {
Map resources = new TreeMap();
Map imports = new HashMap();
Map exports = new HashMap();
Manifest manifest;
boolean manifestFirst;
String name;
Jar parent;
List activators = new ArrayList();
public Jar(Jar parent, String name, InputStream in) throws IOException {
this.name = name;
this.parent = parent;
ZipInputStream jar = new ZipInputStream(in);
ZipEntry entry = jar.getNextEntry();
boolean first = true;
while (entry != null) {
String path = entry.getName();
if (path.endsWith(".class")) {
Clazz clazz = new Clazz(this, path, jar);
resources.put(path, clazz);
}
else if (path.endsWith(".jar")) {
Jar pool = new Jar(this, path, jar);
resources.put(path, pool);
}
else if (path.endsWith("/packageinfo")
&& !path.startsWith("OSGI-OPT")) {
String version = parsePackageInfo(jar, exports);
resources.put(path, version);
}
else if (path.equals("META-INF/MANIFEST.MF")) {
manifestFirst = first;
manifest = new Manifest(jar);
}
else
resources.put(path, null);
entry = jar.getNextEntry();
if (!path.endsWith("/"))
first = false;
}
}
public Jar(Jar parent, String name, File rootDir) throws IOException {
this.name = name;
this.parent = parent;
traverse(rootDir.getAbsolutePath().length(), rootDir, rootDir.list());
}
void traverse(int root, File dir, String list[]) throws IOException {
for (int i = 0; i < list.length; i++) {
File sub = new File(dir, list[i]);
if (sub.isDirectory())
traverse(root, sub, sub.list());
else {
String path = sub.getAbsolutePath().substring(root + 1)
.replace(File.separatorChar, '/');
FileInputStream in = new FileInputStream(sub);
if (path.endsWith(".class")) {
Clazz clazz = new Clazz(this, path, in);
resources.put(path, clazz);
}
else if (path.endsWith(".jar")) {
Jar pool = new Jar(this, path, in);
resources.put(path, pool);
}
else if (path.endsWith("/packageinfo")
&& !path.startsWith("OSGI-OPT")) {
String version = parsePackageInfo(in, exports);
resources.put(path, version);
}
else if (path.endsWith("META-INF/MANIFEST.MF")) {
manifest = new Manifest(in);
}
else
resources.put(path, null);
}
}
}
private static String parsePackageInfo(InputStream jar, Map exports)
throws IOException {
try {
byte[] buf = collect(jar, 0);
String line = new String(buf);
StringTokenizer qt = new StringTokenizer(line, " \r\n\t");
if (qt.hasMoreElements()) {
qt.nextToken();
if (qt.hasMoreElements()) {
String version = qt.nextToken();
return version;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Convenience method to turn an inputstream into a byte array. The method
* uses a recursive algorithm to minimize memory usage.
*
* @param in stream with data
* @param offset where we are in the stream
* @returns byte array filled with data
*/
private static byte[] collect(InputStream in, int offset)
throws IOException {
byte[] result;
byte[] buffer = new byte[10000];
int size = in.read(buffer);
if (size <= 0)
return new byte[offset];
else
result = collect(in, offset + size);
System.arraycopy(buffer, 0, result, offset, size);
return result;
}
public Manifest getManifest() {
return manifest;
}
public Object getEntry(String resource) {
return resources.get(resource);
}
public boolean exists(String jarOrDir) {
return resources.keySet().contains(jarOrDir);
}
public Set getEntryPaths(String prefix) {
Set result = new TreeSet();
for (Iterator i = resources.keySet().iterator(); i.hasNext();) {
String path = (String) i.next();
if (path.startsWith(prefix))
result.add(path);
}
return result;
}
String getName() {
return name;
}
public String toString() {
return getName();
}
public void addActivator(String path) {
if (parent != null)
parent.addActivator(path);
else {
activators.add(path);
}
}
public boolean containsActivator(String path) {
if (parent != null)
return parent.containsActivator(path);
return activators.contains(path);
}
}