Writes all files of the given directory to the specified jar-file
//package com.qlogic.commons.utils.io;
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.util.Enumeration;
import java.util.HashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public final class JarUtil {
private final static boolean IS_WINDOWS = (File.separatorChar == '\\');
/**
* Writes all files of the given directory to the specified jar-file.
*
* @param sourceDir
* The directory containing the "source" files.
* @param target
* The jar file which should be created
* @param compress
* True when the jar file should be compressed
* @throws FileNotFoundException
* when a file could not be found
* @throws IOException
* when a file could not be read or the jar file could not be
* written to.
*/
public static void jar(File sourceDir, File target, boolean compress)
throws IOException {
jar(sourceDir, target, compress);
}
/**
* Writes all given files to the specified jar-file.
*
* @param files
* all files that should be added to the JAR file
* @param sourceDir
* The parent directory containing the given files.
* @param target
* The jar file which should be created
* @param compress
* True when the jar file should be compressed
* @throws FileNotFoundException
* when a file could not be found
* @throws IOException
* when a file could not be read or the jar file could not be
* written to.
*/
public static void jar(File sourceDir, OutputStream target,
boolean compress) throws IOException {
File[] files = sourceDir.listFiles ();
// creates target-jar-file:
JarOutputStream out = new JarOutputStream(target);
if (compress) {
out.setLevel(ZipOutputStream.DEFLATED);
} else {
out.setLevel(ZipOutputStream.STORED);
}
// create a CRC32 object:
CRC32 crc = new CRC32();
byte[] buffer = new byte[1024 * 1024];
// add all files:
int sourceDirLength = sourceDir.getAbsolutePath().length() + 1;
for (File file : files) {
addFile(file, out, crc, sourceDirLength, buffer);
}
out.close();
}
/**
* Adds one file to the given jar file. If the specified file is a
* directory, all included files will be added.
*
* @param file
* The file which should be added
* @param out
* The jar file to which the given jar file should be added
* @param crc
* A helper class for the CRC32 calculation
* @param sourceDirLength
* The number of chars which can be skipped from the file's path
* @param buffer
* A buffer for reading the files.
* @throws FileNotFoundException
* when the file was not found
* @throws IOException
* when the file could not be read or not be added
*/
private static void addFile(File file, JarOutputStream out, CRC32 crc,
int sourceDirLength, byte[] buffer) throws FileNotFoundException,
IOException {
if (file.isDirectory()) {
File[] fileNames = file.listFiles();
for (int i = 0; i < fileNames.length; i++) {
addFile(fileNames[i], out, crc, sourceDirLength, buffer);
}
} else {
String entryName = file.getAbsolutePath().substring(sourceDirLength);
if (IS_WINDOWS) {
entryName = entryName.replace('\\', '/');
}
JarEntry entry = new JarEntry(entryName);
// read file:
FileInputStream in = new FileInputStream(file);
add(entry, in, out, crc, buffer);
}
}
/**
* @param entry
* @param in
* @param out
* @param crc
* @param buffer
* @throws IOException
*/
private static void add(JarEntry entry, InputStream in,
JarOutputStream out, CRC32 crc, byte[] buffer) throws IOException {
out.putNextEntry(entry);
int read;
long size = 0;
while ((read = in.read(buffer)) != -1) {
crc.update(buffer, 0, read);
out.write(buffer, 0, read);
size += read;
}
entry.setCrc(crc.getValue());
entry.setSize(size);
in.close();
out.closeEntry();
crc.reset();
}
/**
* Adds the given file to the specified JAR file.
*
* @param file
* the file that should be added
* @param jarFile
* The JAR to which the file should be added
* @param parentDir
* the parent directory of the file, this is used to calculate
* the path witin the JAR file. When null is given, the file will
* be added into the root of the JAR.
* @param compress
* True when the jar file should be compressed
* @throws FileNotFoundException
* when the jarFile does not exist
* @throws IOException
* when a file could not be written or the jar-file could not
* read.
*/
public static void addToJar(File file, File jarFile, File parentDir,
boolean compress) throws FileNotFoundException, IOException {
File tmpJarFile = File.createTempFile("tmp", ".jar", jarFile
.getParentFile());
JarOutputStream out = new JarOutputStream(new FileOutputStream(
tmpJarFile));
if (compress) {
out.setLevel(ZipOutputStream.DEFLATED);
} else {
out.setLevel(ZipOutputStream.STORED);
}
// copy contents of old jar to new jar:
JarFile inputFile = new JarFile(jarFile);
JarInputStream in = new JarInputStream(new FileInputStream(jarFile));
CRC32 crc = new CRC32();
byte[] buffer = new byte[512 * 1024];
JarEntry entry = (JarEntry) in.getNextEntry();
while (entry != null) {
InputStream entryIn = inputFile.getInputStream(entry);
add(entry, entryIn, out, crc, buffer);
entryIn.close();
entry = (JarEntry) in.getNextEntry();
}
in.close();
inputFile.close();
int sourceDirLength;
if (parentDir == null) {
sourceDirLength = file.getAbsolutePath().lastIndexOf(
File.separatorChar) + 1;
} else {
sourceDirLength = file.getAbsolutePath().lastIndexOf(
File.separatorChar)
+ 1 - parentDir.getAbsolutePath().length();
}
addFile(file, out, crc, sourceDirLength, buffer);
out.close();
// remove old jar file and rename temp file to old one:
if (jarFile.delete()) {
if (!tmpJarFile.renameTo(jarFile)) {
throw new IOException(
"Unable to rename temporary JAR file to ["
+ jarFile.getAbsolutePath() + "].");
}
} else {
throw new IOException("Unable to delete old JAR file ["
+ jarFile.getAbsolutePath() + "].");
}
}
/**
* Extracts the given jar-file to the specified directory. The target
* directory will be cleaned before the jar-file will be extracted.
*
* @param jarFile
* The jar file which should be unpacked
* @param targetDir
* The directory to which the jar-content should be extracted.
* @throws FileNotFoundException
* when the jarFile does not exist
* @throws IOException
* when a file could not be written or the jar-file could not
* read.
*/
public static void unjar(File jarFile, File targetDir)
throws FileNotFoundException, IOException {
// clear target directory:
if (targetDir.exists()) {
targetDir.delete();
}
// create new target directory:
targetDir.mkdirs();
// read jar-file:
String targetPath = targetDir.getAbsolutePath() + File.separatorChar;
byte[] buffer = new byte[1024 * 1024];
JarFile input = new JarFile(jarFile, false, ZipFile.OPEN_READ);
Enumeration<JarEntry> enumeration = input.entries();
for (; enumeration.hasMoreElements();) {
JarEntry entry = enumeration.nextElement();
if (!entry.isDirectory()) {
// do not copy anything from the package cache:
if (entry.getName().indexOf("package cache") == -1) {
String path = targetPath + entry.getName();
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileOutputStream out = new FileOutputStream(file);
InputStream in = input.getInputStream(entry);
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.close();
}
}
}
}
/**
* Extracts the given resource from a jar-file to the specified directory.
*
* @param jarFile
* The jar file which should be unpacked
* @param resource
* The name of a resource in the jar
* @param targetDir
* The directory to which the jar-content should be extracted.
* @throws FileNotFoundException
* when the jarFile does not exist
* @throws IOException
* when a file could not be written or the jar-file could not
* read.
*/
public static void unjar(File jarFile, String resource, File targetDir)
throws FileNotFoundException, IOException {
// clear target directory:
if (targetDir.exists()) {
targetDir.delete();
}
// create new target directory:
targetDir.mkdirs();
// read jar-file:
String targetPath = targetDir.getAbsolutePath() + File.separatorChar;
byte[] buffer = new byte[1024 * 1024];
JarFile input = new JarFile(jarFile, false, ZipFile.OPEN_READ);
Enumeration<JarEntry> enumeration = input.entries();
for (; enumeration.hasMoreElements();) {
JarEntry entry = enumeration.nextElement();
if (!entry.isDirectory()) {
// do not copy anything from the package cache:
if (entry.getName().equals(resource)) {
String path = targetPath + entry.getName();
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileOutputStream out = new FileOutputStream(file);
InputStream in = input.getInputStream(entry);
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.close();
}
}
}
}
/**
* Reads the package-names from the given jar-file.
*
* @param jarFile
* the jar file
* @return an array with all found package-names
* @throws IOException
* when the jar-file could not be read
*/
public static String[] getPackageNames(File jarFile) throws IOException {
HashMap<String, String> packageNames = new HashMap<String, String> ();
JarFile input = new JarFile(jarFile, false, ZipFile.OPEN_READ);
Enumeration<JarEntry> enumeration = input.entries();
for (; enumeration.hasMoreElements();) {
JarEntry entry = enumeration.nextElement();
String name = entry.getName();
if (name.endsWith(".class")) {
int endPos = name.lastIndexOf('/');
boolean isWindows = false;
if (endPos == -1) {
endPos = name.lastIndexOf('\\');
isWindows = true;
}
name = name.substring(0, endPos);
name = name.replace('/', '.');
if (isWindows) {
name = name.replace('\\', '.');
}
packageNames.put(name, name);
}
}
return (String[]) packageNames.values().toArray(
new String[packageNames.size()]);
}
}
Related examples in the same category