Java/File Input Output/Jar File
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 A class to find resources in the classpath by their mime-type specified in the MANIFEST.
- 2 Add a jar entry to the deployment archive
- 3 Add jar contents to the deployment archive under the given prefix
- 4 class for exploding jar/zip files onto the file system
- 5 Create a Jar archive containing the src file/directory
- 6 Create a URL that refers to a jar file in the file system
- 7 Create a URL that refers to an entry in the jar file
- 8 Create Jar file
- 9 Creating a JAR File
- 10 Determine whether a file is a JAR File.
- 11 Get resource from Jar file
- 12 Get the entry name; it should be the same as specified on URL
- 13 Get the jar entry
- 14 Get the jar file
- 15 Get the jar file from a URL
- 16 Getting a Jar File Using a URL
- 17 Helper Class to manipulate Java Archive File
- 18 InstallJars - a utility to download and install files, Jars and Zips.
- 19 JAR Archives: Jar Lister
- 20 JAR Archives: Packer200
- 21 JAR Archives: Unpacker200
- 22 Jar builder
- 23 Jar Entry OutputStream
- 24 Jar file helper to deployment
- 25 Jarring and unjarring files and directories.
- 26 List files in a jar file
- 27 Listing the Entries of a JAR File Manifest
- 28 Listing the Main Attributes in a JAR File Manifest
- 29 Load an Icon from a jar
- 30 Load an Image from a JAR file
- 31 Load resource from Jar file
- 32 Make Temp Jar
- 33 Manifest Writer
- 34 Reading a text file from a jar file without unzipping
- 35 Retreive Binary File From Jar
- 36 Retreive Text File From Jar
- 37 Retrieves the manifest from a JAR file and writes the manifest contents to a file.
- 38 Search all jar and zip files in the current directory for a given class file
- 39 Search class in class path and Jar files
- 40 Sign jar with the certificate named alias in the keystore
- 41 Some utility classes for manipulating JAR files
- 42 Unjar a file
- 43 When no entry is specified on the URL, the entry name is null
- 44 Zip jar Imploder
A class to find resources in the classpath by their mime-type specified in the MANIFEST.
/*
* 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.
*/
/* $Id$ */
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
/**
* A class to find resources in the classpath by their mime-type specified in
* the MANIFEST.
* <p>
* This class searches for content entries in all META-INF/MANIFEST.MF files. It
* will find files with a given Content-Type: attribute. This allows to add
* arbitrary resources by content-type just by creating a JAR wrapper and adding
* them to the classpath.
* <p>
* Example:<br>
*
* <pre>
* Name: test.txt
* Content-Type: text/plain
* </pre>
*/
public final class ClasspathResource {
/**
* Actual Type: Map<String,List<URL>>.
*/
private final Map contentMappings;
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
private static final String CONTENT_TYPE_KEY = "Content-Type";
private static ClasspathResource classpathResource;
private ClasspathResource() {
contentMappings = new HashMap();
loadManifests();
}
/**
* Retrieve the singleton instance of this class.
*
* @return the ClassPathResource instance.
*/
public static synchronized ClasspathResource getInstance() {
if (classpathResource == null) {
classpathResource = new ClasspathResource();
}
return classpathResource;
}
/* Actual return type: Set<ClassLoader> */
private Set getClassLoadersForResources() {
Set v = new HashSet();
try {
ClassLoader l = ClassLoader.getSystemClassLoader();
if (l != null) {
v.add(l);
}
} catch (SecurityException e) {
// Ignore
}
try {
ClassLoader l = Thread.currentThread().getContextClassLoader();
if (l != null) {
v.add(l);
}
} catch (SecurityException e) {
// Ignore
}
try {
ClassLoader l = ClasspathResource.class.getClassLoader();
if (l != null) {
v.add(l);
}
} catch (SecurityException e) {
// Ignore
}
return v;
}
private void loadManifests() {
Enumeration e;
try {
Iterator it = getClassLoadersForResources().iterator();
while (it.hasNext()) {
ClassLoader classLoader = (ClassLoader) it.next();
e = classLoader.getResources(MANIFEST_PATH);
while (e.hasMoreElements()) {
final URL u = (URL) e.nextElement();
try {
final Manifest manifest = new Manifest(u.openStream());
final Map entries = manifest.getEntries();
final Iterator entrysetiterator = entries.entrySet()
.iterator();
while (entrysetiterator.hasNext()) {
final Map.Entry entry = (Map.Entry) entrysetiterator
.next();
final String name = (String) entry.getKey();
final Attributes attributes = (Attributes) entry
.getValue();
final String contentType = attributes
.getValue(CONTENT_TYPE_KEY);
if (contentType != null) {
addToMapping(contentType, name, classLoader);
}
}
} catch (IOException io) {
// TODO: Log.
}
}
}
} catch (IOException io) {
// TODO: Log.
}
}
private void addToMapping(final String contentType, final String name,
final ClassLoader classLoader) {
List existingFiles = (List) contentMappings.get(contentType);
if (existingFiles == null) {
existingFiles = new Vector();
contentMappings.put(contentType, existingFiles);
}
final URL url = classLoader.getResource(name);
if (url != null) {
existingFiles.add(url);
}
}
/**
* Retrieve a list of resources known to have the given mime-type.
*
* @param mimeType
* the mime-type to search for.
* @return a List<URL>, guaranteed to be != null.
*/
public List listResourcesOfMimeType(final String mimeType) {
final List content = (List) contentMappings.get(mimeType);
if (content == null) {
return Collections.EMPTY_LIST;
} else {
return content;
}
}
}
////////////////
/*
* 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.
*/
/* $Id: $ */
package org.apache.xmlgraphics.util;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
/**
* Test for the Service class.
*/
public class ClasspathResourceTest extends TestCase {
/**
* Tests whether the file /sample.txt with mime-type text/plain exists.
*
* @throws Exception
* in case of an error
*/
public void testSampleResource() throws Exception {
final List list = ClasspathResource.getInstance()
.listResourcesOfMimeType("text/plain");
boolean found = false;
final Iterator i = list.iterator();
while (i.hasNext()) {
final URL u = (URL) i.next();
if (u.getPath().endsWith("sample.txt")) {
found = true;
}
}
assertTrue(found);
}
/**
* Tests the mode where Service returns class names.
*
* @throws Exception
* in case of an error
*/
public void testNonexistingResource() throws Exception {
final List list = ClasspathResource.getInstance()
.listResourcesOfMimeType("nota/mime-type");
assertTrue(list.isEmpty());
}
}
Add a jar entry to the deployment archive
/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
/**
* A collection of jar utilities
*
* @author thomas.diesler@jboss.org
* @version $Revision: 81011 $
*/
public class JarUtils {
/**
* Add jar contents to the deployment archive under the given prefix
*/
public static String[] addJar(JarOutputStream outputStream, String prefix, File jar)
throws IOException {
ArrayList tmp = new ArrayList();
FileInputStream fis = new FileInputStream(jar);
JarInputStream jis = new JarInputStream(fis);
JarEntry entry = jis.getNextJarEntry();
while (entry != null) {
if (entry.isDirectory() == false) {
String entryName = prefix + entry.getName();
tmp.add(entryName);
addJarEntry(outputStream, entryName, jis);
}
entry = jis.getNextJarEntry();
}
jis.close();
String[] names = new String[tmp.size()];
tmp.toArray(names);
return names;
}
/**
* Add a jar entry to the deployment archive
*/
public static void addJarEntry(JarOutputStream outputStream, String entryName,
InputStream inputStream) throws IOException {
outputStream.putNextEntry(new JarEntry(entryName));
copyStream(outputStream, inputStream);
}
/**
* Copies the input stream to the output stream
*/
public static void copyStream(OutputStream outputStream, InputStream inputStream)
throws IOException {
byte[] bytes = new byte[4096];
int read = inputStream.read(bytes, 0, 4096);
while (read > 0) {
outputStream.write(bytes, 0, read);
read = inputStream.read(bytes, 0, 4096);
}
}
}
Add jar contents to the deployment archive under the given prefix
/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
/**
* A collection of jar utilities
*
* @author thomas.diesler@jboss.org
* @version $Revision: 81011 $
*/
public class JarUtils {
/**
* Add jar contents to the deployment archive under the given prefix
*/
public static String[] addJar(JarOutputStream outputStream, String prefix, File jar)
throws IOException {
ArrayList tmp = new ArrayList();
FileInputStream fis = new FileInputStream(jar);
JarInputStream jis = new JarInputStream(fis);
JarEntry entry = jis.getNextJarEntry();
while (entry != null) {
if (entry.isDirectory() == false) {
String entryName = prefix + entry.getName();
tmp.add(entryName);
addJarEntry(outputStream, entryName, jis);
}
entry = jis.getNextJarEntry();
}
jis.close();
String[] names = new String[tmp.size()];
tmp.toArray(names);
return names;
}
/**
* Add a jar entry to the deployment archive
*/
public static void addJarEntry(JarOutputStream outputStream, String entryName,
InputStream inputStream) throws IOException {
outputStream.putNextEntry(new JarEntry(entryName));
copyStream(outputStream, inputStream);
}
/**
* Copies the input stream to the output stream
*/
public static void copyStream(OutputStream outputStream, InputStream inputStream)
throws IOException {
byte[] bytes = new byte[4096];
int read = inputStream.read(bytes, 0, 4096);
while (read > 0) {
outputStream.write(bytes, 0, read);
read = inputStream.read(bytes, 0, 4096);
}
}
}
class for exploding jar/zip files onto the file system
/*******************************************************************************
* Copyright (c) 2004, 2008 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
*******************************************************************************/
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* class for exploding jar/zip files onto the file system
*
* @author Barry Feigenbaum
*/
public class ZipExploder {
/**
* create a zip exploder for unpacking .jar/.zip files
*/
public ZipExploder() {
this(false);
}
/**
* create a zip exploder for unpacking .jar/.zip files onto the file system
*
* @param verbose -
* set to <code>true</code> for verbose mode
*/
public ZipExploder(boolean verbose) {
setVerbose(verbose);
}
/**
* create a zip exploder for unpacking .jar/.zip files onto the file system
*
* @param verbose -
* set to <code>true</code> for verbose mode
* @param sorted -
* set to <code>true</code> for sorted file mode
*/
public ZipExploder(boolean verbose, boolean sorted) {
this(verbose);
setSortNames(sorted);
}
protected boolean verbose;
/**
* Get the verbose mode state.
*
* @return verbosity
*/
public boolean getVerbose() {
return verbose;
}
/**
* set the verbose mode state
*
* @param f -
* verbosity
*/
public void setVerbose(boolean f) {
verbose = f;
}
protected boolean sortNames;
/**
* @return Returns the sortNames.
*/
public boolean getSortNames() {
return sortNames;
}
/**
* @param sortNames
* The sortNames to set.
*/
public void setSortNames(boolean sortNames) {
this.sortNames = sortNames;
}
/**
* Explode source JAR and/or ZIP files into a target directory
*
* @param zipNames
* names of source files
* @param jarNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void process(String[] zipNames, String[] jarNames, String destDir) throws IOException {
processZips(zipNames, destDir);
processJars(jarNames, destDir);
}
/**
* Explode source JAR files into a target directory
*
* @param jarNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processJars(String[] jarNames, String destDir) throws IOException {
for (int i = 0; i < jarNames.length; i++) {
processFile(jarNames[i], destDir);
}
}
/**
* Explode source ZIP files into a target directory
*
* @param zipNames
* names of source files
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processZips(String[] zipNames, String destDir) throws IOException {
for (int i = 0; i < zipNames.length; i++) {
processFile(zipNames[i], destDir);
}
}
/**
* Explode source ZIP or JAR file into a target directory
*
* @param zipName
* names of source file
* @param destDir
* target directory name (should already exist)
* @exception IOException
* error creating a target file
*/
public void processFile(String zipName, String destDir) throws IOException {
String source = new File(zipName).getCanonicalPath();
String dest = new File(destDir).getCanonicalPath();
ZipFile f = null;
try {
f = new ZipFile(source);
Map fEntries = getEntries(f);
String[] names = (String[]) fEntries.keySet().toArray(new String[] {});
if (sortNames) {
Arrays.sort(names);
}
// copy all files
for (int i = 0; i < names.length; i++) {
String name = names[i];
ZipEntry e = (ZipEntry) fEntries.get(name);
copyFileEntry(dest, f, e);
}
} catch (IOException ioe) {
String msg = ioe.getMessage();
if (msg.indexOf(zipName) < 0) {
msg += " - " + zipName;
}
throw new IOException(msg);
} finally {
if (f != null) {
try {
f.close();
} catch (IOException ioe) {
}
}
}
}
/** Get all the entries in a ZIP file. */
protected Map getEntries(ZipFile zf) {
Enumeration e = zf.entries();
Map m = new HashMap();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
m.put(ze.getName(), ze);
}
return m;
}
/**
* copy a single entry from the archive
*
* @param destDir
* @param zf
* @param ze
* @throws IOException
*/
public void copyFileEntry(String destDir, ZipFile zf, ZipEntry ze) throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(zf.getInputStream(ze)));
try {
copyFileEntry(destDir, ze.isDirectory(), ze.getName(), dis);
} finally {
try {
dis.close();
} catch (IOException ioe) {
}
}
}
protected void copyFileEntry(String destDir, boolean destIsDir, String destFile,
DataInputStream dis) throws IOException {
byte[] bytes = readAllBytes(dis);
File file = new File(destFile);
String parent = file.getParent();
if (parent != null && parent.length() > 0) {
File dir = new File(destDir, parent);
if (dir != null) {
dir.mkdirs();
}
}
File outFile = new File(destDir, destFile);
if (destIsDir) {
outFile.mkdir();
} else {
FileOutputStream fos = new FileOutputStream(outFile);
try {
fos.write(bytes, 0, bytes.length);
} finally {
try {
fos.close();
} catch (IOException ioe) {
}
}
}
}
// *** below may be slow for large files ***
/** Read all the bytes in a ZIPed file */
protected byte[] readAllBytes(DataInputStream is) throws IOException {
byte[] bytes = new byte[0];
for (int len = is.available(); len > 0; len = is.available()) {
byte[] xbytes = new byte[len];
int count = is.read(xbytes);
if (count > 0) {
byte[] nbytes = new byte[bytes.length + count];
System.arraycopy(bytes, 0, nbytes, 0, bytes.length);
System.arraycopy(xbytes, 0, nbytes, bytes.length, count);
bytes = nbytes;
} else if (count < 0) {
// accommodate apparent bug in IBM JVM where
// available() always returns positive value on some files
break;
}
}
return bytes;
}
protected void print(String s) {
System.out.print(s);
}
/** Print command help text. */
protected static void printHelp() {
System.out.println();
System.out.println("Usage: java " + ZipExploder.class.getName()
+ " (-jar jarFilename... | -zip zipFilename...)... -dir destDir {-verbose}");
System.out.println("Where:");
System.out.println(" jarFilename path to source jar, may repeat");
System.out.println(" zipFilename path to source zip, may repeat");
System.out.println(" destDir path to target directory; should exist");
System.out.println("Note: one -jar or -zip is required; switch case or order is not important");
}
protected static void reportError(String msg) {
System.err.println(msg);
// printHelp();
System.exit(1);
}
/**
* Main command line entry point.
*
* @param args
*/
public static void main(final String[] args) {
if (args.length == 0) {
printHelp();
System.exit(0);
}
List zipNames = new ArrayList();
List jarNames = new ArrayList();
String destDir = null;
boolean jarActive = false, zipActive = false, destDirActive = false;
boolean verbose = false;
// process arguments
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == "-") { // switch
arg = arg.substring(1);
if (arg.equalsIgnoreCase("jar")) {
jarActive = true;
zipActive = false;
destDirActive = false;
} else if (arg.equalsIgnoreCase("zip")) {
zipActive = true;
jarActive = false;
destDirActive = false;
} else if (arg.equalsIgnoreCase("dir")) {
jarActive = false;
zipActive = false;
destDirActive = true;
} else if (arg.equalsIgnoreCase("verbose")) {
verbose = true;
} else {
reportError("Invalid switch - " + arg);
}
} else {
if (jarActive) {
jarNames.add(arg);
} else if (zipActive) {
zipNames.add(arg);
} else if (destDirActive) {
if (destDir != null) {
reportError("duplicate argument - " + "-destDir");
}
destDir = arg;
} else {
reportError("Too many parameters - " + arg);
}
}
}
if (destDir == null || (zipNames.size() + jarNames.size()) == 0) {
reportError("Missing parameters");
}
if (verbose) {
System.out.println("Effective command: " + ZipExploder.class.getName() + " "
+ (jarNames.size() > 0 ? "-jars " + jarNames + " " : "")
+ (zipNames.size() > 0 ? "-zips " + zipNames + " " : "") + "-dir " + destDir);
}
try {
ZipExploder ze = new ZipExploder(verbose);
ze.process((String[]) zipNames.toArray(new String[zipNames.size()]), (String[]) jarNames
.toArray(new String[jarNames.size()]), destDir);
} catch (IOException ioe) {
System.err.println("Exception - " + ioe.getMessage());
ioe.printStackTrace(); // *** debug ***
System.exit(2);
}
}
}
Create a Jar archive containing the src file/directory
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
/** A utility class for dealing with Jar files.
@author Scott.Stark@jboss.org
@version $Revision: 2787 $
*/
public final class JarUtils
{
/**
* Hide the constructor
*/
private JarUtils()
{
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream.</P>
*
* <P>This is a shortcut for<br>
* <code>jar(out, new File[] { src }, null, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @throws IOException
*/
public static void jar(OutputStream out, File src) throws IOException
{
jar(out, new File[] { src }, null, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream.</P>
*
* <P>This is a shortcut for<br>
* <code>jar(out, src, null, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src) throws IOException
{
jar(out, src, null, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream. Directories are processed recursively, applying the
* specified filter if it exists.
*
* <P>This is a shortcut for<br>
* <code>jar(out, src, filter, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @param filter The filter to use while processing directories. Only
* those files matching will be included in the jar archive. If
* null, then all files are included.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src, FileFilter filter)
throws IOException
{
jar(out, src, filter, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream. Directories are processed recursively, applying the
* specified filter if it exists.
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @param filter The filter to use while processing directories. Only
* those files matching will be included in the jar archive. If
* null, then all files are included.
* @param prefix The name of an arbitrary directory that will precede all
* entries in the jar archive. If null, then no prefix will be
* used.
* @param man The manifest to use for the Jar archive. If null, then no
* manifest will be included.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src, FileFilter filter,
String prefix, Manifest man) throws IOException
{
for (int i = 0; i < src.length; i++)
{
if (!src[i].exists())
{
throw new FileNotFoundException(src.toString());
}
}
JarOutputStream jout;
if (man == null)
{
jout = new JarOutputStream(out);
}
else
{
jout = new JarOutputStream(out, man);
}
if (prefix != null && prefix.length() > 0 && !prefix.equals("/"))
{
// strip leading "/"
if (prefix.charAt(0) == "/")
{
prefix = prefix.substring(1);
}
// ensure trailing "/"
if (prefix.charAt(prefix.length() - 1) != "/")
{
prefix = prefix + "/";
}
}
else
{
prefix = "";
}
JarInfo info = new JarInfo(jout, filter);
for (int i = 0; i < src.length; i++)
{
jar(src[i], prefix, info);
}
jout.close();
}
/**
* This simple convenience class is used by the jar method to reduce the
* number of arguments needed. It holds all non-changing attributes
* needed for the recursive jar method.
*/
private static class JarInfo
{
public JarOutputStream out;
public FileFilter filter;
public byte[] buffer;
public JarInfo(JarOutputStream out, FileFilter filter)
{
this.out = out;
this.filter = filter;
buffer = new byte[1024];
}
}
/**
* This recursive method writes all matching files and directories to
* the jar output stream.
*/
private static void jar(File src, String prefix, JarInfo info)
throws IOException
{
JarOutputStream jout = info.out;
if (src.isDirectory())
{
// create / init the zip entry
prefix = prefix + src.getName() + "/";
ZipEntry entry = new ZipEntry(prefix);
entry.setTime(src.lastModified());
entry.setMethod(JarOutputStream.STORED);
entry.setSize(0L);
entry.setCrc(0L);
jout.putNextEntry(entry);
jout.closeEntry();
// process the sub-directories
File[] files = src.listFiles(info.filter);
for (int i = 0; i < files.length; i++)
{
jar(files[i], prefix, info);
}
}
else if (src.isFile())
{
// get the required info objects
byte[] buffer = info.buffer;
// create / init the zip entry
ZipEntry entry = new ZipEntry(prefix + src.getName());
entry.setTime(src.lastModified());
jout.putNextEntry(entry);
// dump the file
FileInputStream in = new FileInputStream(src);
int len;
while ((len = in.read(buffer, 0, buffer.length)) != -1)
{
jout.write(buffer, 0, len);
}
in.close();
jout.closeEntry();
}
}
public static void unjar(InputStream in, File dest) throws IOException
{
if (!dest.exists())
{
dest.mkdirs();
}
if (!dest.isDirectory())
{
throw new IOException("Destination must be a directory.");
}
JarInputStream jin = new JarInputStream(in);
byte[] buffer = new byte[1024];
ZipEntry entry = jin.getNextEntry();
while (entry != null)
{
String fileName = entry.getName();
if (fileName.charAt(fileName.length() - 1) == "/")
{
fileName = fileName.substring(0, fileName.length() - 1);
}
if (fileName.charAt(0) == "/")
{
fileName = fileName.substring(1);
}
if (File.separatorChar != "/")
{
fileName = fileName.replace("/", File.separatorChar);
}
File file = new File(dest, fileName);
if (entry.isDirectory())
{
// make sure the directory exists
file.mkdirs();
jin.closeEntry();
}
else
{
// make sure the directory exists
File parent = file.getParentFile();
if (parent != null && !parent.exists())
{
parent.mkdirs();
}
// dump the file
OutputStream out = new FileOutputStream(file);
int len = 0;
while ((len = jin.read(buffer, 0, buffer.length)) != -1)
{
out.write(buffer, 0, len);
}
out.flush();
out.close();
jin.closeEntry();
file.setLastModified(entry.getTime());
}
entry = jin.getNextEntry();
}
/* Explicity write out the META-INF/MANIFEST.MF so that any headers such
as the Class-Path are see for the unpackaged jar
*/
Manifest mf = jin.getManifest();
if (mf != null)
{
File file = new File(dest, "META-INF/MANIFEST.MF");
File parent = file.getParentFile();
if( parent.exists() == false )
{
parent.mkdirs();
}
OutputStream out = new FileOutputStream(file);
mf.write(out);
out.flush();
out.close();
}
jin.close();
}
/** Given a URL check if its a jar url(jar:<url>!/archive) and if it is,
extract the archive entry into the given dest directory and return a file
URL to its location. If jarURL is not a jar url then it is simply returned
as the URL for the jar.
@param jarURL the URL to validate and extract the referenced entry if its
a jar protocol URL
@param dest the directory into which the nested jar will be extracted.
@return the file: URL for the jar referenced by the jarURL parameter.
* @throws IOException
*/
public static URL extractNestedJar(URL jarURL, File dest)
throws IOException
{
// This may not be a jar URL so validate the protocol
if( jarURL.getProtocol().equals("jar") == false )
return jarURL;
String destPath = dest.getAbsolutePath();
URLConnection urlConn = jarURL.openConnection();
JarURLConnection jarConn = (JarURLConnection) urlConn;
// Extract the archive to dest/jarName-contents/archive
String parentArchiveName = jarConn.getJarFile().getName();
// Find the longest common prefix between destPath and parentArchiveName
int length = Math.min(destPath.length(), parentArchiveName.length());
int n = 0;
while( n < length )
{
char a = destPath.charAt(n);
char b = parentArchiveName.charAt(n);
if( a != b )
break;
n ++;
}
// Remove any common prefix from parentArchiveName
parentArchiveName = parentArchiveName.substring(n);
File archiveDir = new File(dest, parentArchiveName+"-contents");
if( archiveDir.exists() == false && archiveDir.mkdirs() == false )
throw new IOException("Failed to create contents directory for archive, path="+archiveDir.getAbsolutePath());
String archiveName = jarConn.getEntryName();
File archiveFile = new File(archiveDir, archiveName);
File archiveParentDir = archiveFile.getParentFile();
if( archiveParentDir.exists() == false && archiveParentDir.mkdirs() == false )
throw new IOException("Failed to create parent directory for archive, path="+archiveParentDir.getAbsolutePath());
InputStream archiveIS = jarConn.getInputStream();
FileOutputStream fos = new FileOutputStream(archiveFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[4096];
int read;
while( (read = archiveIS.read(buffer)) > 0 )
{
bos.write(buffer, 0, read);
}
archiveIS.close();
bos.close();
// Return the file url to the extracted jar
return archiveFile.toURL();
}
public static void main(String[] args) throws Exception
{
if (args.length == 0)
{
System.out.println("usage: <x or c> <jar-archive> <files...>");
System.exit(0);
}
if (args[0].equals("x"))
{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(args[1]));
File dest = new File(args[2]);
unjar(in, dest);
}
else if (args[0].equals("c"))
{
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(args[1]));
File[] src = new File[args.length - 2];
for (int i = 0; i < src.length; i++)
{
src[i] = new File(args[2 + i]);
}
jar(out, src);
}
else
{
System.out.println("Need x or c as first argument");
}
}
}
Create a URL that refers to a jar file in the file system
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
}
}
Create a URL that refers to an entry in the jar file
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/com/mycompany/MyClass.class");
}
}
Create Jar file
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
public class CreateJarFile {
public static int BUFFER_SIZE = 10240;
protected void createJarArchive(File archiveFile, File[] tobeJared) {
try {
byte buffer[] = new byte[BUFFER_SIZE];
// Open archive file
FileOutputStream stream = new FileOutputStream(archiveFile);
JarOutputStream out = new JarOutputStream(stream, new Manifest());
for (int i = 0; i < tobeJared.length; i++) {
if (tobeJared[i] == null || !tobeJared[i].exists()
|| tobeJared[i].isDirectory())
continue; // Just in case...
System.out.println("Adding " + tobeJared[i].getName());
// Add archive entry
JarEntry jarAdd = new JarEntry(tobeJared[i].getName());
jarAdd.setTime(tobeJared[i].lastModified());
out.putNextEntry(jarAdd);
// Write file to archive
FileInputStream in = new FileInputStream(tobeJared[i]);
while (true) {
int nRead = in.read(buffer, 0, buffer.length);
if (nRead <= 0)
break;
out.write(buffer, 0, nRead);
}
in.close();
}
out.close();
stream.close();
System.out.println("Adding completed OK");
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Error: " + ex.getMessage());
}
}
}
Creating a JAR File
// Create the jar file
jar cf myjar.jar MyClass.class
Determine whether a file is a JAR File.
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipFile;
public class Main {
/**
* Determine whether a file is a JAR File.
*/
public static boolean isJarFile(File file) throws IOException {
if (!isZipFile(file)) {
return false;
}
ZipFile zip = new ZipFile(file);
boolean manifest = zip.getEntry("META-INF/MANIFEST.MF") != null;
zip.close();
return manifest;
}
/**
* Determine whether a file is a ZIP File.
*/
public static boolean isZipFile(File file) throws IOException {
if(file.isDirectory()) {
return false;
}
if(!file.canRead()) {
throw new IOException("Cannot read file "+file.getAbsolutePath());
}
if(file.length() < 4) {
return false;
}
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
int test = in.readInt();
in.close();
return test == 0x504b0304;
}
}
Get resource from Jar file
/**
* 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.
*/
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public final class JarResource {
public List<String> getJarContents(URL jarLocation) throws IOException {
return getJarContents(jarLocation.openStream());
}
public List<String> getJarContents(InputStream is) throws IOException {
return load(is);
}
public List<String> getJarContents(String jarLocation) throws IOException {
return getJarContents(new File(jarLocation));
}
public List<String> getJarContents(File jarFile) throws IOException {
return load(jarFile);
}
private List<String> load(File jarFile) throws IOException {
List<String> jarContents = new ArrayList<String>();
try {
ZipFile zf = new ZipFile(jarFile);
for (Enumeration e = zf.entries(); e.hasMoreElements();) {
ZipEntry ze = (ZipEntry) e.nextElement();
if (ze.isDirectory()) {
continue;
}
jarContents.add(ze.getName());
}
} catch (NullPointerException e) {
System.out.println("done.");
} catch (ZipException ze) {
ze.printStackTrace();
}
return jarContents;
}
private List<String> load(InputStream is) throws IOException {
List<String> jarContents = new ArrayList<String>();
try {
ZipInputStream zis = new ZipInputStream(is);
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
if (ze.isDirectory()) {
continue;
}
jarContents.add(ze.getName());
ze = zis.getNextEntry();
}
} catch (NullPointerException e) {
System.out.println("done.");
}
return jarContents;
}
}
Get the entry name; it should be the same as specified on URL
import java.net.JarURLConnection;
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
String entryName = conn.getEntryName();
}
}
Get the jar entry
import java.net.JarURLConnection;
import java.net.URL;
import java.util.jar.JarEntry;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
JarEntry jarEntry = conn.getJarEntry();
}
}
Get the jar file
import java.net.JarURLConnection;
import java.net.URL;
import java.util.jar.JarFile;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
conn = (JarURLConnection) url.openConnection();
JarFile jarfile = conn.getJarFile();
}
}
Get the jar file from a URL
import java.net.JarURLConnection;
import java.net.URL;
import java.util.jar.JarFile;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
JarFile jarfile = conn.getJarFile();
}
}
Getting a Jar File Using a URL
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
// Create a URL that refers to a jar file on the net
URL url = new URL("jar:http://hostname/my.jar!/");
}
}
Helper Class to manipulate Java Archive File
/* -------------------------------------------------------------------------*
* PKUAS: Peking University Application Server
* Copyright (C) 2006 Peking University
*
* This software is free; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* either version 2.1 or any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
* ------------------------------------------------------------------------*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* This is the Helper Class to manipulate Java Archive File
* @author Lin Liang
*/
public class JarMaker {
public JarMaker() {
}
public static boolean pack(String jarPath, String jarFileName) {
try {
String t_jarPathName = jarPath.replace("\\", File.separatorChar);
String t_jarFileName = jarFileName.replace("\\", File.separatorChar);
RealPackUtilityJar(t_jarPathName, t_jarFileName);
return true;
} catch (Exception ex) {
return false;
}
}
public static boolean utilityPack(String p_utilityFileName, String jarName) {
try {
// begin to pack the utility jar file.
String t_utilityfilename = p_utilityFileName.replace("\\", File.separatorChar);
String t_jarfilename = jarName.replace("\\", File.separatorChar) + ".jar";
// File utilityFile = new File(p_utilityFileName);
RealPackUtilityJar(t_utilityfilename, t_jarfilename);
// delete the utility directory!
} catch (Exception ex) {
return false;
}
return true;
}
public static void RealPackUtilityJar(String s_src, String s_dest) throws IOException {
URL _src, _dest;
File f_src = new File(s_src);
if (!f_src.isDirectory())
throw new IOException(s_src + " is not a directory");
_src = f_src.toURL();
_dest = new File(s_dest).toURL();
int path_l = s_dest.lastIndexOf("/");
if (path_l > 0) {
File dir = new File(s_dest.substring(0, path_l));
if (!dir.exists())
dir.mkdirs();
}
JarOutputStream jout = new JarOutputStream(new FileOutputStream(_dest.getFile()));
// put all into the jar...
add(jout, new File(_src.getFile()), "");
jout.close();
}
/**
* used by downloadAndPack
* @param _jout
* @param _dir
* @param _prefix
* @throws IOException
*/
public static void add(JarOutputStream _jout, File _dir, String _prefix) throws IOException {
File[] content = _dir.listFiles();
if (_dir.isDirectory()) {
for (int i = 0, l = content.length; i < l; ++i) {
if (content[i].isDirectory()) {
_jout.putNextEntry(new ZipEntry(_prefix + (_prefix.equals("") ? "" : "/") + content[i].getName() + "/"));
add(_jout, content[i], _prefix + (_prefix.equals("") ? "" : "/") + content[i].getName());
} else {
_jout.putNextEntry(new ZipEntry(_prefix + (_prefix.equals("") ? "" : "/") + content[i].getName()));
FileInputStream in = new FileInputStream(content[i]);
write(in, _jout);
in.close();
}
}
} else {
_jout.putNextEntry(new ZipEntry(_prefix + (_prefix.equals("") ? "" : "/") + _dir.getName()));
FileInputStream in = new FileInputStream(_dir);
write(in, _jout);
in.close();
}
}
/**
* writes the content of the InputStream into the OutputStream
* @param _in
* @param _out
* @throws IOException
*/
private static synchronized void write(InputStream _in, OutputStream _out) throws IOException {
byte[] buffer = new byte[1024 * 512];
int read;
while (true) {
read = _in.read(buffer);
if (read == -1)
break;
_out.write(buffer, 0, read);
}
_out.flush();
}
/**
* Deletes all files and subdirectories under dir.
* @param dir
* @return true if all deletions were successful.If a deletion fails, the
* method stops attempting to delete and returns false.
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
/**
* @param f_name : source zip file
* @param dir_name : target dir file
*/
public static void unpackJar(File f_name, File dir_name) throws IOException {
unpackJar(f_name.getCanonicalPath(), dir_name.getCanonicalPath());
}
/**
* @param f_name : source zip file path name
* @param dir_name : target dir file path
*/
public static void unpackJar(String f_name, String dir_name) throws IOException {
BufferedInputStream bism = new BufferedInputStream(new FileInputStream(f_name));
ZipInputStream zism = new ZipInputStream(bism);
for (ZipEntry z = zism.getNextEntry(); z != null; z = zism.getNextEntry()) {
File f = new File(dir_name, z.getName());
if (z.isDirectory()) {
f.mkdirs();
} else {
f.getParentFile().mkdirs();
BufferedOutputStream bosm = new BufferedOutputStream(new FileOutputStream(f));
int i;
byte[] buffer = new byte[1024 * 512];
try {
while ((i = zism.read(buffer, 0, buffer.length)) != -1)
bosm.write(buffer, 0, i);
} catch (IOException ie) {
throw ie;
}
bosm.close();
}
}
zism.close();
bism.close();
}
/**
* Unpack the jar file to a directory, till teaf files
* @param file
* @param file1
* @throws IOException
*/
public static void unpackAppJar(File file, File file1) throws IOException {
unpackAppJar(file.getCanonicalPath(), file1.getCanonicalPath());
}
/**
* Unpack the jar file to a directory, till teaf files
* @param file The source file name
* @param file1 The target directory
* @author wangxp
* @version 2003/11/07
*/
public static void unpackAppJar(String file, String file1) throws IOException {
// m_log.debug("unpackAppJar begin. file="+file+"|||file1="+file1);
BufferedInputStream bufferedinputstream = new BufferedInputStream(new FileInputStream(file));
ZipInputStream zipinputstream = new ZipInputStream(bufferedinputstream);
byte abyte0[] = new byte[1024];
for (ZipEntry zipentry = zipinputstream.getNextEntry(); zipentry != null; zipentry = zipinputstream.getNextEntry()) {
File file2 = new File(file1, zipentry.getName());
if (zipentry.isDirectory()) {
if (!file2.exists() && !file2.mkdirs())
throw new IOException("Could not make directory " + file2.getPath());
} else {
File file3 = file2.getParentFile();
if (file3 != null && !file3.exists() && !file3.mkdirs())
throw new IOException("Could not make directory " + file3.getPath());
BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(new FileOutputStream(file2));
int i;
try {
while ((i = zipinputstream.read(abyte0, 0, abyte0.length)) != -1)
bufferedoutputstream.write(abyte0, 0, i);
} catch (IOException ie) {
ie.printStackTrace();
// m_logger.error(ie);
throw ie;
}
bufferedoutputstream.close();
}
}
zipinputstream.close();
bufferedinputstream.close();
// m_log.debug("unpackAppJar end.");
}
/**
* Combine several jar files and some given files into one jar file.
* @param outJar The output jar file"s filename.
* @param inJarsList The jar files to be combined
* @param filter A filter that exclude some entries of input jars. User
* should implement the EntryFilter interface.
* @param inFileList The files to be added into the jar file.
* @param prefixs The prefixs of files to be added into the jar file.
* inFileList and prefixs should be paired.
* @throws FileNotFoundException
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static void combineJars(String outJar, String[] inJarsList, EntryFilter filter, String[] inFileList, String[] prefixs)
throws FileNotFoundException, IOException {
JarOutputStream jout = new JarOutputStream(new FileOutputStream(outJar));
ArrayList entryList = new ArrayList();
for (int i = 0; i < inJarsList.length; i++) {
BufferedInputStream bufferedinputstream = new BufferedInputStream(new FileInputStream(inJarsList[i]));
ZipInputStream zipinputstream = new ZipInputStream(bufferedinputstream);
byte abyte0[] = new byte[1024 * 4];
for (ZipEntry zipentry = zipinputstream.getNextEntry(); zipentry != null; zipentry = zipinputstream.getNextEntry()) {
if (filter.accept(zipentry)) {
if (!entryList.contains(zipentry.getName())) {
jout.putNextEntry(zipentry);
if (!zipentry.isDirectory()) {
int j;
try {
while ((j = zipinputstream.read(abyte0, 0, abyte0.length)) != -1)
jout.write(abyte0, 0, j);
} catch (IOException ie) {
throw ie;
}
}
entryList.add(zipentry.getName());
}
}
}
zipinputstream.close();
bufferedinputstream.close();
}
for (int i = 0; i < inFileList.length; i++) {
add(jout, new File(inFileList[i]), prefixs[i]);
}
jout.close();
}
/**
* Test
* @param args
* @throws Exception
*/
public static void main(String args[]) throws Exception {
String[] in = new String[2];
in[1] = "E:\\pkuas03\\pkuas_51\\repository\\deployed\\ecperf.ear\\corp.jar";
in[0] = "E:\\pkuas03\\pkuas_51\\repository\\deployed\\ecperf.ear\\orders.jar";
String[] fs = new String[1];
fs[0] = "E:\\pkuas03\\pkuas_51\\repository\\deployed\\ecperf.ear\\META-INF\\application.xml";
String[] pres = new String[1];
pres[0] = "META-INF";
combineJars("e:\\111.jar", in, new EntryFilter() {
public boolean accept(ZipEntry entry) {
if (entry.getName().endsWith("ejb-jar.xml"))
return false;
return true;
}
}, fs, pres);
}
interface EntryFilter {
public boolean accept(ZipEntry entry);
}
}
InstallJars - a utility to download and install files, Jars and Zips.
/*******************************************************************************
* Copyright (c) 2004, 2008 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
*******************************************************************************/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/*******************************************************************************
* * InstallJars - a utility to download and install files, Jars and Zips. * *
*
* @author Barry Feigenbaum, Ph.D. *
******************************************************************************/
public class InstallJars {
public static final int BLOCK_SIZE = 512;
public static final int BLOCK_COUNT = 20;
// *** must be a multiple of BLOCK_SIZE ***
public static int bufferSize = 128 * (2 * BLOCK_SIZE);
// *** need to NLS enable all user messages ***
/**
* Constructor. Expand, run and verbose output requested.
*/
public InstallJars() {
this(true, true, true, "InstallJars.properties", "cmd /c java");
}
/**
* Contstructor.
*
* @param expand
* <code>true</code> if the archive is t be expanded in the target
* @param verbose
* <code>true</code> if messages are to be generated
* @param run
* <code>true</code> if file is to be executed
* @param propName
* properties file with items to install
* @param javaParams
* java parameters
*/
public InstallJars(boolean expand, boolean verbose, boolean run, String propName,
String javaParams) {
setExpand(expand);
setVerbose(verbose);
setRunMode(run);
setPropFilename(propName);
setJavaParams(javaParams);
}
protected boolean verbose;
/**
* Get the verbose mode state.
*
* @return is in verbose mode
*/
public boolean getVerbose() {
return verbose;
}
/**
* Set the verbose mode state.
*
* @param f
* value
*/
public void setVerbose(boolean f) {
verbose = f;
}
protected boolean run;
/**
* Get the run mode state.
*
* @return is in run mode
*/
public boolean getRunMode() {
return run;
}
/**
* Set the run mode state.
*
* @param f
* value
*/
public void setRunMode(boolean f) {
run = f;
}
protected boolean expand;
/**
* Get the expand mode state.
*
* @return is expanded
*/
public boolean getExpand() {
return expand;
}
/**
* Set the expand mode state.
*
* @param f
* value
*/
public void setExpand(boolean f) {
expand = f;
}
protected String propFilename;
/**
* Get the propFilename mode state.
*
* @return prooperty file name
*/
public String getPropFilename() {
return propFilename;
}
/**
* Set the propFilename mode state.
*
* @param name
*/
public void setPropFilename(String name) {
propFilename = name;
}
protected String javaParams = "cmd /c java";
/**
* Get the JavaParams mode state.
*
* @return java parameters
*/
public String getJavaParams() {
return javaParams;
}
/**
* Set the JavaParams mode state.
*
* @param p
* value
*/
public void setJavaParams(String p) {
javaParams = p;
}
protected void print(String s) {
if (verbose) {
System.out.print(s);
}
}
protected void println(String s) {
if (verbose) {
System.out.println(s);
}
}
protected void println() {
println("");
}
/**
* Install based on a properties file<br>
*
* @return recommended classpath
* @exception IOException
* Thrown if a JAR file access error occurs
*/
public String install() throws IOException {
StringBuffer classpath = new StringBuffer();
Properties prop = new Properties();
prop.load(new BufferedInputStream(new FileInputStream(propFilename)));
for (Iterator i = prop.keySet().iterator(); i.hasNext();) {
String key = (String) i.next();
String value = prop.getProperty(key);
String xurl = null;
String xdir = null;
String xcp = null;
boolean xexpand = expand, xrun = run;
if (value != null) {
value = value.trim();
if (value.length() > 0) {
String delim = value.substring(0, 1);
StringTokenizer st = new StringTokenizer(value.substring(1), delim);
xurl = st.nextToken();
xdir = (st.hasMoreTokens() ? st.nextToken() : ".").trim();
if (xdir.length() == 0) {
xdir = ".";
}
xcp = (st.hasMoreTokens() ? st.nextToken() : xdir).trim();
if (xcp.length() == 0) {
xcp = xdir;
}
classpath.append(xcp);
classpath.append(";");
while (st.hasMoreTokens()) {
String xoption = st.nextToken().trim();
if (xoption.equalsIgnoreCase("expand")) {
xexpand = true;
} else if (xoption.equalsIgnoreCase("noexpand")) {
xexpand = false;
} else if (xoption.equalsIgnoreCase("run")) {
xrun = true;
} else if (xoption.equalsIgnoreCase("norun")) {
xrun = false;
} else {
throw new IllegalArgumentException("invalid install property - " + key + "=" + value);
}
}
}
}
if (xurl == null || xurl.length() == 0) {
throw new IllegalArgumentException("missing install property - " + key + "=" + value);
}
System.out.print("\nInstalling " + key);
if (verbose) {
System.out.print(" using URL=" + xurl + "; target=" + xdir + "; classpath=" + xcp + "; "
+ (xexpand ? "expand" : "noexpand") + "; " + (xrun ? "run" : "norun"));
}
System.out.println("...");
installFile(xurl, xdir, xexpand, xrun);
}
return classpath.toString();
}
/**
* Install a Zip/Jar file.
*
* @param fileUrl
* The file/zip/jar file
* @param targetPath
* root of directory or file to install into
* @param doExpand
* @param doRun
* @exception IOException
* Thrown if a JAR file access error occurs
*/
public void installFile(String fileUrl, String targetPath, boolean doExpand, boolean doRun)
throws IOException {
String targetFilename = new File(targetPath).getCanonicalPath().replace("\\", "/");
println("Installing in " + targetFilename);
URL url = new URL(fileUrl);
URLConnection conn = url.openConnection();
// System.out.println("Conn = " + conn);
String ctype = conn.getContentType();
println("Content type is " + ctype);
String extension = getExtension(fileUrl);
if (extension.equals("class")) {
installClass(conn, targetFilename, doExpand, doRun);
// println("Installed class file " + fileUrl + "; please run");
} else if (extension.equalsIgnoreCase("zip")) {
installZip(conn, targetFilename, doExpand, doRun);
// println("Installed ZIP file " + fileUrl + "; ZIP expanded");
} else if (extension.equalsIgnoreCase("gz")) {
installGZip(conn, targetFilename, doExpand, doRun);
// println("Installed GZIP file " + fileUrl + "; ZIP expanded");
} else if (extension.equalsIgnoreCase("jar")) {
installJar(conn, targetFilename, doExpand, doRun);
// System.out.println("Installed JAR file " + fileUrl + "; please add to
// CLASSPATH");
} else {
throw new IllegalArgumentException("Unknown extension - " + extension);
}
}
public void installClass(URLConnection conn, String target, boolean doExpand, boolean doRun)
throws IOException {
// doExpand not used on htis type
print("Installing class file " + target + " from " + conn.getURL().toExternalForm());
copyStream(conn, target);
println();
if (doRun) {
runTarget(target, false);
}
}
protected void runTarget(String target, boolean isJar) throws IOException {
// *** add run code ***
if (isJar) {
System.out.println("runTarget(" + target + "," + isJar + ") not currently implemented");
} else {
try {
String name = removeExtension(getFile(target));
String cp = "-cp " + removeFile(target);
String command = javaParams + " " + cp + " " + name + " >" + name + ".out 2>" + name
+ ".err";
// String command = javaParams + " " + cp + " " + name;
System.out.println("Running " + command + "...");
Process p = Runtime.getRuntime().exec(command);
int rc = p.waitFor();
System.out.println("Return code=" + rc);
} catch (Exception e) {
System.out.println("Exception - " + e.getMessage());
}
}
}
public void installJar(URLConnection conn, String target, boolean doExpand, boolean doRun)
throws IOException {
if (doExpand) {
println("Expanding JAR file " + target + " from " + conn.getURL().toExternalForm());
// *** may need to specialize for JAR format ***
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(conn.getInputStream(),
BLOCK_SIZE * BLOCK_COUNT));
int count = 0;
prepDirs(target, true);
try {
while (zis.available() > 0) {
ZipEntry ze = zis.getNextEntry();
copyEntry(target, zis, ze);
count++;
}
} finally {
try {
zis.close();
} catch (IOException ioe) {
}
}
println("Installed " + count + " files/directories");
} else {
print("Installing JAR file " + target + " from " + conn.getURL().toExternalForm());
copyStream(conn, target);
println();
if (doRun) {
runTarget(target, true);
}
}
}
public void installZip(URLConnection conn, String target, boolean doExpand, boolean doRun)
throws IOException {
// doRun not used on htis type
if (doExpand) {
String ctype = conn.getContentType();
if (!ctype.equals("application/zip")) {
throw new IllegalArgumentException("Unkexpected content type - " + ctype);
}
println("Expanding ZIP file to " + target + " from " + conn.getURL().toExternalForm());
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(conn.getInputStream(),
BLOCK_SIZE * BLOCK_COUNT));
int count = 0;
prepDirs(target, true);
try {
for (ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
copyEntry(target, zis, ze);
// zis.closeEntry();
count++;
}
} finally {
try {
zis.close();
} catch (IOException ioe) {
}
}
println("Installed " + count + " files/directories");
} else {
print("Installing ZIP file " + target + " from " + conn.getURL().toExternalForm());
copyStream(conn, target);
println();
}
}
public void installGZip(URLConnection conn, String target, boolean doExpand, boolean doRun)
throws IOException {
// doRun not used on htis type
if (doExpand) {
String ctype = conn.getContentType();
if (!ctype.equals("application/x-tar")) {
throw new IllegalArgumentException("Unkexpected content type - " + ctype);
}
print("Expanding GZIP file to " + target + " from " + conn.getURL().toExternalForm());
prepDirs(target, false);
GZIPInputStream zis = new GZIPInputStream(new BufferedInputStream(conn.getInputStream(),
BLOCK_SIZE * BLOCK_COUNT));
try {
// BufferedOutputStream os = new BufferedOutputStream(new
// FileOutputStream(target), BLOCK_SIZE * BLOCK_COUNT);
// try {
// byte[] buf = new byte[bufferSize];
// for (int size = zis.read(buf, 0, buf.length), count = 0;
// size >= 0;
// size = zis.read(buf, 0, buf.length), count++) {
// //if (count % 4 == 0) print(".");
// os.write(buf, 0, size);
// }
// }
// finally {
// try { os.flush(); os.close(); } catch (IOException ioe) {}
// }
pumpGZip(target, zis);
} finally {
try {
zis.close();
} catch (IOException ioe) {
}
}
println();
} else {
print("Installing GZIP file " + target + " from " + conn.getURL().toExternalForm());
copyStream(conn, target);
println();
}
}
/** Copy a zip entry. */
protected void copyEntry(String target, ZipInputStream zis, ZipEntry ze) throws IOException {
String name = ze.getName();
boolean isDir = false;
if (name.endsWith("/")) {
name = name.substring(0, name.length() - 1);
isDir = true;
}
String path = target + File.separator + name;
path = path.replace("\\", "/");
String mod = ze.getSize() > 0 ? ("[" + ze.getCompressedSize() + ":" + ze.getSize() + "]") : "";
print("Expanding " + ze + mod + " to " + path);
prepDirs(path, isDir);
if (!isDir) {
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(path), BLOCK_SIZE
* BLOCK_COUNT);
try {
byte[] buf = new byte[bufferSize];
for (int size = zis.read(buf, 0, buf.length), count = 0; size >= 0; size = zis.read(buf, 0,
buf.length), count++) {
// if (count % 4 == 0) print(".");
os.write(buf, 0, size);
}
} finally {
try {
os.flush();
os.close();
} catch (IOException ioe) {
}
}
}
println();
}
public void copyStream(URLConnection conn, String target) throws IOException {
prepDirs(target, false);
BufferedInputStream is = new BufferedInputStream(conn.getInputStream(), BLOCK_SIZE
* BLOCK_COUNT);
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(target), BLOCK_SIZE
* BLOCK_COUNT);
byte[] buf = new byte[bufferSize];
for (int size = is.read(buf), count = 0; size >= 0; size = is.read(buf), count++) {
// if (count % 4 == 0) print(".");
os.write(buf, 0, size);
}
os.flush();
os.close();
is.close();
}
protected static final int OFFSET_NAME = 0;
protected static final int OFFSET_MODE = OFFSET_NAME + 100;
protected static final int OFFSET_UID = OFFSET_MODE + 8;
protected static final int OFFSET_GID = OFFSET_UID + 8;
protected static final int OFFSET_SIZE = OFFSET_GID + 8;
protected static final int OFFSET_MTIME = OFFSET_SIZE + 12;
protected static final int OFFSET_CHKSUM = OFFSET_MTIME + 12;
protected static final int OFFSET_TYPE = OFFSET_CHKSUM + 8;
protected static final int OFFSET_LINKNAME = OFFSET_TYPE + 1;
protected static final int OFFSET_MAGIC = OFFSET_LINKNAME + 100;
protected static final int OFFSET_VERSION = OFFSET_MAGIC + 6;
protected static final int OFFSET_UNAME = OFFSET_VERSION + 2;
protected static final int OFFSET_GNAME = OFFSET_UNAME + 32;
protected static final int OFFSET_DEVMAJOR = OFFSET_GNAME + 32;
protected static final int OFFSET_DEVMINOR = OFFSET_DEVMAJOR + 8;
protected static final int OFFSET_PREFIX = OFFSET_DEVMINOR + 8;
protected static final int OFFSET_END = OFFSET_PREFIX + 155;
protected static final String MAGIC = "USTAR";
protected void pumpGZip(String target, GZIPInputStream zis) throws IOException {
String curName = null;
long curSize = 0, remainingSize = 0;
char curType = 0;
int curMajor = 0, curMinor = 0;
boolean inFile = false;
BufferedOutputStream curOs = null;
int instFiles = 0, instDirs = 0;
byte[] buf = new byte[bufferSize];
top: while (true) {
int loaded = loadBytes(buf, zis);
if (loaded < 0) {
break;
}
// System.out.println("pumpGZip: loaded=" + loaded);
// process each buffer of data
for (int index = 0; index < loaded; index += BLOCK_SIZE) {
// System.out.println("pumpGZip: infile=" + inFile + ", remaining=" +
// remainingSize);
if (inFile && remainingSize > 0) { // process body part
int xsize = Math.min((int) remainingSize, BLOCK_SIZE);
if (curOs != null) {
curOs.write(buf, index, xsize);
}
remainingSize -= xsize;
} else { // process header block
if (inFile) {
inFile = false;
if (curOs != null) {
try {
curOs.flush();
curOs.close();
} catch (IOException ioe) {
}
println();
}
}
if (isEmptyBlock(buf, index)) { // check logical end of archive
break top;
}
// System.out.println("pumpGZip: header=" + (new String(buf, 0, index,
// 512)));
curName = extractString(buf, index + OFFSET_NAME, 100);
curType = extractChar(buf, index + OFFSET_TYPE);
curSize = extractLong(buf, index + OFFSET_SIZE, 12);
remainingSize = curSize;
if (remainingSize > Integer.MAX_VALUE) {
throw new IOException("entry size too large - " + remainingSize);
}
String mod = "";
String magic = extractString(buf, index + OFFSET_MAGIC, 6);
if (magic.equals(MAGIC)) {
curName = extractString(buf, index + OFFSET_PREFIX, 155) + curName;
extractInt(buf, index + OFFSET_VERSION, 2);
curMajor = extractInt(buf, index + OFFSET_DEVMAJOR, 8);
curMinor = extractInt(buf, index + OFFSET_DEVMINOR, 8);
if (curMajor > 0 || curMinor > 0) {
mod = "[" + curMajor + "." + curMinor + "]";
}
}
// System.out.println("pumpGZip: " +
// magic + "," +
// curName + "," +
// curType + "," +
// curSize + "," +
// curVersion + "," +
// curMajor + "," +
// curMinor);
String path = target + File.separator + curName;
path = path.replace("\\", "/");
curOs = null;
if (curType == 0 || curType == "0") { // a file
print("Copying " + curName + mod + " to " + path);
prepDirs(path, false);
curOs = new BufferedOutputStream(new FileOutputStream(path), BLOCK_SIZE * BLOCK_COUNT);
inFile = true;
instFiles++;
} else if (curType == "1" || curType == "2") { // a link
if (curSize > 0) {
throw new IOException("link entries cannot have content - " + curSize);
}
println("Link ignored - " + curName + mod);
} else if (curType == "5") { // a directory
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
println("Mkdir " + curName + mod + " to " + path);
prepDirs(path, true);
instDirs++;
} else {
if (curSize > 0) {
// throw new IOException("entry type " + curType + " cannot have a
// content - size=" + curSize);
inFile = true;
}
print("Entry type " + curType + " ignored - " + curName + mod);
}
}
}
}
println("Installed " + instFiles + " files and " + instDirs + " directories");
}
protected int loadBytes(byte[] buf, GZIPInputStream zis) throws IOException {
int loaded = -1;
for (int size = zis.read(buf, 0, buf.length), count = 0; size > 0; size = zis.read(buf, loaded,
buf.length - loaded), count++) {
// if (count % 4 == 0) print(".");
// System.out.println("loadBytes: loaded=" + loaded);
if (loaded < 0) {
loaded = 0;
}
loaded += size;
}
return loaded;
}
protected boolean isEmptyBlock(byte[] buf, int index) {
boolean r = true;
for (int i = 0; r && i < BLOCK_SIZE; i++) {
r = buf[index++] == 0;
}
// System.out.println("isEmptyBlock: " + r);
return r;
}
protected char extractChar(byte[] buf, int index) throws IOException {
return (char) buf[index];
}
protected int extractInt(byte[] buf, int index, int length) throws IOException {
return (int) extractLong(buf, index, length);
}
protected long extractLong(byte[] buf, int index, int length) throws IOException {
String xsize = extractString(buf, index, length);
long v = 0;
for (int i = 0; i < xsize.length(); i++) {
char c = xsize.charAt(i);
if (c != " ") {
if (c < "0" || c > "7") {
throw new IOException("non-octal digit found - " + c);
}
v = v * 8 + (c - "0");
}
}
return v;
}
protected String extractString(byte[] buf, int index, int length) throws IOException {
StringBuffer sb = new StringBuffer();
for (int i = 0, xindex = index; i < length; i++, xindex++) {
int c = buf[xindex];
if (c == 0) {
break;
}
sb.append((char) c);
}
// System.out.println("extractString(" + index + "," + length + "): " +
// sb.toString());
return sb.toString();
}
protected String getFile(String name) {
int posn = name.lastIndexOf("/");
return posn > 0 ? name.substring(posn + 1) : name;
}
protected String removeFile(String name) {
int posn = name.lastIndexOf("/");
return posn > 0 ? name.substring(0, posn) : name;
}
protected String removeExtension(String name) {
int posn1 = name.lastIndexOf("/");
int posn2 = name.lastIndexOf(".");
return (posn2 > 0 && posn2 > posn1) ? name.substring(0, posn2) : name;
}
protected String extraceFile(String name) {
int posn = name.lastIndexOf(File.separator);
return posn >= 0 ? name.substring(posn + 1) : null;
}
protected String getExtension(String name) {
int posn = name.lastIndexOf(".");
return posn >= 0 ? name.substring(posn + 1) : "";
}
protected void prepDirs(String name) {
prepDirs(name, expand);
}
protected void prepDirs(String name, boolean includeLast) {
File f = new File(includeLast ? name : removeFile(name));
// System.out.print("(Making " + f + ")");
f.mkdirs();
}
protected void printUsage() {
println("Effective command: " + getClass().getName() + " " + propFilename
+ (expand ? " -expand" : " -noexpand") + (run ? " -run" : " -norun") + " -java \""
+ javaParams + "\"" + (verbose ? " -verbose" : " -quiet "));
}
/** Print command help text. */
protected static void printHelp() {
System.out.println();
System.out
.println("Usage: java "
+ InstallJars.class.getName()
+ " {propFilename} {-expand | -noexpand} {-run | -norun} {-quiet | -verbose} {-java <params>}");
System.out.println("Where:");
System.out
.println(" propFilename path to properties file (default=InstallJars.properties)");
System.out.println(" -expand expand any top level JAR/ZIP/GZIP (default)");
System.out.println(" -noexpand do not expand any top level JAR/ZIP/GZIP");
System.out.println(" -run run class or JAR files (default)");
System.out.println(" -norun do not run class or JAR files");
System.out.println(" -verbose output progress messages (default)");
System.out.println(" -quiet suppress most messages");
System.out.println(" -java sets java runtime paramters");
System.out.println();
System.out.println("Properties file entry format: name=!url{!target{!classpath{!option}...}}");
System.out.println("Where:");
System.out.println(" name name displayed while installing");
System.out.println(" url source of items to download and install");
System.out.println(" target root of install directory or file (default=.)");
System.out
.println(" classpath class path entry to use for this directrory or file (default=target}");
System.out.println(" option one of the following options: expand, noexpand, run, norun");
System.out.println(" if omitted, the command line default is used");
System.out.println("! is a delimiter, the first non-whitespace character is used.");
System.out.println("Options expand and run may not apply to all types of files.");
}
/**
* Main command line entry point.
*
* @param args
*/
public static void main(final String[] args) {
if (args.length == 0) {
printHelp();
System.exit(0);
}
String propName = null;
boolean expand = true;
boolean verbose = true;
boolean run = true;
String params = "cmd /c java";
// process arguments
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == "-") { // switch
arg = arg.substring(1);
if (arg.equalsIgnoreCase("quiet")) {
verbose = false;
} else if (arg.equalsIgnoreCase("verbose")) {
verbose = true;
} else if (arg.equalsIgnoreCase("expand")) {
expand = true;
} else if (arg.equalsIgnoreCase("noexpand")) {
expand = false;
} else if (arg.equalsIgnoreCase("run")) {
run = true;
} else if (arg.equalsIgnoreCase("norun")) {
run = false;
} else if (arg.equalsIgnoreCase("java")) {
run = false;
if (i < args.length - 1) {
params = args[++i];
}
} else {
System.err.println("Invalid switch - " + arg);
System.exit(1);
}
} else {
if (propName == null) {
propName = arg;
} else {
System.err.println("Too many parameters - " + arg);
System.exit(1);
}
}
}
if (propName == null) {
propName = "InstallJars.properties";
}
// do the install
try {
InstallJars ij = new InstallJars(expand, verbose, run, propName, params);
ij.printUsage();
String cp = ij.install();
System.out.println("\nRecomended additions to your classpath - " + cp);
} catch (Exception e) {
System.err.println("\n" + e.getClass().getName() + ": " + e.getMessage());
if (verbose) {
e.printStackTrace(); // *** debug ***
}
System.exit(2);
}
}
}
JAR Archives: Jar Lister
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
public class Main {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile("a.jar");
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
System.out.println(je.getName());
long uncompressedSize = je.getSize();
long compressedSize = je.getCompressedSize();
long crc = je.getCrc();
int method = je.getMethod();
String comment = je.getComment();
System.out.println(new Date(je.getTime()));
System.out.println("from " + uncompressedSize + " bytes to "+ compressedSize);
if (method == ZipEntry.STORED) {
System.out.println("ZipEntry.STORED");
}
else if (method == ZipEntry.DEFLATED) {
System.out.println(ZipEntry.DEFLATED);
}
System.out.println("Its CRC is " + crc);
System.out.println(comment);
System.out.println(je.isDirectory());
Attributes a = je.getAttributes();
if (a != null) {
Object[] nameValuePairs = a.entrySet().toArray();
for (int j = 0; j < nameValuePairs.length; j++) {
System.out.println(nameValuePairs[j]);
}
}
System.out.println();
}
}
}
JAR Archives: Packer200
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.jar.JarFile;
import java.util.jar.Pack200;
public class Main {
public static void main(String[] args) throws Exception {
JarFile f = new JarFile("a.jar");
Pack200.Packer packer = Pack200.newPacker();
OutputStream out = new FileOutputStream("a.pack");
packer.pack(f, out);
out.close();
}
}
JAR Archives: Unpacker200
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.zip.GZIPInputStream;
public class Main {
public static void main(String[] args) throws Exception {
String inName = "a.pack.gz";
String outName = "a.unpacked";
Pack200.Unpacker unpacker = Pack200.newUnpacker();
JarOutputStream out = new JarOutputStream(new FileOutputStream(outName));
InputStream in = new FileInputStream(inName);
in = new GZIPInputStream(in);
unpacker.unpack(in, out);
out.close();
}
}
Jar builder
/*BEGIN_COPYRIGHT_BLOCK
*
* Copyright (c) 2001-2008, JavaPLT group at Rice University (drjava@rice.edu)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is Open Source Initiative approved Open Source Software.
* Open Source Initative Approved is a trademark of the Open Source Initiative.
*
* This file is part of DrJava. Download the current version of this project
* from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
*
* END_COPYRIGHT_BLOCK*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
public class JarBuilder {
private JarOutputStream _output;
/** Creates a file file without a manifest
*
* @param file the file to write the jar to
* @throws IOException thrown if the file cannot be opened for writing
*/
public JarBuilder(File file) throws IOException {
_output = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(file)), ManifestWriter.DEFAULT);
}
/** Creates an empty jar file with the given manifest
*
* @param jar the file to write the jar to
* @param manifest the file that is the manifest for the archive
* @throws IOException thrown if either file cannot be opened for reading
*/
public JarBuilder(File jar, File manifest) throws IOException {
_output = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(jar)), new Manifest(new FileInputStream(manifest)));
}
/** Creates an empty jar file with the given manifest
*
* @param jar the file to write the jar to
* @param manifest the manifest file for the jar
* @see ManifestWriter
*/
public JarBuilder(File jar, Manifest manifest) {
try {
_output = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(jar)), manifest);
}
catch (IOException e) {
e.printStackTrace();
}
}
/** Takes a parent name and a field name and returns the concatenation of them correctly
*
* @param parent The parent directory
* @param name The name of the file or directory
* @return the string concatenation of the parent and the name
*/
private String makeName(String parent, String name) {
String sep = "/"; // NOTE: This can be a "/" since it is a path in the jar file itself
if( parent.equals("") )
return name;
if (parent.endsWith(sep))
return parent + name;
return parent + sep + name;
}
/** Adds the file to the given path and name
*
* @param file the file to be added
* @param parent the directory to the path in which the file is to be added
* @param fileName the name of the file in the archive
*/
public void addFile(File file, String parent, String fileName) throws IOException {
byte data[] = new byte[2048];
FileInputStream fi = new FileInputStream(file.getAbsolutePath());
BufferedInputStream origin = new BufferedInputStream(fi, 2048);
JarEntry entry = new JarEntry(makeName(parent, fileName));
_output.putNextEntry(entry);
int count = origin.read(data, 0, 2048);
while (count != -1) {
_output.write(data, 0, count);
count = origin.read(data, 0, 2048);
}
origin.close();
}
/** Add the directory into the directory specified by parent
* @param dir the directory to add
* @param parent the path inside the jar that the directory should be added to
*/
public void addDirectoryRecursive(File dir, String parent) {
addDirectoryRecursiveHelper(dir, parent, new byte[2048], new FileFilter() {
public boolean accept(File pathname) { return true; }
});
}
/** Add the directory into the directory specified by parent
* @param dir the directory to add
* @param parent the path inside the jar that the directory should be added to
* @param filter the filter used to filter the files
*/
public void addDirectoryRecursive(File dir, String parent, FileFilter filter) {
addDirectoryRecursiveHelper(dir, parent, new byte[2048], filter);
}
/** Add the contents of a directory that match a filter to the archive
* @param dir the directory to add
* @param parent the directory to add into
* @param buffer a buffer that is 2048 bytes
* @param filter the FileFilter to filter the files by
* @return true on success, false on failure
*/
private boolean addDirectoryRecursiveHelper(File dir, String parent, byte[] buffer, FileFilter filter) {
try {
File[] files = dir.listFiles(filter);
BufferedInputStream origin = null;
if( files == null ) // listFiles may return null if there"s an IO error
return true;
for (int i = 0; i < files.length; i++) {
if( files[i].isFile() ) {
origin = new BufferedInputStream(new FileInputStream(files[i]), 2048);
JarEntry entry = new JarEntry(makeName(parent, files[i].getName()));
_output.putNextEntry(entry);
int count;
while((count = origin.read(buffer, 0, 2048)) != -1) {
_output.write(buffer, 0, count);
}
origin.close();
}
else if( files[i].isDirectory() ) {
addDirectoryRecursiveHelper(files[i], makeName(parent, files[i].getName()),buffer,filter);
}
}
} catch(Exception e) {
e.printStackTrace();
}
return true;
}
/** Makes a directory in the jar file
*
* @param parent The name of the parent that the directory is to be created in
* @param dirName The name of the directory to be created
* @return Returns true on success, false on failure
*/
public boolean makeDirectory(String parent, String dirName) {
JarEntry entry = new JarEntry(makeName(parent, dirName));
try {
_output.putNextEntry(entry);
}
catch (IOException e) {
return false;
}
return true;
}
/** Close writing on the jar file
*/
public void close() throws IOException {
_output.flush();
_output.close();
}
}
class ManifestWriter {
private List<String> _classPaths;
private String _mainClass;
private String _rawManifest;
public static final Manifest DEFAULT = new ManifestWriter().getManifest();
/** Create a new manifest file */
public ManifestWriter() {
_classPaths = new LinkedList<String>();
_mainClass = null;
_rawManifest = null;
}
/** Add a class path to the Manifest
* @param path the path to be added
*/
public void addClassPath(String path) {
_classPaths.add(_classPaths.size(), path);
}
/** Set the main class of the Manifest
* @param mainClass
*/
public void setMainClass(String mainClass) {
_mainClass = mainClass;
_rawManifest = null;
}
public void setManifestContents(String rawManifest) {
_rawManifest = rawManifest;
_mainClass = null;
}
/** Get an input stream to the contents of the manifest file
* @return an InputStream whose contents are the contents of the Manifest file
*/
protected InputStream getInputStream() {
// NOTE: All significant lines in the manifest MUST end in the end of line character
final StringBuilder sbuf = new StringBuilder();
sbuf.append(Attributes.Name.MANIFEST_VERSION.toString());
sbuf.append(": 1.0" + "\n");
if( !_classPaths.isEmpty() ) {
Iterator<String> iter = _classPaths.iterator();
sbuf.append(Attributes.Name.CLASS_PATH.toString());
sbuf.append(":");
while (iter.hasNext()) {
sbuf.append(" ");
sbuf.append(iter.next());
}
sbuf.append("\n");
}
if( _mainClass != null ) {
sbuf.append(Attributes.Name.MAIN_CLASS.toString());
sbuf.append(": ");
sbuf.append(_mainClass);
sbuf.append("\n");
}
if(_rawManifest != null) {
sbuf.append(_rawManifest);
if(!_rawManifest.endsWith("\n"))
sbuf.append("\n");
}
try { return new ByteArrayInputStream(sbuf.toString().getBytes("UTF-8")); }
catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
/** Get the Manifest object that this object created.
* @return the Manifest that this builder created
*/
public Manifest getManifest() {
try {
Manifest m = new Manifest();
m.read(getInputStream());
return m;
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Jar Entry OutputStream
/*
* The contents of this file are subject to the Sapient Public License
* Version 1.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://carbon.sf.net/License.html.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is The Carbon Component Framework.
*
* The Initial Developer of the Original Code is Sapient Corporation
*
* Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
*/
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import sun.rmi.runtime.Log;
/**
* An output stream that is used by EnhancedJarFile to write entries to a jar.
* This implementation uses a ByteArrayOutputStream to buffer the output
* until the stream is closed. When the stream is closed, the output is written
* to the jar.
*
* Copyright 2002 Sapient
* @since carbon 1.0
* @author Douglas Voet, April 2002
* @version $Revision: 1.9 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $)
*/
public class JarEntryOutputStream extends ByteArrayOutputStream {
private EnhancedJarFile jar;
private String jarEntryName;
/**
* Constructor
*
* @param jar the EnhancedJarFile that this instance will write to
* @param jarEntryName the name of the entry to be written
*/
public JarEntryOutputStream(
EnhancedJarFile jar,
String jarEntryName) {
super();
this.jarEntryName = jarEntryName;
this.jar = jar;
}
/**
* Closes the stream and writes entry to the jar
*/
public void close() throws IOException {
writeToJar();
super.close();
}
/**
* Writes the entry to a the jar file. This is done by creating a
* temporary jar file, copying the contents of the existing jar to the
* temp jar, skipping the entry named by this.jarEntryName if it exists.
* Then, if the stream was written to, then contents are written as a
* new entry. Last, a callback is made to the EnhancedJarFile to
* swap the temp jar in for the old jar.
*/
private void writeToJar() throws IOException {
File jarDir = new File(this.jar.getName()).getParentFile();
// create new jar
File newJarFile = File.createTempFile("config", ".jar", jarDir);
newJarFile.deleteOnExit();
JarOutputStream jarOutputStream =
new JarOutputStream(new FileOutputStream(newJarFile));
try {
Enumeration entries = this.jar.entries();
// copy all current entries into the new jar
while (entries.hasMoreElements()) {
JarEntry nextEntry = (JarEntry) entries.nextElement();
// skip the entry named jarEntryName
if (!this.jarEntryName.equals(nextEntry.getName())) {
// the next 3 lines of code are a work around for
// bug 4682202 in the java.sun.ru bug parade, see:
// http://developer.java.sun.ru/developer/bugParade/bugs/4682202.html
JarEntry entryCopy = new JarEntry(nextEntry);
entryCopy.setCompressedSize(-1);
jarOutputStream.putNextEntry(entryCopy);
InputStream intputStream =
this.jar.getInputStream(nextEntry);
// write the data
for (int data = intputStream.read();
data != -1;
data = intputStream.read()) {
jarOutputStream.write(data);
}
}
}
// write the new or modified entry to the jar
if (size() > 0) {
jarOutputStream.putNextEntry(new JarEntry(this.jarEntryName));
jarOutputStream.write(super.buf, 0, size());
jarOutputStream.closeEntry();
}
} finally {
// close close everything up
try {
if (jarOutputStream != null) {
jarOutputStream.close();
}
} catch (IOException ioe) {
// eat it, just wanted to close stream
}
}
// swap the jar
this.jar.swapJars(newJarFile);
}
}
/*
* The contents of this file are subject to the Sapient Public License
* Version 1.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://carbon.sf.net/License.html.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is The Carbon Component Framework.
*
* The Initial Developer of the Original Code is Sapient Corporation
*
* Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
*/
/**
* This class enhances functionality of java.util.jar.JarFile.
* Additional functionality includes jar entry removal, the ability to list
* the entries within a directory within the jar, and the ability to get
* an output stream for modifying extisting entries.
*
* @see java.util.jar.JarFile
*
* Copyright 2002 Sapient
* @since carbon 1.0
* @author Doug Voet, April 2002
* @version $Revision: 1.11 $ ($Author: dvoet $)
*/
class EnhancedJarFile {
public static final String JAR_DELIMETER = "/";
private JarFile jar;
/**
* @see java.util.jar.JarFile#JarFile(java.lang.String)
*/
public EnhancedJarFile(String name) throws IOException {
this.jar = new JarFile(name);
}
/**
* @see java.util.jar.JarFile#JarFile(java.lang.String, boolean)
*/
public EnhancedJarFile(String name, boolean verify) throws IOException {
this.jar = new JarFile(name, verify);
}
/**
* @see java.util.jar.JarFile#JarFile(java.io.File)
*/
public EnhancedJarFile(File file) throws IOException {
this.jar = new JarFile(file);
}
/**
* @see java.util.jar.JarFile#JarFile(java.io.File, boolean)
*/
public EnhancedJarFile(File file, boolean verify) throws IOException {
this.jar = new JarFile(file, verify);
}
/**
* @see java.util.jar.JarFile#JarFile(java.io.File, boolean, int)
*/
public EnhancedJarFile(File file, boolean verify, int mode)
throws IOException {
this.jar = new JarFile(file, verify, mode);
}
/**
* Returns a list of entries that are
* immediately below the entry named by entryName in the jar"s directory
* structure.
*
* @param entryName the name of the directory entry name
* @return List a list of java.util.jar.JarEntry objects that are
* immediately below the entry named by entryName in the jar"s directory
* structure.
*/
public List listSubEntries(String entryName) {
Enumeration entries = jar.entries();
List subEntries = new ArrayList();
while(entries.hasMoreElements()) {
JarEntry nextEntry = (JarEntry) entries.nextElement();
if (nextEntry.getName().startsWith(entryName)) {
// the next entry name starts with the entryName so it
// is a potential sub entry
// tokenize the rest of the next entry name to see how
// many tokens exist
StringTokenizer tokenizer = new StringTokenizer(
nextEntry.getName().substring(entryName.length()),
EnhancedJarFile.JAR_DELIMETER);
if (tokenizer.countTokens() == 1) {
// only 1 token exists, so it is a sub-entry
subEntries.add(nextEntry);
}
}
}
return subEntries;
}
/**
* Creates a new output entry stream within the jar. The entry named
* will be created if it does not exist within the jar already.
*
* @param entryName name of the entry for which to create an output
* stream.
* @return JarEntryOutputStream
*/
public JarEntryOutputStream getEntryOutputStream(String entryName) {
return new JarEntryOutputStream(this, entryName);
}
/**
* Removes the given entry from the jar. If the entry does not exist,
* the method returns without doing anything.
*
* @param entry entry to be removed
* @throws IOException if there is a problem writing the changes
* to the jar
*/
public void removeEntry(JarEntry entry) throws IOException {
// opens an output stream and closes it without writing anything to it
if (entry != null && getEntry(entry.getName()) != null) {
JarEntryOutputStream outputStream =
new JarEntryOutputStream(this, entry.getName());
outputStream.close();
}
}
/**
* @see java.util.jar.JarFile#entries()
*/
public Enumeration entries() {
return this.jar.entries();
}
/**
* @see java.util.jar.JarFile#getEntry(java.lang.String)
*/
public ZipEntry getEntry(String arg0) {
return this.jar.getEntry(arg0);
}
/**
* @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
*/
public InputStream getInputStream(ZipEntry arg0) throws IOException {
return this.jar.getInputStream(arg0);
}
/**
* @see java.util.jar.JarFile#getJarEntry(java.lang.String)
*/
public JarEntry getJarEntry(String arg0) {
return this.jar.getJarEntry(arg0);
}
/**
* @see java.util.jar.JarFile#getManifest()
*/
public Manifest getManifest() throws IOException {
return this.jar.getManifest();
}
/**
* @see java.util.zip.ZipFile#close()
*/
public void close() throws IOException {
this.jar.close();
}
/**
* @see java.util.zip.ZipFile#getName()
*/
public String getName() {
return this.jar.getName();
}
/**
* @see java.util.zip.ZipFile#size()
*/
public int size() {
return this.jar.size();
}
/**
* Utility method used to swap the underlying jar file out for the new one.
* This method closes the old jar file, deletes it, moves the new jar
* file to the location where the old one used to be and opens it.
* <p>
* This is used when modifying the jar (removal, addition, or changes
* of entries)
*
* @param newJarFile the file object pointing to the new jar file
*/
void swapJars(File newJarFile) throws IOException {
File oldJarFile = new File(getName());
this.jar.close();
oldJarFile.delete();
if (newJarFile.renameTo(oldJarFile)) {
this.jar = new JarFile(oldJarFile);
} else {
throw new IOException();
}
}
}
Jar file helper to deployment
/**
* 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.
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.security.cert.Certificate;
/**
* @version $Rev: 726699 $ $Date: 2008-12-15 06:30:36 -0800 (Mon, 15 Dec 2008) $
*/
public class UnpackedJarFile extends JarFile {
private final File baseDir;
private boolean manifestLoaded = false;
private Manifest manifest;
public UnpackedJarFile(File baseDir) throws IOException {
super(DeploymentUtil.DUMMY_JAR_FILE);
this.baseDir = baseDir;
if (!baseDir.isDirectory()) {
throw new IOException("File must be a directory: file=" + baseDir.getAbsolutePath());
}
}
public File getBaseDir() {
return baseDir;
}
public Manifest getManifest() throws IOException {
if (!manifestLoaded) {
File manifestFile = getFile("META-INF/MANIFEST.MF");
if (manifestFile != null && manifestFile.isFile()) {
FileInputStream in = null;
try {
in = new FileInputStream(manifestFile);
manifest = new Manifest(in);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
}
manifestLoaded = true;
}
return manifest;
}
public UnpackedJarEntry getUnpackedJarEntry(String name) {
File file = getFile(name);
if (file == null) {
return null;
}
return new UnpackedJarEntry(name, file, getManifestSafe());
}
public JarEntry getJarEntry(String name) {
return getUnpackedJarEntry(name);
}
public ZipEntry getEntry(String name) {
return getUnpackedJarEntry(name);
}
public Enumeration entries() {
Collection files = DeploymentUtil.listRecursiveFiles(baseDir);
Manifest manifest = getManifestSafe();
LinkedList entries = new LinkedList();
URI baseURI = baseDir.getAbsoluteFile().toURI();
for (Iterator iterator = files.iterator(); iterator.hasNext();) {
File entryFile = ((File) iterator.next()).getAbsoluteFile();
URI entryURI = entryFile.toURI();
URI relativeURI = baseURI.relativize(entryURI);
entries.add(new UnpackedJarEntry(relativeURI.getPath(), entryFile, manifest));
}
return Collections.enumeration(entries);
}
public InputStream getInputStream(ZipEntry zipEntry) throws IOException {
File file;
if (zipEntry instanceof UnpackedJarEntry) {
file = ((UnpackedJarEntry)zipEntry).getFile();
} else {
file = getFile(zipEntry.getName());
}
if (file == null) {
throw new IOException("Entry not found: name=" + zipEntry.getName());
} else if (file.isDirectory()) {
return new DeploymentUtil.EmptyInputStream();
}
return new FileInputStream(file);
}
public String getName() {
return baseDir.getAbsolutePath();
}
/**
* Always returns -1.
* @return -1
*/
public int size() {
return -1;
}
public void close() throws IOException {
try {
super.close();
} catch(IOException ignored) {
}
}
protected void finalize() throws IOException {
}
public File getFile(String name) {
File file = new File(baseDir, name);
if (!file.exists()) {
return null;
}
return file;
}
private Manifest getManifestSafe() {
Manifest manifest = null;
try {
manifest = getManifest();
} catch (IOException e) {
// ignore
}
return manifest;
}
}
/**
* 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.
*/
/**
* @version $Rev: 617659 $ $Date: 2008-02-01 13:29:25 -0800 (Fri, 01 Feb 2008) $
*/
final class DeploymentUtil {
private DeploymentUtil() {
}
public static final File DUMMY_JAR_FILE;
private static final boolean jarUrlRewrite;
static {
jarUrlRewrite = new Boolean(System.getProperty("org.apache.geronimo.deployment.util.DeploymentUtil.jarUrlRewrite", "false"));
try {
DUMMY_JAR_FILE = DeploymentUtil.createTempFile();
new JarOutputStream(new FileOutputStream(DeploymentUtil.DUMMY_JAR_FILE), new Manifest()).close();
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
// be careful to clean up the temp directory
public static File createTempDir() throws IOException {
File tempDir = File.createTempFile("geronimo-deploymentUtil", ".tmpdir");
tempDir.delete();
tempDir.mkdirs();
return tempDir;
}
// be careful to clean up the temp file... we tell the vm to delete this on exit
// but VMs can"t be trusted to acutally delete the file
public static File createTempFile() throws IOException {
File tempFile = File.createTempFile("geronimo-deploymentUtil", ".tmpdir");
tempFile.deleteOnExit();
return tempFile;
}
// be careful to clean up the temp file... we tell the vm to delete this on exit
// but VMs can"t be trusted to acutally delete the file
private static File createTempFile(String extension) throws IOException {
File tempFile = File.createTempFile("geronimo-deploymentUtil", extension == null? ".tmpdir": extension);
tempFile.deleteOnExit();
return tempFile;
}
public static void copyFile(File source, File destination) throws IOException {
File destinationDir = destination.getParentFile();
if (!destinationDir.exists() && !destinationDir.mkdirs()) {
throw new java.io.IOException("Cannot create directory : " + destinationDir);
}
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(source);
out = new FileOutputStream(destination);
writeAll(in, out);
} finally {
close(in);
close(out);
}
}
private static void writeAll(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[4096];
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
out.flush();
}
public static File toTempFile(JarFile jarFile, String path) throws IOException {
return toTempFile(createJarURL(jarFile, path));
}
public static File toTempFile(URL url) throws IOException {
InputStream in = null;
OutputStream out = null;
JarFile jarFile = null;
try {
if(url.getProtocol().equalsIgnoreCase("jar")) {
// url.openStream() locks the jar file and does not release the lock even after the stream is closed.
// This problem is avoided by using JarFile APIs.
File file = new File(url.getFile().substring(5, url.getFile().indexOf("!/")));
String path = url.getFile().substring(url.getFile().indexOf("!/")+2);
jarFile = new JarFile(file);
JarEntry jarEntry = jarFile.getJarEntry(path);
if(jarEntry != null) {
in = jarFile.getInputStream(jarEntry);
} else {
throw new FileNotFoundException("JarEntry "+path+" not found in "+file);
}
} else {
in = url.openStream();
}
int index = url.getPath().lastIndexOf(".");
String extension = null;
if (index > 0) {
extension = url.getPath().substring(index);
}
File tempFile = createTempFile(extension);
out = new FileOutputStream(tempFile);
writeAll(in, out);
return tempFile;
} finally {
close(out);
close(in);
close(jarFile);
}
}
public static String readAll(URL url) throws IOException {
Reader reader = null;
JarFile jarFile = null;
try {
if(url.getProtocol().equalsIgnoreCase("jar")) {
// url.openStream() locks the jar file and does not release the lock even after the stream is closed.
// This problem is avoided by using JarFile APIs.
File file = new File(url.getFile().substring(5, url.getFile().indexOf("!/")));
String path = url.getFile().substring(url.getFile().indexOf("!/")+2);
jarFile = new JarFile(file);
JarEntry jarEntry = jarFile.getJarEntry(path);
if(jarEntry != null) {
reader = new InputStreamReader(jarFile.getInputStream(jarEntry));
} else {
throw new FileNotFoundException("JarEntry "+path+" not found in "+file);
}
} else {
reader = new InputStreamReader(url.openStream());
}
char[] buffer = new char[4000];
StringBuffer out = new StringBuffer();
for(int count = reader.read(buffer); count >= 0; count = reader.read(buffer)) {
out.append(buffer, 0, count);
}
return out.toString();
} finally {
close(reader);
close(jarFile);
}
}
public static File toFile(JarFile jarFile) throws IOException {
if (jarFile instanceof UnpackedJarFile) {
return ((UnpackedJarFile) jarFile).getBaseDir();
} else {
throw new IOException("jarFile is not a directory");
}
}
// be careful with this method as it can leave a temp lying around
public static File toFile(JarFile jarFile, String path) throws IOException {
if (jarFile instanceof UnpackedJarFile) {
File baseDir = ((UnpackedJarFile) jarFile).getBaseDir();
File file = new File(baseDir, path);
if (!file.isFile()) {
throw new IOException("No such file: " + file.getAbsolutePath());
}
return file;
} else {
String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path;
return toTempFile(new URL(urlString));
}
}
public static URL createJarURL(JarFile jarFile, String path) throws MalformedURLException {
if (jarFile instanceof NestedJarFile) {
NestedJarFile nestedJar = (NestedJarFile) jarFile;
if (nestedJar.isUnpacked()) {
JarFile baseJar = nestedJar.getBaseJar();
String basePath = nestedJar.getBasePath();
if (baseJar instanceof UnpackedJarFile) {
File baseDir = ((UnpackedJarFile) baseJar).getBaseDir();
baseDir = new File(baseDir, basePath);
return new File(baseDir, path).toURL();
}
}
}
if (jarFile instanceof UnpackedJarFile) {
File baseDir = ((UnpackedJarFile) jarFile).getBaseDir();
return new File(baseDir, path).toURL();
} else {
String urlString = "jar:" + new File(jarFile.getName()).toURL() + "!/" + path;
if(jarUrlRewrite) {
// To prevent the lockout of archive, instead of returning a jar url, write the content to a
// temp file and return the url of that file.
File tempFile = null;
try {
tempFile = toTempFile(new URL(urlString));
} catch (IOException e) {
// The JarEntry does not exist!
// Return url of a file that does not exist.
try {
tempFile = createTempFile();
tempFile.delete();
} catch (IOException ignored) {
}
}
return tempFile.toURL();
} else {
return new URL(urlString);
}
}
}
public static JarFile createJarFile(File jarFile) throws IOException {
if (jarFile.isDirectory()) {
return new UnpackedJarFile(jarFile);
} else {
return new JarFile(jarFile);
}
}
public static void copyToPackedJar(JarFile inputJar, File outputFile) throws IOException {
if (inputJar.getClass() == JarFile.class) {
// this is a plain old jar... nothign special
copyFile(new File(inputJar.getName()), outputFile);
} else if (inputJar instanceof NestedJarFile && ((NestedJarFile)inputJar).isPacked()) {
NestedJarFile nestedJarFile = (NestedJarFile)inputJar;
JarFile baseJar = nestedJarFile.getBaseJar();
String basePath = nestedJarFile.getBasePath();
if (baseJar instanceof UnpackedJarFile) {
// our target jar is just a file in upacked jar (a plain old directory)... now
// we just need to find where it is and copy it to the outptu
copyFile(((UnpackedJarFile)baseJar).getFile(basePath), outputFile);
} else {
// out target is just a plain old jar file directly accessabel from the file system
copyFile(new File(baseJar.getName()), outputFile);
}
} else {
// copy out the module contents to a standalone jar file (entry by entry)
JarOutputStream out = null;
try {
out = new JarOutputStream(new FileOutputStream(outputFile));
byte[] buffer = new byte[4096];
Enumeration entries = inputJar.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
InputStream in = inputJar.getInputStream(entry);
try {
out.putNextEntry(new ZipEntry(entry.getName()));
try {
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
} finally {
out.closeEntry();
}
} finally {
close(in);
}
}
} finally {
close(out);
}
}
}
public static void jarDirectory(File sourceDirecotry, File destinationFile) throws IOException {
JarFile inputJar = new UnpackedJarFile(sourceDirecotry);
try {
copyToPackedJar(inputJar, destinationFile);
} finally {
close(inputJar);
}
}
private static void createDirectory(File dir) throws IOException {
if (dir != null && !dir.exists()) {
boolean success = dir.mkdirs();
if (!success) {
throw new IOException("Cannot create directory " + dir.getAbsolutePath());
}
}
}
public static void unzipToDirectory(ZipFile zipFile, File destDir) throws IOException {
Enumeration entries = zipFile.entries();
try {
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
if (entry.isDirectory()) {
File dir = new File(destDir, entry.getName());
createDirectory(dir);
} else {
File file = new File(destDir, entry.getName());
createDirectory(file.getParentFile());
OutputStream out = null;
InputStream in = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
in = zipFile.getInputStream(entry);
writeAll(in, out);
} finally {
if (null != out) {
out.close();
}
if (null != in) {
in.close();
}
}
}
}
} finally {
zipFile.close();
}
}
public static boolean recursiveDelete(File root, Collection<String> unableToDeleteCollection) {
if (root == null) {
return true;
}
if (root.isDirectory()) {
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
recursiveDelete(file, unableToDeleteCollection);
} else {
if (!file.delete() && unableToDeleteCollection != null) {
unableToDeleteCollection.add(file.getAbsolutePath());
}
}
// help out the GC of file handles by nulling the references
files[i] = null;
}
}
}
boolean rootDeleteStatus;
if (!(rootDeleteStatus = root.delete()) && unableToDeleteCollection != null)
unableToDeleteCollection.add(root.getAbsolutePath());
return rootDeleteStatus;
}
public static boolean recursiveDelete(File root) {
return recursiveDelete(root, null);
}
public static Collection<File> listRecursiveFiles(File file) {
Collection<File> list = new ArrayList<File>();
listRecursiveFiles(file, list);
return Collections.unmodifiableCollection(list);
}
public static void listRecursiveFiles(File file, Collection<File> collection) {
File[] files = file.listFiles();
if ( null == files ) {
return;
}
for (File file1 : files) {
collection.add(file1);
if (file1.isDirectory()) {
listRecursiveFiles(file1, collection);
}
}
}
public static void flush(OutputStream thing) {
if (thing != null) {
try {
thing.flush();
} catch(Exception ignored) {
}
}
}
public static void flush(Writer thing) {
if (thing != null) {
try {
thing.flush();
} catch(Exception ignored) {
}
}
}
public static void close(JarFile thing) {
if (thing != null) {
try {
thing.close();
} catch(Exception ignored) {
}
}
}
public static void close(InputStream thing) {
if (thing != null) {
try {
thing.close();
} catch(Exception ignored) {
}
}
}
public static void close(OutputStream thing) {
if (thing != null) {
try {
thing.close();
} catch(Exception ignored) {
}
}
}
public static void close(Reader thing) {
if (thing != null) {
try {
thing.close();
} catch(Exception ignored) {
}
}
}
public static void close(Writer thing) {
if (thing != null) {
try {
thing.close();
} catch(Exception ignored) {
}
}
}
public static final class EmptyInputStream extends InputStream {
public int read() {
return -1;
}
public int read(byte b[]) {
return -1;
}
public int read(byte b[], int off, int len) {
return -1;
}
public long skip(long n) {
return 0;
}
public int available() {
return 0;
}
public void close() {
}
public synchronized void mark(int readlimit) {
}
public synchronized void reset() {
}
public boolean markSupported() {
return false;
}
}
}
/**
* 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.
*/
/**
* @version $Rev: 726699 $ $Date: 2008-12-15 06:30:36 -0800 (Mon, 15 Dec 2008) $
*/
class NestedJarFile extends JarFile {
private JarFile baseJar;
private String basePath;
private boolean isClosed = false;
private boolean manifestLoaded = false;
private Manifest manifest;
private File tempFile;
public NestedJarFile(JarFile jarFile, String path) throws IOException {
super(DeploymentUtil.DUMMY_JAR_FILE);
// verify that the jar actually contains that path
JarEntry targetEntry = jarFile.getJarEntry(path + "/");
if (targetEntry == null) {
targetEntry = jarFile.getJarEntry(path);
if (targetEntry == null) {
throw new IOException("Jar entry does not exist: jarFile=" + jarFile.getName() + ", path=" + path);
}
}
if (targetEntry.isDirectory()) {
if(targetEntry instanceof UnpackedJarEntry) {
//unpacked nested module inside unpacked ear
File targetFile = ((UnpackedJarEntry) targetEntry).getFile();
baseJar = new UnpackedJarFile(targetFile);
basePath = "";
} else {
baseJar = jarFile;
if (!path.endsWith("/")) {
path += "/";
}
basePath = path;
}
} else {
if (targetEntry instanceof UnpackedJarEntry) {
// for unpacked jars we don"t need to copy the jar file
// out to a temp directory, since it is already available
// as a raw file
File targetFile = ((UnpackedJarEntry) targetEntry).getFile();
baseJar = new JarFile(targetFile);
basePath = "";
} else {
tempFile = DeploymentUtil.toFile(jarFile, targetEntry.getName());
baseJar = new JarFile(tempFile);
basePath = "";
}
}
}
public boolean isUnpacked() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return ( basePath.length() > 0 ) ||
( ( baseJar != null ) && ( baseJar instanceof UnpackedJarFile ) );
}
public boolean isPacked() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return ( basePath.length() == 0 ) &&
( ( baseJar == null ) || !( baseJar instanceof UnpackedJarFile ) );
}
public JarFile getBaseJar() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return baseJar;
}
public String getBasePath() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return basePath;
}
public Manifest getManifest() throws IOException {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
if (!manifestLoaded) {
JarEntry manifestEntry = getBaseEntry("META-INF/MANIFEST.MF");
if (manifestEntry != null && !manifestEntry.isDirectory()) {
InputStream in = null;
try {
in = baseJar.getInputStream(manifestEntry);
manifest = new Manifest(in);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
}
manifestLoaded = true;
}
return manifest;
}
public NestedJarEntry getNestedJarEntry(String name) {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
JarEntry baseEntry = getBaseEntry(name);
if (baseEntry == null) {
return null;
}
return new NestedJarEntry(name, baseEntry, getManifestSafe());
}
public JarEntry getJarEntry(String name) {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return getNestedJarEntry(name);
}
public ZipEntry getEntry(String name) {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return getNestedJarEntry(name);
}
public Enumeration entries() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
Collection baseEntries = Collections.list(baseJar.entries());
Collection entries = new LinkedList();
for (Iterator iterator = baseEntries.iterator(); iterator.hasNext();) {
JarEntry baseEntry = (JarEntry) iterator.next();
String path = baseEntry.getName();
if (path.startsWith(basePath)) {
entries.add(new NestedJarEntry(path.substring(basePath.length()), baseEntry, getManifestSafe()));
}
}
return Collections.enumeration(entries);
}
public InputStream getInputStream(ZipEntry zipEntry) throws IOException {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
JarEntry baseEntry;
if (zipEntry instanceof NestedJarEntry) {
baseEntry = ((NestedJarEntry)zipEntry).getBaseEntry();
} else {
baseEntry = getBaseEntry(zipEntry.getName());
}
if (baseEntry == null) {
throw new IOException("Entry not found: name=" + zipEntry.getName());
} else if (baseEntry.isDirectory()) {
return new DeploymentUtil.EmptyInputStream();
}
return baseJar.getInputStream(baseEntry);
}
public String getName() {
return baseJar.getName();
}
/**
* Always returns -1.
* @return -1
*/
public int size() {
if (isClosed) {
throw new IllegalStateException("NestedJarFile is closed");
}
return -1;
}
public void close() throws IOException {
if (isClosed) {
return;
}
try {
try {
super.close();
} catch(IOException ignored) {
}
if (baseJar != null && basePath.length() == 0) {
// baseJar is created by us. We should be closing it too.
baseJar.close();
}
} finally {
isClosed = true;
baseJar = null;
basePath = null;
manifestLoaded = false;
manifest = null;
if (tempFile != null) {
tempFile.delete();
tempFile = null;
}
}
}
protected void finalize() throws IOException {
close();
}
private JarEntry getBaseEntry(String name) {
return baseJar.getJarEntry(basePath + name);
}
private Manifest getManifestSafe() {
Manifest manifest = null;
try {
manifest = getManifest();
} catch (IOException e) {
// ignore
}
return manifest;
}
}
/**
* 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.
*/
/**
* @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
*/
class NestedJarEntry extends JarEntry {
private final JarEntry baseEntry;
private final Manifest manifest;
public NestedJarEntry(String name, JarEntry baseEntry, Manifest manifest) {
super(name);
this.baseEntry = baseEntry;
this.manifest = manifest;
}
public JarEntry getBaseEntry() {
return baseEntry;
}
public Attributes getAttributes() throws IOException {
if (manifest == null) {
return null;
}
return manifest.getAttributes(getName());
}
public long getTime() {
return baseEntry.getTime();
}
public void setTime(long time) {
baseEntry.setTime(time);
}
public long getSize() {
return baseEntry.getSize();
}
public void setSize(long size) {
baseEntry.setSize(size);
}
public long getCompressedSize() {
return baseEntry.getCompressedSize();
}
public void setCompressedSize(long csize) {
baseEntry.setCompressedSize(csize);
}
public long getCrc() {
return baseEntry.getCrc();
}
public void setCrc(long crc) {
baseEntry.setCrc(crc);
}
public int getMethod() {
return baseEntry.getMethod();
}
public void setMethod(int method) {
baseEntry.setMethod(method);
}
public byte[] getExtra() {
return baseEntry.getExtra();
}
public void setExtra(byte[] extra) {
baseEntry.setExtra(extra);
}
public String getComment() {
return baseEntry.getComment();
}
public void setComment(String comment) {
baseEntry.setComment(comment);
}
public boolean isDirectory() {
return baseEntry.isDirectory();
}
public String toString() {
return baseEntry.toString();
}
public int hashCode() {
return baseEntry.hashCode();
}
public Object clone() {
return new NestedJarEntry(getName(), baseEntry, manifest);
}
}
/**
* 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.
*/
/**
* @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
*/
class UnpackedJarEntry extends JarEntry {
private final File file;
private final Manifest manifest;
public UnpackedJarEntry(String name, File file, Manifest manifest) {
super(name);
this.file = file;
this.manifest = manifest;
}
public File getFile() {
return file;
}
public Attributes getAttributes() throws IOException {
if (manifest == null) {
return null;
}
return manifest.getAttributes(getName());
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param time ignored
* @throws UnsupportedOperationException always
*/
public void setTime(long time) throws UnsupportedOperationException {
throw new UnsupportedOperationException("Can not change the time of unpacked jar entry");
}
public long getTime() {
return file.lastModified();
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param size ignored
* @throws UnsupportedOperationException always
*/
public void setSize(long size) throws UnsupportedOperationException {
throw new UnsupportedOperationException("Can not change the size of unpacked jar entry");
}
public long getSize() {
if (file.isDirectory()) {
return -1;
} else {
return file.length();
}
}
/**
* An unpacked jar is not compressed, so this method returns getSize().
* @return getSize()
*/
public long getCompressedSize() {
return getSize();
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param compressedSize ignored
* @throws UnsupportedOperationException always
*/
public void setCompressedSize(long compressedSize) {
throw new UnsupportedOperationException("Can not change the compressed size of unpacked jar entry");
}
public long getCrc() {
return super.getCrc(); //To change body of overridden methods use File | Settings | File Templates.
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param crc ignored
* @throws UnsupportedOperationException always
*/
public void setCrc(long crc) {
throw new UnsupportedOperationException("Can not change the crc of unpacked jar entry");
}
public int getMethod() {
return ZipEntry.STORED;
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param method ignored
* @throws UnsupportedOperationException always
*/
public void setMethod(int method) {
throw new UnsupportedOperationException("Can not change the method of unpacked jar entry");
}
/**
* Always returns null.
* @return null
*/
public byte[] getExtra() {
return null;
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param extra ignored
* @throws UnsupportedOperationException always
*/
public void setExtra(byte[] extra) {
throw new UnsupportedOperationException("Can not change the extra data of unpacked jar entry");
}
/**
* Always returns null.
* @return null
*/
public String getComment() {
return null;
}
/**
* An unpacked jar is read only, so this method always throws an UnsupportedOperationException.
* @param comment ignored
* @throws UnsupportedOperationException always
*/
public void setComment(String comment) {
throw new UnsupportedOperationException("Can not change the comment of unpacked jar entry");
}
public boolean isDirectory() {
return file.isDirectory();
}
public Object clone() {
return new UnpackedJarEntry(getName(), file, manifest);
}
}
Jarring and unjarring files and directories.
/* Copyright 2004 The Apache Software Foundation
*
* Licensed 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.
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
/**
* Provides utility services for jarring and unjarring files and directories.
* Note that a given instance of JarHelper is not threadsafe with respect to
* multiple jar operations.
*
* @author Patrick Calahan <pcal@bea.ru>
*/
public class JarHelper {
// Constants
private static final int BUFFER_SIZE = 2156;
// Variables
private byte[] mBuffer = new byte[BUFFER_SIZE];
private int mByteCount = 0;
private boolean mVerbose = false;
private String mDestJarName = "";
// Constructor
/**
* Instantiates a new JarHelper.
*/
public JarHelper() {
}
// Public methods
/**
* Jars a given directory or single file into a JarOutputStream.
*/
public void jarDir(File dirOrFile2Jar, File destJar) throws IOException {
if (dirOrFile2Jar == null || destJar == null)
throw new IllegalArgumentException();
mDestJarName = destJar.getCanonicalPath();
FileOutputStream fout = new FileOutputStream(destJar);
JarOutputStream jout = new JarOutputStream(fout);
// jout.setLevel(0);
try {
jarDir(dirOrFile2Jar, jout, null);
} catch (IOException ioe) {
throw ioe;
} finally {
jout.close();
fout.close();
}
}
/**
* Unjars a given jar file into a given directory.
*/
public void unjarDir(File jarFile, File destDir) throws IOException {
BufferedOutputStream dest = null;
FileInputStream fis = new FileInputStream(jarFile);
unjar(fis, destDir);
}
/**
* Given an InputStream on a jar file, unjars the contents into the given
* directory.
*/
public void unjar(InputStream in, File destDir) throws IOException {
BufferedOutputStream dest = null;
JarInputStream jis = new JarInputStream(in);
JarEntry entry;
while ((entry = jis.getNextJarEntry()) != null) {
if (entry.isDirectory()) {
File dir = new File(destDir, entry.getName());
dir.mkdir();
if (entry.getTime() != -1)
dir.setLastModified(entry.getTime());
continue;
}
int count;
byte data[] = new byte[BUFFER_SIZE];
File destFile = new File(destDir, entry.getName());
if (mVerbose)
System.out.println("unjarring " + destFile + " from " + entry.getName());
FileOutputStream fos = new FileOutputStream(destFile);
dest = new BufferedOutputStream(fos, BUFFER_SIZE);
while ((count = jis.read(data, 0, BUFFER_SIZE)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
if (entry.getTime() != -1)
destFile.setLastModified(entry.getTime());
}
jis.close();
}
public void setVerbose(boolean b) {
mVerbose = b;
}
// Private methods
private static final char SEP = "/";
/**
* Recursively jars up the given path under the given directory.
*/
private void jarDir(File dirOrFile2jar, JarOutputStream jos, String path) throws IOException {
if (mVerbose)
System.out.println("checking " + dirOrFile2jar);
if (dirOrFile2jar.isDirectory()) {
String[] dirList = dirOrFile2jar.list();
String subPath = (path == null) ? "" : (path + dirOrFile2jar.getName() + SEP);
if (path != null) {
JarEntry je = new JarEntry(subPath);
je.setTime(dirOrFile2jar.lastModified());
jos.putNextEntry(je);
jos.flush();
jos.closeEntry();
}
for (int i = 0; i < dirList.length; i++) {
File f = new File(dirOrFile2jar, dirList[i]);
jarDir(f, jos, subPath);
}
} else {
if (dirOrFile2jar.getCanonicalPath().equals(mDestJarName)) {
if (mVerbose)
System.out.println("skipping " + dirOrFile2jar.getPath());
return;
}
if (mVerbose)
System.out.println("adding " + dirOrFile2jar.getPath());
FileInputStream fis = new FileInputStream(dirOrFile2jar);
try {
JarEntry entry = new JarEntry(path + dirOrFile2jar.getName());
entry.setTime(dirOrFile2jar.lastModified());
jos.putNextEntry(entry);
while ((mByteCount = fis.read(mBuffer)) != -1) {
jos.write(mBuffer, 0, mByteCount);
if (mVerbose)
System.out.println("wrote " + mByteCount + " bytes");
}
jos.flush();
jos.closeEntry();
} catch (IOException ioe) {
throw ioe;
} finally {
fis.close();
}
}
}
// for debugging
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.err.println("Usage: JarHelper jarname.jar directory");
return;
}
JarHelper jarHelper = new JarHelper();
jarHelper.mVerbose = true;
File destJar = new File(args[0]);
File dirOrFile2Jar = new File(args[1]);
jarHelper.jarDir(dirOrFile2Jar, destJar);
}
}
List files in a jar file
import java.io.*;
import java.util.*;
import java.util.jar.*;
public class JarDir {
public static void main (String args[])
throws IOException {
JarFile jarFile = new JarFile("yourJarFileName.jar");
Enumeration enum = jarFile.entries();
while (enum.hasMoreElements()) {
process(enum.nextElement());
}
}
private static void process(Object obj) {
JarEntry entry = (JarEntry)obj;
String name = entry.getName();
long size = entry.getSize();
long compressedSize = entry.getCompressedSize();
System.out.println(
name + "\t" + size + "\t" + compressedSize);
}
}
Listing the Entries of a JAR File Manifest
import java.util.Iterator;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
public class Main {
public static void main(String[] argv) throws Exception {
JarFile jarfile = new JarFile("filename.jar");
Manifest manifest = jarfile.getManifest();
Map map = manifest.getEntries();
for (Iterator it = map.keySet().iterator(); it.hasNext();) {
String entryName = (String) it.next();
Attributes attrs = (Attributes) map.get(entryName);
for (Iterator it2 = attrs.keySet().iterator(); it2.hasNext();) {
Attributes.Name attrName = (Attributes.Name) it2.next();
String attrValue = attrs.getValue(attrName);
}
}
}
}
Listing the Main Attributes in a JAR File Manifest
import java.util.Iterator;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
public class Main {
public static void main(String[] argv) throws Exception {
JarFile jarfile = new JarFile("filename.jar");
Manifest manifest = jarfile.getManifest();
Attributes attrs = (Attributes) manifest.getMainAttributes();
for (Iterator it = attrs.keySet().iterator(); it.hasNext();) {
Attributes.Name attrName = (Attributes.Name) it.next();
String attrValue = attrs.getValue(attrName);
}
}
}
Load an Icon from a jar
import javax.swing.Icon;
import javax.swing.UIManager;
public class Main {
public static void main(String[] argv) throws Exception {
}
public static Icon getIconForType(int iconType) {
switch (iconType) {
case 0:
return UIManager.getIcon("OptionPane.errorIcon");
case 1:
return UIManager.getIcon("OptionPane.informationIcon");
case 2:
return UIManager.getIcon("OptionPane.warningIcon");
case 3:
return UIManager.getIcon("OptionPane.questionIcon");
}
return null;
}
}
Load an Image from a JAR file
import java.awt.Image;
import java.awt.Toolkit;
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
String imgName = "image.jpg";
URL imgURL = Main.class.getResource(imgName);
Toolkit tk = Toolkit.getDefaultToolkit();
Image img = tk.getImage(imgURL);
}
}
Load resource from Jar file
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public final class JarResources {
Hashtable htSizes = new Hashtable();
Hashtable htJarContents = new Hashtable();
private String jarFileName;
public JarResources(String jarFileName) throws Exception {
this.jarFileName = jarFileName;
ZipFile zf = new ZipFile(jarFileName);
Enumeration e = zf.entries();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
}
zf.close();
// extract resources and put them into the hashtable.
FileInputStream fis = new FileInputStream(jarFileName);
BufferedInputStream bis = new BufferedInputStream(fis);
ZipInputStream zis = new ZipInputStream(bis);
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
}
int size = (int) ze.getSize();
// -1 means unknown size.
if (size == -1) {
size = ((Integer) htSizes.get(ze.getName())).intValue();
}
byte[] b = new byte[(int) size];
int rb = 0;
int chunk = 0;
while (((int) size - rb) > 0) {
chunk = zis.read(b, rb, (int) size - rb);
if (chunk == -1) {
break;
}
rb += chunk;
}
htJarContents.put(ze.getName(), b);
}
}
public byte[] getResource(String name) {
return (byte[]) htJarContents.get(name);
}
private String dumpZipEntry(ZipEntry ze) {
StringBuffer sb = new StringBuffer();
if (ze.isDirectory()) {
sb.append("d ");
} else {
sb.append("f ");
}
if (ze.getMethod() == ZipEntry.STORED) {
sb.append("stored ");
} else {
sb.append("defalted ");
}
sb.append(ze.getName());
sb.append("\t");
sb.append("" + ze.getSize());
if (ze.getMethod() == ZipEntry.DEFLATED) {
sb.append("/" + ze.getCompressedSize());
}
return (sb.toString());
}
public static void main(String[] args) throws Exception {
JarResources jr = new JarResources("a.jar");
byte[] buff = jr.getResource("b.gif");
}
}
Make Temp Jar
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Main {
static File makeTempJar(File moduleFile) throws IOException {
String prefix = moduleFile.getName();
if (prefix.endsWith(".jar") || prefix.endsWith(".JAR")) { // NOI18N
prefix = prefix.substring(0, prefix.length() - 4);
}
if (prefix.length() < 3) prefix += ".";
if (prefix.length() < 3) prefix += ".";
if (prefix.length() < 3) prefix += ".";
String suffix = "-test.jar"; // NOI18N
File physicalModuleFile = File.createTempFile(prefix, suffix);
physicalModuleFile.deleteOnExit();
InputStream is = new FileInputStream(moduleFile);
try {
OutputStream os = new FileOutputStream(physicalModuleFile);
try {
byte[] buf = new byte[4096];
int i;
while ((i = is.read(buf)) != -1) {
os.write(buf, 0, i);
}
} finally {
os.close();
}
} finally {
is.close();
}
return physicalModuleFile;
}
}
Manifest Writer
/*BEGIN_COPYRIGHT_BLOCK
*
* Copyright (c) 2001-2008, JavaPLT group at Rice University (drjava@rice.edu)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is Open Source Initiative approved Open Source Software.
* Open Source Initative Approved is a trademark of the Open Source Initiative.
*
* This file is part of DrJava. Download the current version of this project
* from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
*
* END_COPYRIGHT_BLOCK*/
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
import java.io.*;
/** Writes manifest objects. Useful for creating Manifest files without writing them to files. */
public class ManifestWriter {
private List<String> _classPaths;
private String _mainClass;
private String _rawManifest;
public static final Manifest DEFAULT = new ManifestWriter().getManifest();
/** Create a new manifest file */
public ManifestWriter() {
_classPaths = new LinkedList<String>();
_mainClass = null;
_rawManifest = null;
}
/** Add a class path to the Manifest
* @param path the path to be added
*/
public void addClassPath(String path) {
_classPaths.add(_classPaths.size(), path);
}
/** Set the main class of the Manifest
* @param mainClass
*/
public void setMainClass(String mainClass) {
_mainClass = mainClass;
_rawManifest = null;
}
public void setManifestContents(String rawManifest) {
_rawManifest = rawManifest;
_mainClass = null;
}
/** Get an input stream to the contents of the manifest file
* @return an InputStream whose contents are the contents of the Manifest file
*/
protected InputStream getInputStream() {
// NOTE: All significant lines in the manifest MUST end in the end of line character
final StringBuilder sbuf = new StringBuilder();
sbuf.append(Attributes.Name.MANIFEST_VERSION.toString());
sbuf.append(": 1.0" + "\n");
if( !_classPaths.isEmpty() ) {
Iterator<String> iter = _classPaths.iterator();
sbuf.append(Attributes.Name.CLASS_PATH.toString());
sbuf.append(":");
while (iter.hasNext()) {
sbuf.append(" ");
sbuf.append(iter.next());
}
sbuf.append("\n");
}
if( _mainClass != null ) {
sbuf.append(Attributes.Name.MAIN_CLASS.toString());
sbuf.append(": ");
sbuf.append(_mainClass);
sbuf.append("\n");
}
if(_rawManifest != null) {
sbuf.append(_rawManifest);
if(!_rawManifest.endsWith("\n"))
sbuf.append("\n");
}
try { return new ByteArrayInputStream(sbuf.toString().getBytes("UTF-8")); }
catch (UnsupportedEncodingException e) { throw new RuntimeException(e); }
}
/** Get the Manifest object that this object created.
* @return the Manifest that this builder created
*/
public Manifest getManifest() {
try {
Manifest m = new Manifest();
m.read(getInputStream());
return m;
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Reading a text file from a jar file without unzipping
import java.io.*;
import java.util.jar.*;
public class JarRead {
public static void main (String args[])
throws IOException {
if (args.length != 2) {
System.out.println(
"Please provide a JAR filename and file to read");
System.exit(-1);
}
JarFile jarFile = new JarFile(args[0]);
JarEntry entry = jarFile.getJarEntry(args[1]);
InputStream input = jarFile.getInputStream(entry);
process(input);
jarFile.close();
}
private static void process(InputStream input)
throws IOException {
InputStreamReader isr =
new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
}
Retreive Binary File From Jar
/*
* Copyright 2006 - 2008 Georges Stephan
*
* Licensed 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.
*/
import java.util.logging.*;
import java.io.*;
/**
*
* @author Georges Stephan
*/
public class Util {
private static Logger logger = Logger.getLogger(Util.class.getName());
public static String validateString(String aString) {
if(aString==null) return("");
aString=aString.replace("\"", " ");
aString=aString.trim();
return(aString);
}
public static String removeNonDigits(String aString) {
StringBuffer newString = new StringBuffer();
for(int x=0;x<aString.length();x++) {
if(Character.isDigit(aString.charAt(x))) newString.append(aString.charAt(x));
}
return(newString.toString());
}
public static void createHome() throws Exception {
File ch = new File(System.getProperty("user.home")+File.separator+".dataform");
if(!ch.exists()) {
if(!ch.mkdir()) throw new Exception("Failed to create the dataform configuration directory");
}
}
public static String getHomeDir() {
return(System.getProperty("user.home")+File.separator+".dataform"+File.separator);
}
public static boolean retreiveTextFileFromJar(String resourceName,String targetDirectory) throws Exception {
boolean found=false;
if(resourceName!=null) {
InputStream is = Util.class.getResourceAsStream(resourceName);
if(is==null) logger.log(Level.WARNING,"The resource ""+resourceName+"" was not found.");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
String lineSep = System.getProperty("line.separator");
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append(lineSep);
}
is.close();
if(sb!=null) {
if(sb.length()>0) {
FileWriter temp = new FileWriter(targetDirectory+File.separator+resourceName);
temp.write(sb.toString());
temp.close();
found=true;
}
}
}
return(found);
}
public static boolean retreiveBinaryFileFromJar(String resourceName,String targetDirectory,Object resource) throws Exception {
boolean found=false;
if(resourceName!=null) {
InputStream is = resource.getClass().getResourceAsStream(resourceName);
if(is==null) throw new Exception ("Resource "+resourceName+" was not found.");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
FileOutputStream fos = new FileOutputStream(targetDirectory+File.separator+resourceName.substring(resourceName.lastIndexOf("/"),resourceName.length()));
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
fos.flush();
br.close();
is.close();
found=true;
} else {
found=false;
}
return found;
}
}
Retreive Text File From Jar
/*
* Copyright 2006 - 2008 Georges Stephan
*
* Licensed 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.
*/
import java.util.logging.*;
import java.io.*;
/**
*
* @author Georges Stephan
*/
public class Util {
private static Logger logger = Logger.getLogger(Util.class.getName());
public static String validateString(String aString) {
if(aString==null) return("");
aString=aString.replace("\"", " ");
aString=aString.trim();
return(aString);
}
public static String removeNonDigits(String aString) {
StringBuffer newString = new StringBuffer();
for(int x=0;x<aString.length();x++) {
if(Character.isDigit(aString.charAt(x))) newString.append(aString.charAt(x));
}
return(newString.toString());
}
public static void createHome() throws Exception {
File ch = new File(System.getProperty("user.home")+File.separator+".dataform");
if(!ch.exists()) {
if(!ch.mkdir()) throw new Exception("Failed to create the dataform configuration directory");
}
}
public static String getHomeDir() {
return(System.getProperty("user.home")+File.separator+".dataform"+File.separator);
}
public static boolean retreiveTextFileFromJar(String resourceName,String targetDirectory) throws Exception {
boolean found=false;
if(resourceName!=null) {
InputStream is = Util.class.getResourceAsStream(resourceName);
if(is==null) logger.log(Level.WARNING,"The resource ""+resourceName+"" was not found.");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
String lineSep = System.getProperty("line.separator");
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append(lineSep);
}
is.close();
if(sb!=null) {
if(sb.length()>0) {
FileWriter temp = new FileWriter(targetDirectory+File.separator+resourceName);
temp.write(sb.toString());
temp.close();
found=true;
}
}
}
return(found);
}
public static boolean retreiveBinaryFileFromJar(String resourceName,String targetDirectory,Object resource) throws Exception {
boolean found=false;
if(resourceName!=null) {
InputStream is = resource.getClass().getResourceAsStream(resourceName);
if(is==null) throw new Exception ("Resource "+resourceName+" was not found.");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
FileOutputStream fos = new FileOutputStream(targetDirectory+File.separator+resourceName.substring(resourceName.lastIndexOf("/"),resourceName.length()));
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
fos.flush();
br.close();
is.close();
found=true;
} else {
found=false;
}
return found;
}
}
Retrieves the manifest from a JAR file and writes the manifest contents to a file.
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
public class Main {
public static void main(String[] argv) throws Exception {
JarFile jarfile = new JarFile("filename.jar");
Manifest manifest = jarfile.getManifest();
OutputStream fos = new FileOutputStream("manifest");
jarfile.getManifest().write(fos);
fos.close();
}
}
Search all jar and zip files in the current directory for a given class file
/*
* The QueryForm License, Version 1.1
*
* Copyright (c) 1998 - 2003 David F. Glasser. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by
* David F. Glasser."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "QueryForm" and "David F. Glasser" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact dglasser@pobox.ru.
*
* 5. Products derived from this software may not be called "QueryForm",
* nor may "QueryForm" appear in their name, without prior written
* permission of David F. Glasser.
*
* THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL DAVID F. GLASSER, THE APACHE SOFTWARE
* FOUNDATION OR ITS CONTRIBUTORS, OR ANY AUTHORS OR DISTRIBUTORS
* OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/).
*
*
*
* $Source: /cvsroot/qform/qform/src/org/glasser/util/JarSearcher.java,v $
* $Revision: 1.1 $
* $Author: dglasser $
* $Date: 2003/01/25 23:17:02 $
*
* --------------------------------------------------------------------
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.io.*;
/**
* This program will search all jar and zip files in the current directory for
* a given class file.
*
* @author Dave Glasser
*/
public class JarSearcher {
/**
* Returns true if the jar or zip file at jarFilePath contains (with the internal
* path) the file named by classFilePath.
*/
public static boolean searchJarFile(String jarFilePath, String classFilePath) {
return searchJarFile( new File(jarFilePath), classFilePath);
}
public static boolean searchJarFile(File file, String classFilePath) {
try {
if(!file.exists()) return false;
ZipFile jarFile = new ZipFile(file);
if(jarFile.getEntry(classFilePath) != null) {
jarFile.close();
return true;
}
else {
jarFile.close();
return false;
}
}
catch(IOException ex) {
System.out.println(ex.toString());
return false;
}
}
static class ArchiveFilter implements FileFilter {
public boolean accept(File pathName) {
String upcase = pathName.getName().toUpperCase();
if(upcase.endsWith(".ZIP") || upcase.endsWith(".JAR")) return true;
return false;
}
}
public static void main (String[] args) {
if(args.length == 0) {
System.out.println("usage: java ClassFinder <class name>\n\n"
+ "example: java ClassFinder java.lang.String\n");
System.exit(0);
}
File cwd = new File(".");
File[] archives = cwd.listFiles(new ArchiveFilter());
String classFileName = args[0].replace(".", "/");
if(classFileName.endsWith(".class") == false) {
classFileName += ".class";
}
System.out.println("Searching for " + classFileName + " ...");
for(int j=0; j<archives.length; j++) {
// System.out.println("Searching " + archives[j].getName());
if(searchJarFile(archives[j], classFileName)) {
System.out.println("FOUND IN " + archives[j].getName());
}
}
}
}
Search class in class path and Jar files
/*
* $Id: ClassSearchUtils.java,v 1.1 2009/03/01 12:01:11 rah003 Exp $
*
* Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
import java.awt.HeadlessException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;
public class ClassSearchUtils {
private static final Logger log = Logger.getAnonymousLogger();
/**
* Classloader to be used to obtain resources from file system.
*/
private ClassLoader classloader;
/**
* List of the resource found in the classpath.
*/
private ArrayList list;
/**
* Extension of the resource to be found in the classpath.
*/
private String extension;
private String prefix;
/**
* Search for the resource with the extension in the classpath. Method
* self-instantiate factory for every call to ensure thread safety.
* @param extension Mandatory extension of the resource. If all resources
* are required extension should be empty string. Null extension is not
* allowed and will cause method to fail.
* @return List of all resources with specified extension.
*/
public static List<Class<?>> searchClassPath(String prefix) {
return searchClassPath(prefix, ".class");
}
/**
* Search for the resource with the extension in the classpath. Method
* self-instantiate factory for every call to ensure thread safety.
* @param extension Mandatory extension of the resource. If all resources
* are required extension should be empty string. Null extension is not
* allowed and will cause method to fail.
* @return List of all resources with specified extension.
*/
public static List searchClassPath(String prefix, String extension) {
ClassSearchUtils factory = new ClassSearchUtils();
factory.prefix = prefix;
return factory.find(extension);
}
/**
* Search for the resource with the extension in the classpath.
* @param extension Mandatory extension of the resource. If all resources
* are required extension should be empty string. Null extension is not
* allowed and will cause method to fail.
* @return List of all resources with specified extension.
*/
private List<Class<?>> find(String extension) {
this.extension = extension;
this.list = new ArrayList();
this.classloader = this.getClass().getClassLoader();
String classpath = System.getProperty("java.class.path");
try {
Method method =
this.classloader.getClass().getMethod("getClassPath", (Class<?>) null);
if (method != null) {
classpath = (String) method.invoke(this.classloader, (Object) null);
}
} catch (Exception e) {
// ignore
}
if (classpath == null) {
classpath = System.getProperty("java.class.path");
}
StringTokenizer tokenizer =
new StringTokenizer(classpath, File.pathSeparator);
String token;
File dir;
String name;
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
dir = new File(token);
if (dir.isDirectory()) {
lookInDirectory("", dir);
}
if (dir.isFile()) {
name = dir.getName().toLowerCase();
if (name.endsWith(".zip") || name.endsWith(".jar")) {
this.lookInArchive(dir);
}
}
}
return this.list;
}
/**
* @param name Name of to parent directories in java class notation (dot
* separator)
* @param dir Directory to be searched for classes.
*/
private void lookInDirectory(String name, File dir) {
log.fine( "Looking in directory [" + dir.getName() + "].");
File[] files = dir.listFiles();
File file;
String fileName;
final int size = files.length;
for (int i = 0; i < size; i++) {
file = files[i];
fileName = file.getName();
if (file.isFile()
&& fileName.toLowerCase().endsWith(this.extension)) {
try {
if (this.extension.equalsIgnoreCase(".class")) {
fileName = fileName.substring(0, fileName.length() - 6);
// filter ignored resources
if (!(name + fileName).startsWith(this.prefix)) {
continue;
}
log.fine(
"Found class: [" + name + fileName + "].");
this.list.add(Class.forName(name + fileName));
} else {
this.list.add(
this.classloader.getResource(
name.replace(".", File.separatorChar)
+ fileName));
}
} catch (ClassNotFoundException e) {
// ignore
} catch (NoClassDefFoundError e) {
//ignore too
} catch (ExceptionInInitializerError e) {
if (e.getCause() instanceof HeadlessException) {
// running in headless env ... ignore
} else {
throw e;
}
}
}
// search recursively.
// I don"t like that but we will see how it will work.
if (file.isDirectory()) {
lookInDirectory(name + fileName + ".", file);
}
}
}
/**
* Search archive files for required resource.
* @param archive Jar or zip to be searched for classes or other resources.
*/
private void lookInArchive(File archive) {
log.fine(
"Looking in archive ["
+ archive.getName()
+ "] for extension ["
+ this.extension
+ "].");
JarFile jarFile = null;
try {
jarFile = new JarFile(archive);
} catch (IOException e) {
log.warning(
"Non fatal error. Unable to read jar item.");
return;
}
Enumeration entries = jarFile.entries();
JarEntry entry;
String entryName;
while (entries.hasMoreElements()) {
entry = (JarEntry) entries.nextElement();
entryName = entry.getName();
if (entryName.toLowerCase().endsWith(this.extension)) {
try {
if (this.extension.equalsIgnoreCase(".class")) {
// convert name into java classloader notation
entryName =
entryName.substring(0, entryName.length() - 6);
entryName = entryName.replace("/", ".");
// filter ignored resources
if (!entryName.startsWith(this.prefix)) {
continue;
}
log.fine(
"Found class: [" + entryName + "]. ");
this.list.add(Class.forName(entryName));
} else {
this.list.add(this.classloader.getResource(entryName));
log.fine(
"Found appropriate resource with name ["
+ entryName
+ "]. Resource instance:"
+ this.classloader.getResource(entryName));
}
} catch (Throwable e) {
// ignore
log.warning(
"Unable to load resource ["
+ entryName
+ "] form file ["
+ archive.getAbsolutePath()
+ "].");
}
}
}
}
}
Sign jar with the certificate named alias in the keystore
jarsigner -keystore .keystore -storepass password myjar.jar alias
Some utility classes for manipulating JAR files
/*
*
*
* Copyright 2005 Vincent Massol.
*
* Licensed 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.
*
*
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
/**
* Some utility classes for manipulating JAR files.
*
* @version $Id $
*/
public final class JarUtils
{
/**
* Create a jar file from a particular directory.
*
* @param root in the root directory
* @param directory in the directory we are adding
* @param jarStream the jar stream to be added to
* @throws IOException on IOException
*/
protected void createJarFromDirectory(File root,
File directory,
JarOutputStream jarStream)
throws IOException
{
byte[] buffer = new byte[40960];
int bytesRead;
File[] filesToAdd = directory.listFiles();
for (int i = 0; i < filesToAdd.length; i++)
{
File fileToAdd = filesToAdd[i];
if (fileToAdd.isDirectory())
{
createJarFromDirectory(root, fileToAdd, jarStream);
}
else
{
FileInputStream addFile = new FileInputStream(fileToAdd);
try
{
// Create a jar entry and add it to the temp jar.
String entryName = fileToAdd.getPath().substring(root.getPath().length() + 1);
// If we leave these entries as "\"s, then the resulting zip file won"t be
// expandable on Unix operating systems like OSX, because it is possible to
// have filenames with \s in them - so it"s impossible to determine that this
// is actually a directory.
entryName = entryName.replace("\\", "/");
JarEntry entry = new JarEntry(entryName);
jarStream.putNextEntry(entry);
// Read the file and write it to the jar.
while ((bytesRead = addFile.read(buffer)) != -1)
{
jarStream.write(buffer, 0, bytesRead);
}
jarStream.closeEntry();
}
finally
{
addFile.close();
}
}
}
}
/**
* Create a JAR file from a directory, recursing through children.
*
* @param directory in directory source
* @param outputJar in file to output the jar data to
* @return out File that was generated
* @throws IOException when there is an I/O exception
*/
public File createJarFromDirectory(String directory, File outputJar)
throws IOException
{
JarOutputStream jarStream = null;
try
{
if (!outputJar.getParentFile().exists())
{
outputJar.getParentFile().mkdirs();
}
jarStream = new JarOutputStream(new FileOutputStream(outputJar));
File dir = new File(directory);
createJarFromDirectory(dir, dir, jarStream);
}
finally
{
if (jarStream != null)
{
jarStream.close();
}
}
return outputJar;
}
}
Unjar a file
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
/** A utility class for dealing with Jar files.
@author Scott.Stark@jboss.org
@version $Revision: 2787 $
*/
public final class JarUtils
{
/**
* Hide the constructor
*/
private JarUtils()
{
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream.</P>
*
* <P>This is a shortcut for<br>
* <code>jar(out, new File[] { src }, null, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @throws IOException
*/
public static void jar(OutputStream out, File src) throws IOException
{
jar(out, new File[] { src }, null, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream.</P>
*
* <P>This is a shortcut for<br>
* <code>jar(out, src, null, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src) throws IOException
{
jar(out, src, null, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream. Directories are processed recursively, applying the
* specified filter if it exists.
*
* <P>This is a shortcut for<br>
* <code>jar(out, src, filter, null, null);</code></P>
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @param filter The filter to use while processing directories. Only
* those files matching will be included in the jar archive. If
* null, then all files are included.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src, FileFilter filter)
throws IOException
{
jar(out, src, filter, null, null);
}
/**
* <P>This function will create a Jar archive containing the src
* file/directory. The archive will be written to the specified
* OutputStream. Directories are processed recursively, applying the
* specified filter if it exists.
*
* @param out The output stream to which the generated Jar archive is
* written.
* @param src The file or directory to jar up. Directories will be
* processed recursively.
* @param filter The filter to use while processing directories. Only
* those files matching will be included in the jar archive. If
* null, then all files are included.
* @param prefix The name of an arbitrary directory that will precede all
* entries in the jar archive. If null, then no prefix will be
* used.
* @param man The manifest to use for the Jar archive. If null, then no
* manifest will be included.
* @throws IOException
*/
public static void jar(OutputStream out, File[] src, FileFilter filter,
String prefix, Manifest man) throws IOException
{
for (int i = 0; i < src.length; i++)
{
if (!src[i].exists())
{
throw new FileNotFoundException(src.toString());
}
}
JarOutputStream jout;
if (man == null)
{
jout = new JarOutputStream(out);
}
else
{
jout = new JarOutputStream(out, man);
}
if (prefix != null && prefix.length() > 0 && !prefix.equals("/"))
{
// strip leading "/"
if (prefix.charAt(0) == "/")
{
prefix = prefix.substring(1);
}
// ensure trailing "/"
if (prefix.charAt(prefix.length() - 1) != "/")
{
prefix = prefix + "/";
}
}
else
{
prefix = "";
}
JarInfo info = new JarInfo(jout, filter);
for (int i = 0; i < src.length; i++)
{
jar(src[i], prefix, info);
}
jout.close();
}
/**
* This simple convenience class is used by the jar method to reduce the
* number of arguments needed. It holds all non-changing attributes
* needed for the recursive jar method.
*/
private static class JarInfo
{
public JarOutputStream out;
public FileFilter filter;
public byte[] buffer;
public JarInfo(JarOutputStream out, FileFilter filter)
{
this.out = out;
this.filter = filter;
buffer = new byte[1024];
}
}
/**
* This recursive method writes all matching files and directories to
* the jar output stream.
*/
private static void jar(File src, String prefix, JarInfo info)
throws IOException
{
JarOutputStream jout = info.out;
if (src.isDirectory())
{
// create / init the zip entry
prefix = prefix + src.getName() + "/";
ZipEntry entry = new ZipEntry(prefix);
entry.setTime(src.lastModified());
entry.setMethod(JarOutputStream.STORED);
entry.setSize(0L);
entry.setCrc(0L);
jout.putNextEntry(entry);
jout.closeEntry();
// process the sub-directories
File[] files = src.listFiles(info.filter);
for (int i = 0; i < files.length; i++)
{
jar(files[i], prefix, info);
}
}
else if (src.isFile())
{
// get the required info objects
byte[] buffer = info.buffer;
// create / init the zip entry
ZipEntry entry = new ZipEntry(prefix + src.getName());
entry.setTime(src.lastModified());
jout.putNextEntry(entry);
// dump the file
FileInputStream in = new FileInputStream(src);
int len;
while ((len = in.read(buffer, 0, buffer.length)) != -1)
{
jout.write(buffer, 0, len);
}
in.close();
jout.closeEntry();
}
}
public static void unjar(InputStream in, File dest) throws IOException
{
if (!dest.exists())
{
dest.mkdirs();
}
if (!dest.isDirectory())
{
throw new IOException("Destination must be a directory.");
}
JarInputStream jin = new JarInputStream(in);
byte[] buffer = new byte[1024];
ZipEntry entry = jin.getNextEntry();
while (entry != null)
{
String fileName = entry.getName();
if (fileName.charAt(fileName.length() - 1) == "/")
{
fileName = fileName.substring(0, fileName.length() - 1);
}
if (fileName.charAt(0) == "/")
{
fileName = fileName.substring(1);
}
if (File.separatorChar != "/")
{
fileName = fileName.replace("/", File.separatorChar);
}
File file = new File(dest, fileName);
if (entry.isDirectory())
{
// make sure the directory exists
file.mkdirs();
jin.closeEntry();
}
else
{
// make sure the directory exists
File parent = file.getParentFile();
if (parent != null && !parent.exists())
{
parent.mkdirs();
}
// dump the file
OutputStream out = new FileOutputStream(file);
int len = 0;
while ((len = jin.read(buffer, 0, buffer.length)) != -1)
{
out.write(buffer, 0, len);
}
out.flush();
out.close();
jin.closeEntry();
file.setLastModified(entry.getTime());
}
entry = jin.getNextEntry();
}
/* Explicity write out the META-INF/MANIFEST.MF so that any headers such
as the Class-Path are see for the unpackaged jar
*/
Manifest mf = jin.getManifest();
if (mf != null)
{
File file = new File(dest, "META-INF/MANIFEST.MF");
File parent = file.getParentFile();
if( parent.exists() == false )
{
parent.mkdirs();
}
OutputStream out = new FileOutputStream(file);
mf.write(out);
out.flush();
out.close();
}
jin.close();
}
/** Given a URL check if its a jar url(jar:<url>!/archive) and if it is,
extract the archive entry into the given dest directory and return a file
URL to its location. If jarURL is not a jar url then it is simply returned
as the URL for the jar.
@param jarURL the URL to validate and extract the referenced entry if its
a jar protocol URL
@param dest the directory into which the nested jar will be extracted.
@return the file: URL for the jar referenced by the jarURL parameter.
* @throws IOException
*/
public static URL extractNestedJar(URL jarURL, File dest)
throws IOException
{
// This may not be a jar URL so validate the protocol
if( jarURL.getProtocol().equals("jar") == false )
return jarURL;
String destPath = dest.getAbsolutePath();
URLConnection urlConn = jarURL.openConnection();
JarURLConnection jarConn = (JarURLConnection) urlConn;
// Extract the archive to dest/jarName-contents/archive
String parentArchiveName = jarConn.getJarFile().getName();
// Find the longest common prefix between destPath and parentArchiveName
int length = Math.min(destPath.length(), parentArchiveName.length());
int n = 0;
while( n < length )
{
char a = destPath.charAt(n);
char b = parentArchiveName.charAt(n);
if( a != b )
break;
n ++;
}
// Remove any common prefix from parentArchiveName
parentArchiveName = parentArchiveName.substring(n);
File archiveDir = new File(dest, parentArchiveName+"-contents");
if( archiveDir.exists() == false && archiveDir.mkdirs() == false )
throw new IOException("Failed to create contents directory for archive, path="+archiveDir.getAbsolutePath());
String archiveName = jarConn.getEntryName();
File archiveFile = new File(archiveDir, archiveName);
File archiveParentDir = archiveFile.getParentFile();
if( archiveParentDir.exists() == false && archiveParentDir.mkdirs() == false )
throw new IOException("Failed to create parent directory for archive, path="+archiveParentDir.getAbsolutePath());
InputStream archiveIS = jarConn.getInputStream();
FileOutputStream fos = new FileOutputStream(archiveFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[4096];
int read;
while( (read = archiveIS.read(buffer)) > 0 )
{
bos.write(buffer, 0, read);
}
archiveIS.close();
bos.close();
// Return the file url to the extracted jar
return archiveFile.toURL();
}
public static void main(String[] args) throws Exception
{
if (args.length == 0)
{
System.out.println("usage: <x or c> <jar-archive> <files...>");
System.exit(0);
}
if (args[0].equals("x"))
{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(args[1]));
File dest = new File(args[2]);
unjar(in, dest);
}
else if (args[0].equals("c"))
{
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(args[1]));
File[] src = new File[args.length - 2];
for (int i = 0; i < src.length; i++)
{
src[i] = new File(args[2 + i]);
}
jar(out, src);
}
else
{
System.out.println("Need x or c as first argument");
}
}
}
When no entry is specified on the URL, the entry name is null
import java.net.JarURLConnection;
import java.net.URL;
public class Main {
public static void main(String[] argv) throws Exception {
URL url = new URL("jar:file:/c://my.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
String entryName = conn.getEntryName(); // null
}
}
Zip jar Imploder
/*******************************************************************************
* Copyright (c) 2004, 2008 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
*******************************************************************************/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author Barry Feigenbaum
*/
public class ZipImploder {
protected int dirCount, fileCount;
/**
* @return Returns the dirCount.
*/
public int getDirCount() {
return dirCount;
}
/**
* @return Returns the fileCount.
*/
public int getFileCount() {
return fileCount;
}
/**
* create a new imploder with no verbosity
*
*/
public ZipImploder() {
this(false);
}
/**
* create a new imploder with the specified verbosity state
*
* @param verbose -
* verbosity state
*/
public ZipImploder(boolean verbose) {
setVerbose(verbose);
}
protected boolean verbose;
/**
* get the verbose mode
*
* @return verbosity mode
*/
public boolean getVerbose() {
return verbose;
}
/**
* set the verbosity mode
*
* @param f
* verbosity state
*/
public void setVerbose(boolean f) {
verbose = f;
}
protected String baseDir;
/**
* @return Returns the baseDir.
*/
public String getBaseDir() {
return baseDir;
}
/**
* @param baseDir
* The baseDir to set.
* @throws IOException
*/
public void setBaseDir(String baseDir) throws IOException {
if (baseDir != null) {
baseDir = new File(baseDir).getCanonicalPath();
baseDir = baseDir.replace("\\", "/");
}
this.baseDir = baseDir;
}
protected Manifest manifest;
/**
* @return Returns the manifest
*/
public Manifest getManifest() {
return manifest;
}
/**
* @param manifest
* The manifest to set.
*/
public void setManifest(Manifest manifest) {
this.manifest = manifest;
}
protected boolean includeDirs;
/**
* returns whether or not path information is included in .zip
*
* @return <code>true</code> if path information is included,
* <code>false</code> otherwise
*/
public boolean getIncludeDirs() {
return includeDirs;
}
/**
* set whether or not path information is included in .zip files
*
* @param includeDirs
* include path inforamtion in .zip file
*/
public void setIncludeDirs(boolean includeDirs) {
this.includeDirs = includeDirs;
}
/**
* implode source directory into .jar/.zip file
*
* @param zipName
* name of target file
* @param jarName
* name of target file
* @param sourceDir
* source directory name
* @exception IOException
* error creating a target file
*/
public void process(String zipName, String jarName, String sourceDir) throws IOException {
dirCount = 0;
fileCount = 0;
if (zipName != null) {
processZip(zipName, sourceDir);
}
if (jarName != null) {
processJar(jarName, sourceDir);
}
}
/**
* Implode target JAR file from a source directory
*
* @param jarName
* name of target file
* @param sourceDir
* source directory name
* @exception IOException
* error creating a target file
*/
public void processJar(String jarName, String sourceDir) throws IOException {
processJar(jarName, sourceDir, null);
}
/**
* Implode target JAR file from a source directory
*
* @param jarName
* name of target file
* @param sourceDir
* source directory name (
* @param comment
* @exception IOException
* error creating a target file
*/
public void processJar(String jarName, String sourceDir, String comment) throws IOException {
processJar(jarName, sourceDir, comment, -1, -1);
}
/**
* Implode target JAR file from a source directory
*
* @param jarName -
* name of target .jar
* @param sourceDir -
* source directory
* @param comment -
* comment for .jar file
* @param method
* @param level
* @throws IOException
*/
public void processJar(String jarName, String sourceDir, String comment, int method, int level)
throws IOException {
String dest = setup(jarName, sourceDir);
Manifest man = getManifest();
JarOutputStream jos = man != null ? new JarOutputStream(new BufferedOutputStream(
new FileOutputStream(dest)), man) : new JarOutputStream(new BufferedOutputStream(
new FileOutputStream(dest)));
configure(jos, comment, method, level);
process(jos, new File(sourceDir));
}
/**
* Implode target JAR file from a source directory
*
* @param zipName
* name of target file
* @param sourceDir
* source directory name (
* @exception IOException
* error creating a target file
*/
public void processZip(String zipName, String sourceDir) throws IOException {
processZip(zipName, sourceDir, null);
}
/**
* Implode target zip file from a source directory
*
* @param zipName
* @param sourceDir
* @param comment
* @throws IOException
*/
public void processZip(String zipName, String sourceDir, String comment) throws IOException {
processZip(zipName, sourceDir, comment, -1, -1);
}
/**
* Implode target zip file from a source directory
*
* @param zipName
* @param sourceDir
* @param comment
* @param method
* @param level
* @throws IOException
*/
public void processZip(String zipName, String sourceDir, String comment, int method, int level)
throws IOException {
String dest = setup(zipName, sourceDir);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
configure(zos, comment, method, level);
process(zos, new File(sourceDir));
}
protected void configure(ZipOutputStream zos, String comment, int method, int level) {
if (comment != null) {
zos.setComment(comment);
}
if (method >= 0) {
zos.setMethod(method);
}
if (level >= 0) {
zos.setLevel(level);
}
}
protected String setup(String zipName, String sourceDir) throws IOException {
File dir = new File(sourceDir);
if (!dir.exists() && !dir.isDirectory()) {
throw new IOException("source must exist and be a directory: " + dir);
}
String source = dir.getCanonicalPath();
String dest = new File(zipName).getCanonicalPath();
return dest;
}
protected void process(ZipOutputStream zos, File dir) throws IOException {
try {
processDir(zos, dir);
} finally {
zos.close();
}
}
protected String removeDrive(String path) {
return path.length() >= 2 && path.charAt(1) == ":" ? path.substring(2) : path;
}
protected String removeLead(String path) {
if (baseDir != null && path.startsWith(baseDir)) {
path = path.substring(baseDir.length());
if (path.length() >= 1) {
if (path.charAt(0) == "/" || path.charAt(0) == "\\") {
path = path.substring(1); // drop leading /
}
}
}
return path;
}
public void processDir(ZipOutputStream zos, File dir) throws IOException {
String path = dir.getCanonicalPath();
path = path.replace("\\", "/");
if (includeDirs) {
if (baseDir == null || path.length() > baseDir.length()) {
String xpath = removeDrive(removeLead(path));
if (xpath.length() > 0) {
xpath += "/";
ZipEntry ze = new ZipEntry(xpath);
zos.putNextEntry(ze);
}
}
}
dirCount++;
String[] files = dir.list();
for (int i = 0; i < files.length; i++) {
String file = files[i];
File f = new File(dir, file);
if (f.isDirectory()) {
processDir(zos, f);
} else {
processFile(zos, f);
}
}
}
/**
* process a single file for a .zip file
*
* @param zos
* @param f
* @throws IOException
*/
public void processFile(ZipOutputStream zos, File f) throws IOException {
String path = f.getCanonicalPath();
path = path.replace("\\", "/");
String xpath = removeDrive(removeLead(path));
ZipEntry ze = new ZipEntry(xpath);
ze.setTime(f.lastModified());
ze.setSize(f.length());
zos.putNextEntry(ze);
fileCount++;
try {
copyFileEntry(zos, f);
} finally {
zos.closeEntry();
}
}
protected void copyFileEntry(ZipOutputStream zos, File f) throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
try {
copyFileEntry(zos, dis);
} finally {
try {
dis.close();
} catch (IOException ioe) {
}
}
}
protected void copyFileEntry(ZipOutputStream zos, DataInputStream dis) throws IOException {
byte[] bytes = readAllBytes(dis);
zos.write(bytes, 0, bytes.length);
}
// *** below may be slow for large files ***
/** Read all the bytes in a stream */
protected byte[] readAllBytes(DataInputStream is) throws IOException {
byte[] bytes = new byte[0];
for (int len = is.available(); len > 0; len = is.available()) {
byte[] xbytes = new byte[len];
int count = is.read(xbytes);
if (count > 0) {
byte[] nbytes = new byte[bytes.length + count];
System.arraycopy(bytes, 0, nbytes, 0, bytes.length);
System.arraycopy(xbytes, 0, nbytes, bytes.length, count);
bytes = nbytes;
}
}
return bytes;
}
protected void print(String s) {
System.out.print(s);
}
/** Print command help text. */
public static void printHelp() {
System.out.println();
System.out.println("Usage: java " + ZipImploder.class.getName());
System.out.println(" (-jar <jarName> {-manifest <manfile>} | -zip <zipName>)");
System.out.println(" -dir <sourceDir> {-lead <leadDir>} {-doDirs} {-verbose}");
System.out.println("Where:");
System.out.println(" <jarName> path to target jar");
System.out.println(" <zipName> path to target zip");
System.out.println(" <manfile> path to manifest file");
System.out.println(" <sourceDir> path to source directory; must exist");
System.out
.println(" <leadDir> partial lead path to remove from stored entries; default: <sourceDir>");
System.out.println(" <noDirs> skip output of directory entries");
System.out.println(" <verbose> output progress information");
System.out.println("Note: switch case or order is not important");
}
protected static void reportError(String msg) {
System.err.println(msg);
// printHelp();
System.exit(1);
}
/**
* Main command line entry point.
*
* @param args
*/
public static void main(final String[] args) {
if (args.length == 0) {
printHelp();
System.exit(0);
}
String zipName = null;
String jarName = null;
String manName = null;
String sourceDir = null;
String leadDir = null;
boolean jarActive = false, manActive = false, zipActive = false, sourceDirActive = false, leadDirActive = false;
boolean verbose = false;
boolean noDirs = false;
// process arguments
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == "-") { // switch
arg = arg.substring(1);
if (arg.equalsIgnoreCase("jar")) {
jarActive = true;
manActive = false;
zipActive = false;
sourceDirActive = false;
leadDirActive = false;
} else if (arg.equalsIgnoreCase("manifest")) {
jarActive = false;
manActive = true;
zipActive = false;
sourceDirActive = false;
leadDirActive = false;
} else if (arg.equalsIgnoreCase("zip")) {
zipActive = true;
manActive = false;
jarActive = false;
sourceDirActive = false;
leadDirActive = false;
} else if (arg.equalsIgnoreCase("dir")) {
jarActive = false;
manActive = false;
zipActive = false;
sourceDirActive = true;
leadDirActive = false;
} else if (arg.equalsIgnoreCase("lead")) {
jarActive = false;
manActive = false;
zipActive = false;
sourceDirActive = false;
leadDirActive = true;
} else if (arg.equalsIgnoreCase("noDirs")) {
noDirs = true;
jarActive = false;
manActive = false;
zipActive = false;
sourceDirActive = false;
leadDirActive = false;
} else if (arg.equalsIgnoreCase("verbose")) {
verbose = true;
jarActive = false;
manActive = false;
zipActive = false;
sourceDirActive = false;
leadDirActive = false;
} else {
reportError("Invalid switch - " + arg);
}
} else {
if (jarActive) {
if (jarName != null) {
reportError("Duplicate value - " + arg);
}
jarName = arg;
} else if (manActive) {
if (manName != null) {
reportError("Duplicate value - " + arg);
}
manName = arg;
} else if (zipActive) {
if (zipName != null) {
reportError("Duplicate value - " + arg);
}
zipName = arg;
} else if (sourceDirActive) {
if (sourceDir != null) {
reportError("Duplicate value - " + arg);
}
sourceDir = arg;
} else if (leadDirActive) {
if (leadDir != null) {
reportError("Duplicate value - " + arg);
}
leadDir = arg;
} else {
reportError("Too many parameters - " + arg);
}
}
}
if (sourceDir == null || (zipName == null && jarName == null)) {
reportError("Missing parameters");
}
if (manName != null && zipName != null) {
reportError("Manifests not supported on ZIP files");
}
if (leadDir == null) {
leadDir = new File(sourceDir).getAbsolutePath().replace("\\", "/") + "/";
}
if (verbose) {
System.out.println("Effective command: "
+ ZipImploder.class.getName()
+ (jarName != null ? " -jar " + jarName
+ (manName != null ? " -manifest " + manName : "") : "")
+ (zipName != null ? " -zip " + zipName : "") + " -dir " + sourceDir + " -lead "
+ leadDir + (noDirs ? " -noDirs" : "") + (verbose ? " -verbose" : ""));
}
try {
ZipImploder zi = new ZipImploder(verbose);
if (leadDir != null) {
zi.setBaseDir(leadDir);
}
if (manName != null) {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(manName));
try {
zi.setManifest(new Manifest(bis));
} finally {
bis.close();
}
}
zi.setIncludeDirs(!noDirs);
zi.process(zipName, jarName, sourceDir);
if (verbose) {
System.out
.println("\nDone Directories=" + zi.getDirCount() + " Files=" + zi.getFileCount());
}
} catch (IOException ioe) {
System.err.println("Exception - " + ioe.getMessage());
// ioe.printStackTrace(); // *** debug ***
System.exit(2);
}
}
}