blob: 58b09c72defeeb50580e532aee6f9a9f68413f48 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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);
}
}