Author: davidb
Date: Tue Feb 11 14:44:51 2014
New Revision: 1567159
URL: http://svn.apache.org/r1567159
Log:
Convert file to use unix line delimiters.
Modified:
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
Modified:
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
URL:
http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java?rev=1567159&r1=1567158&r2=1567159&view=diff
==============================================================================
---
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
(original)
+++
aries/trunk/spi-fly/spi-fly-static-tool/src/main/java/org/apache/aries/spifly/statictool/Main.java
Tue Feb 11 14:44:51 2014
@@ -1,348 +1,348 @@
-/**
- * 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.aries.spifly.statictool;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Properties;
-import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-import org.apache.aries.spifly.ConsumerHeaderProcessor;
-import org.apache.aries.spifly.SpiFlyConstants;
-import org.apache.aries.spifly.Streams;
-import org.apache.aries.spifly.Util;
-import org.apache.aries.spifly.WeavingData;
-import org.apache.aries.spifly.weaver.TCCLSetterVisitor;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-public class Main {
- private static final String MODIFIED_BUNDLE_SUFFIX = "_spifly.jar";
- private static final String IMPORT_PACKAGE = "Import-Package";
-
- public static void usage() {
- System.err.println("This tool processes OSGi Bundles that use
java.util.ServiceLoader.load() to");
- System.err.println("obtain implementations via META-INF/services. The
byte code in the bundles is");
- System.err.println("modified so that the ThreadContextClassLoader is
set appropriately for the ");
- System.err.println("duration of the java.util.ServiceLoader.load()
call.");
- System.err.println("To opt-in to this process, bundles need to have
the following MANIFEST.MF");
- System.err.println("header set:");
- System.err.println(" " + SpiFlyConstants.SPI_CONSUMER_HEADER + ":
*");
- System.err.println("Modified bundles are written out under the
following name:");
- System.err.println(" <original-bundle-name>" +
MODIFIED_BUNDLE_SUFFIX);
- System.err.println();
- System.err.println("Usage: java " + Main.class.getName() + "
bundle1.jar bundle2.jar ...");
- System.exit(-1);
- }
-
- public static void main(String ... args) throws Exception {
- if (args.length < 1)
- usage();
-
- for (String arg : args) {
- weaveJar(arg);
- }
- }
-
- private static void weaveJar(String jarPath) throws Exception {
- System.out.println("[SPI Fly Static Tool] Processing: " + jarPath);
-
- File jarFile = new File(jarPath);
- File tempDir = new File(System.getProperty("java.io.tmpdir") +
File.separator + jarFile.getName() + "_" + System.currentTimeMillis());
- Manifest manifest = unJar(jarFile, tempDir);
- String consumerHeaderVal =
manifest.getMainAttributes().getValue(SpiFlyConstants.SPI_CONSUMER_HEADER);
- String consumerHeaderKey = null;
- if (consumerHeaderVal != null) {
- consumerHeaderKey = SpiFlyConstants.SPI_CONSUMER_HEADER;
- } else {
- consumerHeaderVal =
manifest.getMainAttributes().getValue(SpiFlyConstants.REQUIRE_CAPABILITY);
- if (consumerHeaderVal != null) {
- consumerHeaderKey = SpiFlyConstants.REQUIRE_CAPABILITY;
- }
- }
-
- if (consumerHeaderVal != null) {
- String bcp =
manifest.getMainAttributes().getValue(Constants.BUNDLE_CLASSPATH);
- weaveDir(tempDir, consumerHeaderKey, consumerHeaderVal, bcp);
-
- if (SpiFlyConstants.SPI_CONSUMER_HEADER.equals(consumerHeaderKey))
{
- manifest.getMainAttributes().remove(new
Attributes.Name(SpiFlyConstants.SPI_CONSUMER_HEADER));
-
manifest.getMainAttributes().putValue(SpiFlyConstants.PROCESSED_SPI_CONSUMER_HEADER,
consumerHeaderVal);
- } else {
- // It's SpiFlyConstants.REQUIRE_CAPABILITY
-
- // Take out the processor requirement, this probably needs to
be improved a little bit
- String newConsumerHeaderVal = consumerHeaderVal.replaceAll(
-
"osgi[.]extender;\\s*filter[:][=][\"]?[(]osgi[.]extender[=]osgi[.]serviceloader[.]processor[)][\"]?",
"").
- trim();
- if (newConsumerHeaderVal.startsWith(","))
- newConsumerHeaderVal = newConsumerHeaderVal.substring(1);
-
- if (newConsumerHeaderVal.endsWith(","))
- newConsumerHeaderVal = newConsumerHeaderVal.substring(0,
newConsumerHeaderVal.length()-1);
-
manifest.getMainAttributes().putValue(SpiFlyConstants.REQUIRE_CAPABILITY,
newConsumerHeaderVal);
-
manifest.getMainAttributes().putValue("X-SpiFly-Processed-Require-Capability",
consumerHeaderVal);
- }
-
- // TODO if new packages needed then...
- extendImportPackage(manifest);
-
- File newJar = getNewJarFile(jarFile);
- jar(newJar, tempDir, manifest);
- } else {
- System.out.println("[SPI Fly Static Tool] This file is not marked
as an SPI Consumer.");
- }
- delTree(tempDir);
- }
-
- private static void extendImportPackage(Manifest manifest) throws
IOException {
- String utilPkgVersion = getPackageVersion(Util.class);
-
- Version osgiVersion = Version.parseVersion(utilPkgVersion);
-
- Version minVersion = new Version(osgiVersion.getMajor(),
osgiVersion.getMinor(), osgiVersion.getMicro());
- Version maxVersion = new Version(osgiVersion.getMajor(),
osgiVersion.getMinor() + 1, 0);
-
- String ip = manifest.getMainAttributes().getValue(IMPORT_PACKAGE);
- if (ip == null)
- ip = "";
-
- StringBuilder sb = new StringBuilder(ip);
- if (ip.length() > 0)
- sb.append(",");
- sb.append(Util.class.getPackage().getName());
- sb.append(";version=\"[");
- sb.append(minVersion);
- sb.append(",");
- sb.append(maxVersion);
- sb.append(")\"");
- manifest.getMainAttributes().putValue(IMPORT_PACKAGE, sb.toString());
- }
-
- private static String getPackageVersion(Class<?> clazz) throws IOException
{
- URL url = clazz.getResource("packageinfo");
- if (url == null) {
- throw new RuntimeException("'packageinfo' file with version
information not found for package: "
- + clazz.getPackage().getName());
- }
-
- byte[] bytes = Streams.suck(url.openStream());
- Properties p = new Properties();
- p.load(new ByteArrayInputStream(bytes));
- return p.getProperty("version");
- }
-
- private static File getNewJarFile(File jarFile) {
- String s = jarFile.getAbsolutePath();
- int idx = s.lastIndexOf('.');
- s = s.substring(0, idx);
- s += MODIFIED_BUNDLE_SUFFIX;
- return new File(s);
- }
-
- private static void weaveDir(File dir, String consumerHeaderKey, String
consumerHeaderValue, String bundleClassPath) throws Exception {
- Set<WeavingData> wd =
ConsumerHeaderProcessor.processHeader(consumerHeaderKey, consumerHeaderValue);
-
- URLClassLoader cl = new URLClassLoader(new URL []
{dir.toURI().toURL()}, Main.class.getClassLoader());
- String dirName = dir.getAbsolutePath();
-
- DirTree dt = new DirTree(dir);
- for (File f : dt.getFiles()) {
- if (!f.getName().endsWith(".class"))
- continue;
-
- String className = f.getAbsolutePath().substring(dirName.length());
- if (className.startsWith(File.separator))
- className = className.substring(1);
- className = className.substring(0, className.length() -
".class".length());
- className = className.replace(File.separator, ".");
-
- InputStream is = new FileInputStream(f);
- byte[] b;
- try {
- ClassReader cr = new ClassReader(is);
- ClassWriter cw = new
StaticToolClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES,
cl);
- TCCLSetterVisitor cv = new TCCLSetterVisitor(cw, className,
wd);
- cr.accept(cv, ClassReader.SKIP_FRAMES);
- if (cv.isWoven()) {
- b = cw.toByteArray();
- } else {
- // if not woven, store the original bytes
- b = Streams.suck(new FileInputStream(f));
- }
- } finally {
- is.close();
- }
-
- OutputStream os = new FileOutputStream(f);
- try {
- os.write(b);
- } finally {
- os.close();
- }
- }
-
- if (bundleClassPath != null) {
- for (String entry : bundleClassPath.split(",")) {
- File jarFile = new File(dir, entry.trim());
- if (jarFile.isFile()) {
- weaveBCPJar(jarFile, consumerHeaderKey,
consumerHeaderValue);
- }
- }
- }
- }
-
- private static void weaveBCPJar(File jarFile, String consumerHeaderKey,
String consumerHeaderVal) throws Exception {
- File tempDir = new File(System.getProperty("java.io.tmpdir") +
File.separator + jarFile.getName() + "_" + System.currentTimeMillis());
- try {
- Manifest manifest = unJar(jarFile, tempDir);
- weaveDir(tempDir, consumerHeaderKey, consumerHeaderVal, null);
- if (!jarFile.delete()) {
- throw new IOException("Could not replace file: " + jarFile);
- }
-
- jar(jarFile, tempDir, manifest);
- } finally {
- delTree(tempDir);
- }
- }
-
- static Manifest unJar(File jarFile, File tempDir) throws IOException {
- ensureDirectory(tempDir);
-
- JarInputStream jis = new JarInputStream(new FileInputStream(jarFile));
- JarEntry je = null;
- while((je = jis.getNextJarEntry()) != null) {
- if (je.isDirectory()) {
- File outDir = new File(tempDir, je.getName());
- ensureDirectory(outDir);
-
- continue;
- }
-
- File outFile = new File(tempDir, je.getName());
- File outDir = outFile.getParentFile();
- ensureDirectory(outDir);
-
- OutputStream out = new FileOutputStream(outFile);
- try {
- Streams.pump(jis, out);
- } finally {
- out.flush();
- out.close();
- jis.closeEntry();
- }
- outFile.setLastModified(je.getTime());
- }
-
- Manifest manifest = jis.getManifest();
- if (manifest != null) {
- File mf = new File(tempDir, "META-INF/MANIFEST.MF");
- File mfDir = mf.getParentFile();
- ensureDirectory(mfDir);
-
- OutputStream out = new FileOutputStream(mf);
- try {
- manifest.write(out);
- } finally {
- out.flush();
- out.close();
- }
- }
-
- jis.close();
- return manifest;
- }
-
- static void jar(File jarFile, File rootFile, Manifest manifest) throws
IOException {
- JarOutputStream jos = new JarOutputStream(new
FileOutputStream(jarFile), manifest);
- try {
- addToJarRecursively(jos, rootFile.getAbsoluteFile(),
rootFile.getAbsolutePath());
- } finally {
- jos.close();
- }
- }
-
- static void addToJarRecursively(JarOutputStream jar, File source, String
rootDirectory) throws IOException {
- String sourceName = source.getAbsolutePath().replace("\\", "/");
- sourceName = sourceName.substring(rootDirectory.length());
-
- if (sourceName.startsWith("/")) {
- sourceName = sourceName.substring(1);
- }
-
- if ("META-INF/MANIFEST.MF".equals(sourceName))
- return;
-
- if (source.isDirectory()) {
- /* Is there any point in adding a directory beyond just taking up
space?
- if (!sourceName.isEmpty()) {
- if (!sourceName.endsWith("/")) {
- sourceName += "/";
- }
- JarEntry entry = new JarEntry(sourceName);
- jar.putNextEntry(entry);
- jar.closeEntry();
- }
- */
- for (File nested : source.listFiles()) {
- addToJarRecursively(jar, nested, rootDirectory);
- }
- return;
- }
-
- JarEntry entry = new JarEntry(sourceName);
- jar.putNextEntry(entry);
- InputStream is = new FileInputStream(source);
- try {
- Streams.pump(is, jar);
- } finally {
- jar.closeEntry();
- is.close();
- }
- }
-
- static void delTree(File tempDir) throws IOException {
- for (File f : new DirTree(tempDir).getFiles()) {
- if (!f.delete())
- throw new IOException("Problem deleting file: " +
tempDir.getAbsolutePath());
- }
- }
-
- private static void ensureDirectory(File outDir) throws IOException {
- if (!outDir.isDirectory())
- if (!outDir.mkdirs())
- throw new IOException("Unable to create directory " +
outDir.getAbsolutePath());
- }
-}
-
+/**
+ * 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.aries.spifly.statictool;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.aries.spifly.ConsumerHeaderProcessor;
+import org.apache.aries.spifly.SpiFlyConstants;
+import org.apache.aries.spifly.Streams;
+import org.apache.aries.spifly.Util;
+import org.apache.aries.spifly.WeavingData;
+import org.apache.aries.spifly.weaver.TCCLSetterVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+public class Main {
+ private static final String MODIFIED_BUNDLE_SUFFIX = "_spifly.jar";
+ private static final String IMPORT_PACKAGE = "Import-Package";
+
+ public static void usage() {
+ System.err.println("This tool processes OSGi Bundles that use
java.util.ServiceLoader.load() to");
+ System.err.println("obtain implementations via META-INF/services. The
byte code in the bundles is");
+ System.err.println("modified so that the ThreadContextClassLoader is
set appropriately for the ");
+ System.err.println("duration of the java.util.ServiceLoader.load()
call.");
+ System.err.println("To opt-in to this process, bundles need to have
the following MANIFEST.MF");
+ System.err.println("header set:");
+ System.err.println(" " + SpiFlyConstants.SPI_CONSUMER_HEADER + ":
*");
+ System.err.println("Modified bundles are written out under the
following name:");
+ System.err.println(" <original-bundle-name>" +
MODIFIED_BUNDLE_SUFFIX);
+ System.err.println();
+ System.err.println("Usage: java " + Main.class.getName() + "
bundle1.jar bundle2.jar ...");
+ System.exit(-1);
+ }
+
+ public static void main(String ... args) throws Exception {
+ if (args.length < 1)
+ usage();
+
+ for (String arg : args) {
+ weaveJar(arg);
+ }
+ }
+
+ private static void weaveJar(String jarPath) throws Exception {
+ System.out.println("[SPI Fly Static Tool] Processing: " + jarPath);
+
+ File jarFile = new File(jarPath);
+ File tempDir = new File(System.getProperty("java.io.tmpdir") +
File.separator + jarFile.getName() + "_" + System.currentTimeMillis());
+ Manifest manifest = unJar(jarFile, tempDir);
+ String consumerHeaderVal =
manifest.getMainAttributes().getValue(SpiFlyConstants.SPI_CONSUMER_HEADER);
+ String consumerHeaderKey = null;
+ if (consumerHeaderVal != null) {
+ consumerHeaderKey = SpiFlyConstants.SPI_CONSUMER_HEADER;
+ } else {
+ consumerHeaderVal =
manifest.getMainAttributes().getValue(SpiFlyConstants.REQUIRE_CAPABILITY);
+ if (consumerHeaderVal != null) {
+ consumerHeaderKey = SpiFlyConstants.REQUIRE_CAPABILITY;
+ }
+ }
+
+ if (consumerHeaderVal != null) {
+ String bcp =
manifest.getMainAttributes().getValue(Constants.BUNDLE_CLASSPATH);
+ weaveDir(tempDir, consumerHeaderKey, consumerHeaderVal, bcp);
+
+ if (SpiFlyConstants.SPI_CONSUMER_HEADER.equals(consumerHeaderKey))
{
+ manifest.getMainAttributes().remove(new
Attributes.Name(SpiFlyConstants.SPI_CONSUMER_HEADER));
+
manifest.getMainAttributes().putValue(SpiFlyConstants.PROCESSED_SPI_CONSUMER_HEADER,
consumerHeaderVal);
+ } else {
+ // It's SpiFlyConstants.REQUIRE_CAPABILITY
+
+ // Take out the processor requirement, this probably needs to
be improved a little bit
+ String newConsumerHeaderVal = consumerHeaderVal.replaceAll(
+
"osgi[.]extender;\\s*filter[:][=][\"]?[(]osgi[.]extender[=]osgi[.]serviceloader[.]processor[)][\"]?",
"").
+ trim();
+ if (newConsumerHeaderVal.startsWith(","))
+ newConsumerHeaderVal = newConsumerHeaderVal.substring(1);
+
+ if (newConsumerHeaderVal.endsWith(","))
+ newConsumerHeaderVal = newConsumerHeaderVal.substring(0,
newConsumerHeaderVal.length()-1);
+
manifest.getMainAttributes().putValue(SpiFlyConstants.REQUIRE_CAPABILITY,
newConsumerHeaderVal);
+
manifest.getMainAttributes().putValue("X-SpiFly-Processed-Require-Capability",
consumerHeaderVal);
+ }
+
+ // TODO if new packages needed then...
+ extendImportPackage(manifest);
+
+ File newJar = getNewJarFile(jarFile);
+ jar(newJar, tempDir, manifest);
+ } else {
+ System.out.println("[SPI Fly Static Tool] This file is not marked
as an SPI Consumer.");
+ }
+ delTree(tempDir);
+ }
+
+ private static void extendImportPackage(Manifest manifest) throws
IOException {
+ String utilPkgVersion = getPackageVersion(Util.class);
+
+ Version osgiVersion = Version.parseVersion(utilPkgVersion);
+
+ Version minVersion = new Version(osgiVersion.getMajor(),
osgiVersion.getMinor(), osgiVersion.getMicro());
+ Version maxVersion = new Version(osgiVersion.getMajor(),
osgiVersion.getMinor() + 1, 0);
+
+ String ip = manifest.getMainAttributes().getValue(IMPORT_PACKAGE);
+ if (ip == null)
+ ip = "";
+
+ StringBuilder sb = new StringBuilder(ip);
+ if (ip.length() > 0)
+ sb.append(",");
+ sb.append(Util.class.getPackage().getName());
+ sb.append(";version=\"[");
+ sb.append(minVersion);
+ sb.append(",");
+ sb.append(maxVersion);
+ sb.append(")\"");
+ manifest.getMainAttributes().putValue(IMPORT_PACKAGE, sb.toString());
+ }
+
+ private static String getPackageVersion(Class<?> clazz) throws IOException
{
+ URL url = clazz.getResource("packageinfo");
+ if (url == null) {
+ throw new RuntimeException("'packageinfo' file with version
information not found for package: "
+ + clazz.getPackage().getName());
+ }
+
+ byte[] bytes = Streams.suck(url.openStream());
+ Properties p = new Properties();
+ p.load(new ByteArrayInputStream(bytes));
+ return p.getProperty("version");
+ }
+
+ private static File getNewJarFile(File jarFile) {
+ String s = jarFile.getAbsolutePath();
+ int idx = s.lastIndexOf('.');
+ s = s.substring(0, idx);
+ s += MODIFIED_BUNDLE_SUFFIX;
+ return new File(s);
+ }
+
+ private static void weaveDir(File dir, String consumerHeaderKey, String
consumerHeaderValue, String bundleClassPath) throws Exception {
+ Set<WeavingData> wd =
ConsumerHeaderProcessor.processHeader(consumerHeaderKey, consumerHeaderValue);
+
+ URLClassLoader cl = new URLClassLoader(new URL []
{dir.toURI().toURL()}, Main.class.getClassLoader());
+ String dirName = dir.getAbsolutePath();
+
+ DirTree dt = new DirTree(dir);
+ for (File f : dt.getFiles()) {
+ if (!f.getName().endsWith(".class"))
+ continue;
+
+ String className = f.getAbsolutePath().substring(dirName.length());
+ if (className.startsWith(File.separator))
+ className = className.substring(1);
+ className = className.substring(0, className.length() -
".class".length());
+ className = className.replace(File.separator, ".");
+
+ InputStream is = new FileInputStream(f);
+ byte[] b;
+ try {
+ ClassReader cr = new ClassReader(is);
+ ClassWriter cw = new
StaticToolClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES,
cl);
+ TCCLSetterVisitor cv = new TCCLSetterVisitor(cw, className,
wd);
+ cr.accept(cv, ClassReader.SKIP_FRAMES);
+ if (cv.isWoven()) {
+ b = cw.toByteArray();
+ } else {
+ // if not woven, store the original bytes
+ b = Streams.suck(new FileInputStream(f));
+ }
+ } finally {
+ is.close();
+ }
+
+ OutputStream os = new FileOutputStream(f);
+ try {
+ os.write(b);
+ } finally {
+ os.close();
+ }
+ }
+
+ if (bundleClassPath != null) {
+ for (String entry : bundleClassPath.split(",")) {
+ File jarFile = new File(dir, entry.trim());
+ if (jarFile.isFile()) {
+ weaveBCPJar(jarFile, consumerHeaderKey,
consumerHeaderValue);
+ }
+ }
+ }
+ }
+
+ private static void weaveBCPJar(File jarFile, String consumerHeaderKey,
String consumerHeaderVal) throws Exception {
+ File tempDir = new File(System.getProperty("java.io.tmpdir") +
File.separator + jarFile.getName() + "_" + System.currentTimeMillis());
+ try {
+ Manifest manifest = unJar(jarFile, tempDir);
+ weaveDir(tempDir, consumerHeaderKey, consumerHeaderVal, null);
+ if (!jarFile.delete()) {
+ throw new IOException("Could not replace file: " + jarFile);
+ }
+
+ jar(jarFile, tempDir, manifest);
+ } finally {
+ delTree(tempDir);
+ }
+ }
+
+ static Manifest unJar(File jarFile, File tempDir) throws IOException {
+ ensureDirectory(tempDir);
+
+ JarInputStream jis = new JarInputStream(new FileInputStream(jarFile));
+ JarEntry je = null;
+ while((je = jis.getNextJarEntry()) != null) {
+ if (je.isDirectory()) {
+ File outDir = new File(tempDir, je.getName());
+ ensureDirectory(outDir);
+
+ continue;
+ }
+
+ File outFile = new File(tempDir, je.getName());
+ File outDir = outFile.getParentFile();
+ ensureDirectory(outDir);
+
+ OutputStream out = new FileOutputStream(outFile);
+ try {
+ Streams.pump(jis, out);
+ } finally {
+ out.flush();
+ out.close();
+ jis.closeEntry();
+ }
+ outFile.setLastModified(je.getTime());
+ }
+
+ Manifest manifest = jis.getManifest();
+ if (manifest != null) {
+ File mf = new File(tempDir, "META-INF/MANIFEST.MF");
+ File mfDir = mf.getParentFile();
+ ensureDirectory(mfDir);
+
+ OutputStream out = new FileOutputStream(mf);
+ try {
+ manifest.write(out);
+ } finally {
+ out.flush();
+ out.close();
+ }
+ }
+
+ jis.close();
+ return manifest;
+ }
+
+ static void jar(File jarFile, File rootFile, Manifest manifest) throws
IOException {
+ JarOutputStream jos = new JarOutputStream(new
FileOutputStream(jarFile), manifest);
+ try {
+ addToJarRecursively(jos, rootFile.getAbsoluteFile(),
rootFile.getAbsolutePath());
+ } finally {
+ jos.close();
+ }
+ }
+
+ static void addToJarRecursively(JarOutputStream jar, File source, String
rootDirectory) throws IOException {
+ String sourceName = source.getAbsolutePath().replace("\\", "/");
+ sourceName = sourceName.substring(rootDirectory.length());
+
+ if (sourceName.startsWith("/")) {
+ sourceName = sourceName.substring(1);
+ }
+
+ if ("META-INF/MANIFEST.MF".equals(sourceName))
+ return;
+
+ if (source.isDirectory()) {
+ /* Is there any point in adding a directory beyond just taking up
space?
+ if (!sourceName.isEmpty()) {
+ if (!sourceName.endsWith("/")) {
+ sourceName += "/";
+ }
+ JarEntry entry = new JarEntry(sourceName);
+ jar.putNextEntry(entry);
+ jar.closeEntry();
+ }
+ */
+ for (File nested : source.listFiles()) {
+ addToJarRecursively(jar, nested, rootDirectory);
+ }
+ return;
+ }
+
+ JarEntry entry = new JarEntry(sourceName);
+ jar.putNextEntry(entry);
+ InputStream is = new FileInputStream(source);
+ try {
+ Streams.pump(is, jar);
+ } finally {
+ jar.closeEntry();
+ is.close();
+ }
+ }
+
+ static void delTree(File tempDir) throws IOException {
+ for (File f : new DirTree(tempDir).getFiles()) {
+ if (!f.delete())
+ throw new IOException("Problem deleting file: " +
tempDir.getAbsolutePath());
+ }
+ }
+
+ private static void ensureDirectory(File outDir) throws IOException {
+ if (!outDir.isDirectory())
+ if (!outDir.mkdirs())
+ throw new IOException("Unable to create directory " +
outDir.getAbsolutePath());
+ }
+}
+