Java Tutorial/File/JarFile
Содержание
- 1 A class to find resources in the classpath by their mime-type specified in the MANIFEST.
- 2 Add jar contents to the deployment archive under the given prefix
- 3 Create JarFile and use Pack200.Packer
- 4 Creating a JAR File
- 5 Get CRC code for each file in a Jar file
- 6 Get file comment
- 7 Get jar file Attribute
- 8 Get resource from Jar file
- 9 Get the jar entry
- 10 Get the jar file
- 11 Get uncompressed and compressed file size in a Jar file
- 12 Get zip method: ZipEntry.STORED, ZipEntry.DEFLATED
- 13 JAR Archives: Jar Lister
- 14 JAR Archives: Packer200
- 15 JAR Archives: Unpacker200
- 16 Jar Entry OutputStream
- 17 List all file names in a jar file
- 18 Listing the Entries of a JAR File Manifest
- 19 Listing the Main Attributes in a JAR File Manifest
- 20 Load resource from Jar file
- 21 Make Temp Jar
- 22 Manifest Writer
- 23 Retrieves the manifest from a JAR file and writes the manifest contents to a file.
- 24 Search class in class path and Jar files
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.
*
* 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.
*
* 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 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);
}
}
}
Create JarFile and use Pack200.Packer
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.jar.JarFile;
import java.util.jar.Pack200;
public class MainClass {
public static void main(String[] args) throws Exception {
OutputStream out = null;
JarFile f = new JarFile(args[0]);
Pack200.Packer packer = Pack200.newPacker();
out = new FileOutputStream(args[0] + ".pack");
packer.pack(f, out);
out.close();
}
}
Creating a JAR File
// Create the jar file
jar cf myjar.jar MyClass.class
Get CRC code for each file in a Jar file
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
long crc = je.getCrc();
System.out.println("Its CRC is " + crc);
String comment = je.getComment();
if (comment != null && !comment.equals("")) {
System.out.println(comment);
}
if (je.isDirectory()) {
System.out.println(name + " is a directory");
}
}
}
}
Get file comment
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
long crc = je.getCrc();
System.out.println("Its CRC is " + crc);
String comment = je.getComment();
if (comment != null && !comment.equals("")) {
System.out.println(comment);
}
if (je.isDirectory()) {
System.out.println(name + " is a directory");
}
}
}
}
Get jar file Attribute
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
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]);
}
}
}
}
}
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 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 uncompressed and compressed file size in a Jar file
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
Date lastModified = new Date(je.getTime());
long uncompressedSize = je.getSize();
long compressedSize = je.getCompressedSize();
System.out.println(lastModified);
System.out.println(uncompressedSize);
System.out.println(compressedSize);
}
}
}
Get zip method: ZipEntry.STORED, ZipEntry.DEFLATED
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
Date lastModified = new Date(je.getTime());
long uncompressedSize = je.getSize();
long compressedSize = je.getCompressedSize();
int method = je.getMethod();
if (method == ZipEntry.STORED) {
System.out.println(name + " was stored at " + lastModified);
System.out.println("with a size of " + uncompressedSize
+ " bytes");
}
else if (method == ZipEntry.DEFLATED) {
System.out.println(name + " was deflated at " + lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");
}
else {
System.out.println(name
+ " was compressed using an unrecognized method at "
+ lastModified);
System.out.println("from " + uncompressedSize + " bytes to "
+ compressedSize + " bytes, a savings of "
+ (100.0 - 100.0*compressedSize/uncompressedSize) + "%");
}
}
}
}
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 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.
*
* 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();
}
}
}
List all file names in a jar file
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class MainClass {
public static void main(String[] args) throws IOException {
JarFile jf = new JarFile(args[0]);
Enumeration e = jf.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
String name = je.getName();
System.out.println(name);
}
}
}
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 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;
}
}
}
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 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()
+ "].");
}
}
}
}
}