aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java458
1 files changed, 458 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
new file mode 100644
index 00000000..499cca27
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/jlink/jlink.java
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ *
+ */
+/**
+ * jlink.java links together multiple .jar files Original code by Patrick
+ * Beard. Modifications to work with ANT by Matthew Kuperus Heun.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.jlink;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tools.ant.util.FileUtils;
+
+// CheckStyle:TypeNameCheck OFF - bc
+/**
+ * jlink links together multiple .jar files.
+ */
+public class jlink {
+ private static final int BUFFER_SIZE = 8192;
+ private static final int VECTOR_INIT_SIZE = 10;
+
+ private String outfile = null;
+
+ private Vector mergefiles = new Vector(VECTOR_INIT_SIZE);
+
+ private Vector addfiles = new Vector(VECTOR_INIT_SIZE);
+
+ private boolean compression = false;
+
+ // CheckStyle:VisibilityModifier OFF - bc
+
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ // CheckStyle:VisibilityModifier OFF - bc
+
+ /** The file that will be created by this instance of jlink.
+ * @param outfile the file to create.
+ */
+ public void setOutfile(String outfile) {
+ if (outfile == null) {
+ return;
+ }
+ this.outfile = outfile;
+ }
+
+
+ /**
+ * Adds a file to be merged into the output.
+ * @param fileToMerge the file to merge into the output.
+ */
+ public void addMergeFile(String fileToMerge) {
+ if (fileToMerge == null) {
+ return;
+ }
+ mergefiles.addElement(fileToMerge);
+ }
+
+
+ /** Adds a file to be added into the output.
+ * @param fileToAdd the file to add to the output.
+ */
+ public void addAddFile(String fileToAdd) {
+ if (fileToAdd == null) {
+ return;
+ }
+ addfiles.addElement(fileToAdd);
+ }
+
+
+ /**
+ * Adds several files to be merged into the output.
+ * @param filesToMerge an array of files to merge into the output.
+ */
+ public void addMergeFiles(String[] filesToMerge) {
+ if (filesToMerge == null) {
+ return;
+ }
+ for (int i = 0; i < filesToMerge.length; i++) {
+ addMergeFile(filesToMerge[i]);
+ }
+ }
+
+
+ /**
+ * Adds several file to be added into the output.
+ * @param filesToAdd an array of files to add to the output.
+ */
+ public void addAddFiles(String[] filesToAdd) {
+ if (filesToAdd == null) {
+ return;
+ }
+ for (int i = 0; i < filesToAdd.length; i++) {
+ addAddFile(filesToAdd[i]);
+ }
+ }
+
+
+ /**
+ * Determines whether output will be compressed.
+ * @param compress if true use compression.
+ */
+ public void setCompression(boolean compress) {
+ this.compression = compress;
+ }
+
+
+ /**
+ * Performs the linking of files. Addfiles are added to the output as-is.
+ * For example, a jar file is added to the output as a jar file. However,
+ * mergefiles are first examined for their type. If it is a jar or zip
+ * file, the contents will be extracted from the mergefile and entered
+ * into the output. If a zip or jar file is encountered in a subdirectory
+ * it will be added, not merged. If a directory is encountered, it becomes
+ * the root entry of all the files below it. Thus, you can provide
+ * multiple, disjoint directories, as addfiles: they will all be added in
+ * a rational manner to outfile.
+ * @throws Exception on error.
+ */
+ public void link() throws Exception {
+ ZipOutputStream output = new ZipOutputStream(new FileOutputStream(outfile));
+
+ if (compression) {
+ output.setMethod(ZipOutputStream.DEFLATED);
+ output.setLevel(Deflater.DEFAULT_COMPRESSION);
+ } else {
+ output.setMethod(ZipOutputStream.STORED);
+ }
+
+ Enumeration merges = mergefiles.elements();
+
+ while (merges.hasMoreElements()) {
+ String path = (String) merges.nextElement();
+ File f = new File(path);
+
+ if (f.getName().endsWith(".jar") || f.getName().endsWith(".zip")) {
+ //Do the merge
+ mergeZipJarContents(output, f);
+ } else {
+ //Add this file to the addfiles Vector and add it
+ //later at the top level of the output file.
+ addAddFile(path);
+ }
+ }
+
+ Enumeration adds = addfiles.elements();
+
+ while (adds.hasMoreElements()) {
+ String name = (String) adds.nextElement();
+ File f = new File(name);
+
+ if (f.isDirectory()) {
+ //System.out.println("in jlink: adding directory contents of " + f.getPath());
+ addDirContents(output, f, f.getName() + '/', compression);
+ } else {
+ addFile(output, f, "", compression);
+ }
+ }
+ FileUtils.close(output);
+ }
+
+
+ /**
+ * The command line entry point for jlink.
+ * @param args an array of arguments
+ */
+ public static void main(String[] args) {
+ // jlink output input1 ... inputN
+ if (args.length < 2) {
+ System.out.println("usage: jlink output input1 ... inputN");
+ System.exit(1);
+ }
+ jlink linker = new jlink();
+
+ linker.setOutfile(args[0]);
+ // To maintain compatibility with the command-line version,
+ // we will only add files to be merged.
+ for (int i = 1; i < args.length; i++) {
+ linker.addMergeFile(args[i]);
+ }
+ try {
+ linker.link();
+ } catch (Exception ex) {
+ System.err.print(ex.getMessage());
+ }
+ }
+
+
+ /*
+ * Actually performs the merging of f into the output.
+ * f should be a zip or jar file.
+ */
+ private void mergeZipJarContents(ZipOutputStream output, File f) throws IOException {
+ //Check to see that the file with name "name" exists.
+ if (!f.exists()) {
+ return;
+ }
+ ZipFile zipf = new ZipFile(f);
+ Enumeration entries = zipf.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry inputEntry = (ZipEntry) entries.nextElement();
+ //Ignore manifest entries. They're bound to cause conflicts between
+ //files that are being merged. User should supply their own
+ //manifest file when doing the merge.
+ String inputEntryName = inputEntry.getName();
+ int index = inputEntryName.indexOf("META-INF");
+
+ if (index < 0) {
+ //META-INF not found in the name of the entry. Go ahead and process it.
+ try {
+ output.putNextEntry(processEntry(zipf, inputEntry));
+ } catch (ZipException ex) {
+ //If we get here, it could be because we are trying to put a
+ //directory entry that already exists.
+ //For example, we're trying to write "com", but a previous
+ //entry from another mergefile was called "com".
+ //In that case, just ignore the error and go on to the
+ //next entry.
+ String mess = ex.getMessage();
+
+ if (mess.indexOf("duplicate") >= 0) {
+ //It was the duplicate entry.
+ continue;
+ } else {
+ // I hate to admit it, but we don't know what happened
+ // here. Throw the Exception.
+ throw ex;
+ }
+ }
+
+ InputStream in = zipf.getInputStream(inputEntry);
+ int len = buffer.length;
+ int count = -1;
+
+ while ((count = in.read(buffer, 0, len)) > 0) {
+ output.write(buffer, 0, count);
+ }
+ in.close();
+ output.closeEntry();
+ }
+ }
+ zipf.close();
+ }
+
+
+ /*
+ * Adds contents of a directory to the output.
+ */
+ private void addDirContents(ZipOutputStream output, File dir, String prefix,
+ boolean compress) throws IOException {
+ String[] contents = dir.list();
+
+ for (int i = 0; i < contents.length; ++i) {
+ String name = contents[i];
+ File file = new File(dir, name);
+
+ if (file.isDirectory()) {
+ addDirContents(output, file, prefix + name + '/', compress);
+ } else {
+ addFile(output, file, prefix, compress);
+ }
+ }
+ }
+
+
+ /*
+ * Gets the name of an entry in the file. This is the real name
+ * which for a class is the name of the package with the class
+ * name appended.
+ */
+ private String getEntryName(File file, String prefix) {
+ String name = file.getName();
+
+ if (!name.endsWith(".class")) {
+ // see if the file is in fact a .class file, and determine its actual name.
+ InputStream input = null;
+ try {
+ input = new FileInputStream(file);
+ String className = ClassNameReader.getClassName(input);
+
+ if (className != null) {
+ return className.replace('.', '/') + ".class";
+ }
+ } catch (IOException ioe) {
+ //do nothing
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ //do nothing
+ }
+ }
+ }
+ }
+ System.out.println("From " + file.getPath() + " and prefix " + prefix
+ + ", creating entry " + prefix + name);
+ return (prefix + name);
+ }
+
+
+ /*
+ * Adds a file to the output stream.
+ */
+ private void addFile(ZipOutputStream output, File file, String prefix,
+ boolean compress) throws IOException {
+ //Make sure file exists
+ if (!file.exists()) {
+ return;
+ }
+ ZipEntry entry = new ZipEntry(getEntryName(file, prefix));
+
+ entry.setTime(file.lastModified());
+ entry.setSize(file.length());
+ if (!compress) {
+ entry.setCrc(calcChecksum(file));
+ }
+ FileInputStream input = new FileInputStream(file);
+
+ addToOutputStream(output, input, entry);
+ }
+
+
+ /*
+ * A convenience method that several other methods might call.
+ */
+ private void addToOutputStream(ZipOutputStream output, InputStream input,
+ ZipEntry ze) throws IOException {
+ try {
+ output.putNextEntry(ze);
+ } catch (ZipException zipEx) {
+ //This entry already exists. So, go with the first one.
+ input.close();
+ return;
+ }
+
+ int numBytes = -1;
+
+ while ((numBytes = input.read(buffer)) > 0) {
+ output.write(buffer, 0, numBytes);
+ }
+ output.closeEntry();
+ input.close();
+ }
+
+
+ /*
+ * A method that does the work on a given entry in a mergefile.
+ * The big deal is to set the right parameters in the ZipEntry
+ * on the output stream.
+ */
+ private ZipEntry processEntry(ZipFile zip, ZipEntry inputEntry) {
+ /*
+ First, some notes.
+ On MRJ 2.2.2, getting the size, compressed size, and CRC32 from the
+ ZipInputStream does not work for compressed (deflated) files. Those calls return -1.
+ For uncompressed (stored) files, those calls do work.
+ However, using ZipFile.getEntries() works for both compressed and
+ uncompressed files.
+
+ Now, from some simple testing I did, it seems that the value of CRC-32 is
+ independent of the compression setting. So, it should be easy to pass this
+ information on to the output entry.
+ */
+ String name = inputEntry.getName();
+
+ if (!(inputEntry.isDirectory() || name.endsWith(".class"))) {
+ try {
+ InputStream input = zip.getInputStream(zip.getEntry(name));
+ String className = ClassNameReader.getClassName(input);
+
+ input.close();
+ if (className != null) {
+ name = className.replace('.', '/') + ".class";
+ }
+ } catch (IOException ioe) {
+ //do nothing
+ }
+ }
+ ZipEntry outputEntry = new ZipEntry(name);
+
+ outputEntry.setTime(inputEntry.getTime());
+ outputEntry.setExtra(inputEntry.getExtra());
+ outputEntry.setComment(inputEntry.getComment());
+ outputEntry.setTime(inputEntry.getTime());
+ if (compression) {
+ outputEntry.setMethod(ZipEntry.DEFLATED);
+ //Note, don't need to specify size or crc for compressed files.
+ } else {
+ outputEntry.setMethod(ZipEntry.STORED);
+ outputEntry.setCrc(inputEntry.getCrc());
+ outputEntry.setSize(inputEntry.getSize());
+ }
+ return outputEntry;
+ }
+
+
+ /*
+ * Necessary in the case where you add a entry that
+ * is not compressed.
+ */
+ private long calcChecksum(File f) throws IOException {
+ BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
+
+ return calcChecksum(in);
+ }
+
+
+ /*
+ * Necessary in the case where you add a entry that
+ * is not compressed.
+ */
+ private long calcChecksum(InputStream in) throws IOException {
+ CRC32 crc = new CRC32();
+ int len = buffer.length;
+ int count = -1;
+ int haveRead = 0;
+
+ while ((count = in.read(buffer, 0, len)) > 0) {
+ haveRead += count;
+ crc.update(buffer, 0, count);
+ }
+ in.close();
+ return crc.getValue();
+ }
+
+
+}
+
+