aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java1238
1 files changed, 0 insertions, 1238 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java
deleted file mode 100644
index c2c0f0ed..00000000
--- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Jar.java
+++ /dev/null
@@ -1,1238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.tools.ant.taskdefs;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-import java.util.Vector;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.Manifest.Section;
-import org.apache.tools.ant.types.ArchiveFileSet;
-import org.apache.tools.ant.types.EnumeratedAttribute;
-import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.types.ResourceCollection;
-import org.apache.tools.ant.types.ZipFileSet;
-import org.apache.tools.ant.types.spi.Service;
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.zip.JarMarker;
-import org.apache.tools.zip.ZipExtraField;
-import org.apache.tools.zip.ZipOutputStream;
-
-/**
- * Creates a JAR archive.
- *
- * @since Ant 1.1
- *
- * @ant.task category="packaging"
- */
-public class Jar extends Zip {
- /** The index file name. */
- private static final String INDEX_NAME = "META-INF/INDEX.LIST";
-
- /** The manifest file name. */
- private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
-
- /**
- * List of all known SPI Services
- */
- private List<Service> serviceList = new ArrayList<Service>();
-
- /** merged manifests added through addConfiguredManifest */
- private Manifest configuredManifest;
-
- /** shadow of the above if upToDate check alters the value */
- private Manifest savedConfiguredManifest;
-
- /** merged manifests added through filesets */
- private Manifest filesetManifest;
-
- /**
- * Manifest of original archive, will be set to null if not in
- * update mode.
- */
- private Manifest originalManifest;
-
- /**
- * whether to merge fileset manifests;
- * value is true if filesetmanifest is 'merge' or 'mergewithoutmain'
- */
- private FilesetManifestConfig filesetManifestConfig;
-
- /**
- * whether to merge the main section of fileset manifests;
- * value is true if filesetmanifest is 'merge'
- */
- private boolean mergeManifestsMain = true;
-
- /** the manifest specified by the 'manifest' attribute **/
- private Manifest manifest;
-
- /** The encoding to use when reading in a manifest file */
- private String manifestEncoding;
-
- /**
- * The file found from the 'manifest' attribute. This can be
- * either the location of a manifest, or the name of a jar added
- * through a fileset. If its the name of an added jar, the
- * manifest is looked for in META-INF/MANIFEST.MF
- */
- private File manifestFile;
-
- /** jar index is JDK 1.3+ only */
- private boolean index = false;
-
- /** Whether to index META-INF/ and its children */
- private boolean indexMetaInf = false;
-
- /**
- * whether to really create the archive in createEmptyZip, will
- * get set in getResourcesToAdd.
- */
- private boolean createEmpty = false;
-
- /**
- * Stores all files that are in the root of the archive (i.e. that
- * have a name that doesn't contain a slash) so they can get
- * listed in the index.
- *
- * Will not be filled unless the user has asked for an index.
- *
- * @since Ant 1.6
- */
- private Vector<String> rootEntries;
-
- /**
- * Path containing jars that shall be indexed in addition to this archive.
- *
- * @since Ant 1.6.2
- */
- private Path indexJars;
-
- // CheckStyle:LineLength OFF - Link is too long.
- /**
- * Strict mode for checking rules of the JAR-Specification.
- * @see http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning
- */
- private StrictMode strict = new StrictMode("ignore");
-
- // CheckStyle:LineLength ON
-
- /**
- * whether to merge Class-Path attributes.
- */
- private boolean mergeClassPaths = false;
-
- /**
- * whether to flatten Class-Path attributes into a single one.
- */
- private boolean flattenClassPaths = false;
-
- /**
- * Extra fields needed to make Solaris recognize the archive as a jar file.
- *
- * @since Ant 1.6.3
- */
- private static final ZipExtraField[] JAR_MARKER = new ZipExtraField[] {
- JarMarker.getInstance()
- };
-
- /** constructor */
- public Jar() {
- super();
- archiveType = "jar";
- emptyBehavior = "create";
- setEncoding("UTF8");
- setZip64Mode(Zip64ModeAttribute.NEVER);
- rootEntries = new Vector<String>();
- }
-
- /**
- * Not used for jar files.
- * @param we not used
- * @ant.attribute ignore="true"
- */
- public void setWhenempty(WhenEmpty we) {
- log("JARs are never empty, they contain at least a manifest file",
- Project.MSG_WARN);
- }
-
- /**
- * Indicates if a jar file should be created when it would only contain a
- * manifest file.
- * Possible values are: <code>fail</code> (throw an exception
- * and halt the build); <code>skip</code> (do not create
- * any archive, but issue a warning); <code>create</code>
- * (make an archive with only a manifest file).
- * Default is <code>create</code>;
- * @param we a <code>WhenEmpty</code> enumerated value
- */
- public void setWhenmanifestonly(WhenEmpty we) {
- emptyBehavior = we.getValue();
- }
-
- /**
- * Activate the strict mode. When set to <i>true</i> a BuildException
- * will be thrown if the Jar-Packaging specification was broken.
- * @param strict New value of the strict mode.
- * @since Ant 1.7.1
- */
- public void setStrict(StrictMode strict) {
- this.strict = strict;
- }
-
- /**
- * Set the destination file.
- * @param jarFile the destination file
- * @deprecated since 1.5.x.
- * Use setDestFile(File) instead.
- */
- public void setJarfile(File jarFile) {
- setDestFile(jarFile);
- }
-
- /**
- * Set whether or not to create an index list for classes.
- * This may speed up classloading in some cases.
- * @param flag a <code>boolean</code> value
- */
- public void setIndex(boolean flag) {
- index = flag;
- }
-
- /**
- * Set whether or not to add META-INF and its children to the index.
- *
- * <p>Doesn't have any effect if index is false.</p>
- *
- * <p>Sun's jar implementation used to skip the META-INF directory
- * and Ant followed that example. The behavior has been changed
- * with Java 5. In order to avoid problems with Ant generated
- * jars on Java 1.4 or earlier Ant will not include META-INF
- * unless explicitly asked to.</p>
- *
- * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526">
- * jar -i omits service providers in index.list</a>
- * @since Ant 1.8.0
- * @param flag a <code>boolean</code> value, defaults to false
- */
- public void setIndexMetaInf(boolean flag) {
- indexMetaInf = flag;
- }
-
- /**
- * The character encoding to use in the manifest file.
- *
- * @param manifestEncoding the character encoding
- */
- public void setManifestEncoding(String manifestEncoding) {
- this.manifestEncoding = manifestEncoding;
- }
-
- /**
- * Allows the manifest for the archive file to be provided inline
- * in the build file rather than in an external file.
- *
- * @param newManifest an embedded manifest element
- * @throws ManifestException on error
- */
- public void addConfiguredManifest(Manifest newManifest)
- throws ManifestException {
- if (configuredManifest == null) {
- configuredManifest = newManifest;
- } else {
- configuredManifest.merge(newManifest, false, mergeClassPaths);
- }
- savedConfiguredManifest = configuredManifest;
- }
-
- /**
- * The manifest file to use. This can be either the location of a manifest,
- * or the name of a jar added through a fileset. If its the name of an added
- * jar, the task expects the manifest to be in the jar at META-INF/MANIFEST.MF.
- *
- * @param manifestFile the manifest file to use.
- */
- public void setManifest(File manifestFile) {
- if (!manifestFile.exists()) {
- throw new BuildException("Manifest file: " + manifestFile
- + " does not exist.", getLocation());
- }
-
- this.manifestFile = manifestFile;
- }
-
- private Manifest getManifest(File manifestFile) {
-
- Manifest newManifest = null;
- FileInputStream fis = null;
- InputStreamReader isr = null;
- try {
- fis = new FileInputStream(manifestFile);
- if (manifestEncoding == null) {
- isr = new InputStreamReader(fis);
- } else {
- isr = new InputStreamReader(fis, manifestEncoding);
- }
- newManifest = getManifest(isr);
- } catch (UnsupportedEncodingException e) {
- throw new BuildException("Unsupported encoding while reading manifest: "
- + e.getMessage(), e);
- } catch (IOException e) {
- throw new BuildException("Unable to read manifest file: "
- + manifestFile
- + " (" + e.getMessage() + ")", e);
- } finally {
- FileUtils.close(isr);
- }
- return newManifest;
- }
-
- /**
- * @return null if jarFile doesn't contain a manifest, the
- * manifest otherwise.
- * @since Ant 1.5.2
- */
- private Manifest getManifestFromJar(File jarFile) throws IOException {
- ZipFile zf = null;
- try {
- zf = new ZipFile(jarFile);
-
- // must not use getEntry as "well behaving" applications
- // must accept the manifest in any capitalization
- Enumeration<? extends ZipEntry> e = zf.entries();
- while (e.hasMoreElements()) {
- ZipEntry ze = e.nextElement();
- if (ze.getName().equalsIgnoreCase(MANIFEST_NAME)) {
- InputStreamReader isr =
- new InputStreamReader(zf.getInputStream(ze), "UTF-8");
- return getManifest(isr);
- }
- }
- return null;
- } finally {
- if (zf != null) {
- try {
- zf.close();
- } catch (IOException e) {
- // TODO - log an error? throw an exception?
- }
- }
- }
- }
-
- private Manifest getManifest(Reader r) {
-
- Manifest newManifest = null;
- try {
- newManifest = new Manifest(r);
- } catch (ManifestException e) {
- log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
- throw new BuildException("Invalid Manifest: " + manifestFile,
- e, getLocation());
- } catch (IOException e) {
- throw new BuildException("Unable to read manifest file"
- + " (" + e.getMessage() + ")", e);
- }
- return newManifest;
- }
-
- private boolean jarHasIndex(File jarFile) throws IOException {
- ZipFile zf = null;
- try {
- zf = new ZipFile(jarFile);
- Enumeration<? extends ZipEntry> e = zf.entries();
- while (e.hasMoreElements()) {
- ZipEntry ze = e.nextElement();
- if (ze.getName().equalsIgnoreCase(INDEX_NAME)) {
- return true;
- }
- }
- return false;
- } finally {
- if (zf != null) {
- try {
- zf.close();
- } catch (IOException e) {
- // TODO - log an error? throw an exception?
- }
- }
- }
- }
-
- /**
- * Behavior when a Manifest is found in a zipfileset or zipgroupfileset file.
- * Valid values are "skip", "merge", and "mergewithoutmain".
- * "merge" will merge all of manifests together, and merge this into any
- * other specified manifests.
- * "mergewithoutmain" merges everything but the Main section of the manifests.
- * Default value is "skip".
- *
- * Note: if this attribute's value is not "skip", the created jar will not
- * be readable by using java.util.jar.JarInputStream
- *
- * @param config setting for found manifest behavior.
- */
- public void setFilesetmanifest(FilesetManifestConfig config) {
- filesetManifestConfig = config;
- mergeManifestsMain = "merge".equals(config.getValue());
-
- if (filesetManifestConfig != null
- && !filesetManifestConfig.getValue().equals("skip")) {
-
- doubleFilePass = true;
- }
- }
-
- /**
- * Adds a zipfileset to include in the META-INF directory.
- *
- * @param fs zipfileset to add
- */
- public void addMetainf(ZipFileSet fs) {
- // We just set the prefix for this fileset, and pass it up.
- fs.setPrefix("META-INF/");
- super.addFileset(fs);
- }
-
- /**
- * Add a path to index jars.
- * @param p a path
- * @since Ant 1.6.2
- */
- public void addConfiguredIndexJars(Path p) {
- if (indexJars == null) {
- indexJars = new Path(getProject());
- }
- indexJars.append(p);
- }
-
- /**
- * A nested SPI service element.
- * @param service the nested element.
- * @since Ant 1.7
- */
- public void addConfiguredService(Service service) {
- // Check if the service is configured correctly
- service.check();
- serviceList.add(service);
- }
-
- /**
- * Write SPI Information to JAR
- */
- private void writeServices(ZipOutputStream zOut) throws IOException {
- for (Service service : serviceList) {
- InputStream is = null;
- try {
- is = service.getAsStream();
- //stolen from writeManifest
- super.zipFile(is, zOut,
- "META-INF/services/" + service.getType(),
- System.currentTimeMillis(), null,
- ZipFileSet.DEFAULT_FILE_MODE);
- } finally {
- // technically this is unnecessary since
- // Service.getAsStream returns a ByteArrayInputStream
- // and not closing it wouldn't do any harm.
- FileUtils.close(is);
- }
- }
- }
-
- /**
- * Whether to merge Class-Path attributes.
- *
- * @since Ant 1.8.0
- */
- public void setMergeClassPathAttributes(boolean b) {
- mergeClassPaths = b;
- }
-
- /**
- * Whether to flatten multi-valued attributes (i.e. Class-Path)
- * into a single one.
- *
- * @since Ant 1.8.0
- */
- public void setFlattenAttributes(boolean b) {
- flattenClassPaths = b;
- }
-
- /**
- * Initialize the zip output stream.
- * @param zOut the zip output stream
- * @throws IOException on I/O errors
- * @throws BuildException on other errors
- */
- protected void initZipOutputStream(ZipOutputStream zOut)
- throws IOException, BuildException {
-
- if (!skipWriting) {
- Manifest jarManifest = createManifest();
- writeManifest(zOut, jarManifest);
- writeServices(zOut);
- }
- }
-
- private Manifest createManifest()
- throws BuildException {
- try {
- if (manifest == null) {
- if (manifestFile != null) {
- // if we haven't got the manifest yet, attempt to
- // get it now and have manifest be the final merge
- manifest = getManifest(manifestFile);
- }
- }
-
- // fileset manifest must come even before the default
- // manifest if mergewithoutmain is selected and there is
- // no explicit manifest specified - otherwise the Main
- // section of the fileset manifest is still merged to the
- // final manifest.
- boolean mergeFileSetFirst = !mergeManifestsMain
- && filesetManifest != null
- && configuredManifest == null && manifest == null;
-
- Manifest finalManifest;
- if (mergeFileSetFirst) {
- finalManifest = new Manifest();
- finalManifest.merge(filesetManifest, false, mergeClassPaths);
- finalManifest.merge(Manifest.getDefaultManifest(),
- true, mergeClassPaths);
- } else {
- finalManifest = Manifest.getDefaultManifest();
- }
-
- /*
- * Precedence: manifestFile wins over inline manifest,
- * over manifests read from the filesets over the original
- * manifest.
- *
- * merge with null argument is a no-op
- */
-
- if (isInUpdateMode()) {
- finalManifest.merge(originalManifest, false, mergeClassPaths);
- }
- if (!mergeFileSetFirst) {
- finalManifest.merge(filesetManifest, false, mergeClassPaths);
- }
- finalManifest.merge(configuredManifest, !mergeManifestsMain,
- mergeClassPaths);
- finalManifest.merge(manifest, !mergeManifestsMain,
- mergeClassPaths);
-
- return finalManifest;
-
- } catch (ManifestException e) {
- log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
- throw new BuildException("Invalid Manifest", e, getLocation());
- }
- }
-
- private void writeManifest(ZipOutputStream zOut, Manifest manifest)
- throws IOException {
- for (Enumeration<String> e = manifest.getWarnings();
- e.hasMoreElements();) {
- log("Manifest warning: " + e.nextElement(),
- Project.MSG_WARN);
- }
-
- zipDir((Resource) null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE,
- JAR_MARKER);
- // time to write the manifest
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- OutputStreamWriter osw = new OutputStreamWriter(baos, Manifest.JAR_ENCODING);
- PrintWriter writer = new PrintWriter(osw);
- manifest.write(writer, flattenClassPaths);
- if (writer.checkError()) {
- throw new IOException("Encountered an error writing the manifest");
- }
- writer.close();
-
- ByteArrayInputStream bais =
- new ByteArrayInputStream(baos.toByteArray());
- try {
- super.zipFile(bais, zOut, MANIFEST_NAME,
- System.currentTimeMillis(), null,
- ZipFileSet.DEFAULT_FILE_MODE);
- } finally {
- // not really required
- FileUtils.close(bais);
- }
- super.initZipOutputStream(zOut);
- }
-
- /**
- * Finalize the zip output stream.
- * This creates an index list if the index attribute is true.
- * @param zOut the zip output stream
- * @throws IOException on I/O errors
- * @throws BuildException on other errors
- */
- protected void finalizeZipOutputStream(ZipOutputStream zOut)
- throws IOException, BuildException {
-
- if (index) {
- createIndexList(zOut);
- }
- }
-
- /**
- * Create the index list to speed up classloading.
- * This is a JDK 1.3+ specific feature and is enabled by default. See
- * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index">
- * the JAR index specification</a> for more details.
- *
- * @param zOut the zip stream representing the jar being built.
- * @throws IOException thrown if there is an error while creating the
- * index and adding it to the zip stream.
- */
- private void createIndexList(ZipOutputStream zOut) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- // encoding must be UTF8 as specified in the specs.
- PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos,
- "UTF8"));
-
- // version-info blankline
- writer.println("JarIndex-Version: 1.0");
- writer.println();
-
- // header newline
- writer.println(zipFile.getName());
-
- writeIndexLikeList(new ArrayList<String>(addedDirs.keySet()),
- rootEntries, writer);
- writer.println();
-
- if (indexJars != null) {
- Manifest mf = createManifest();
- Manifest.Attribute classpath =
- mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
- String[] cpEntries = null;
- if (classpath != null && classpath.getValue() != null) {
- StringTokenizer tok = new StringTokenizer(classpath.getValue(),
- " ");
- cpEntries = new String[tok.countTokens()];
- int c = 0;
- while (tok.hasMoreTokens()) {
- cpEntries[c++] = tok.nextToken();
- }
- }
- String[] indexJarEntries = indexJars.list();
- for (int i = 0; i < indexJarEntries.length; i++) {
- String name = findJarName(indexJarEntries[i], cpEntries);
- if (name != null) {
- ArrayList<String> dirs = new ArrayList<String>();
- ArrayList<String> files = new ArrayList<String>();
- grabFilesAndDirs(indexJarEntries[i], dirs, files);
- if (dirs.size() + files.size() > 0) {
- writer.println(name);
- writeIndexLikeList(dirs, files, writer);
- writer.println();
- }
- }
- }
- }
-
- if (writer.checkError()) {
- throw new IOException("Encountered an error writing jar index");
- }
- writer.close();
- ByteArrayInputStream bais =
- new ByteArrayInputStream(baos.toByteArray());
- try {
- super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(),
- null, ZipFileSet.DEFAULT_FILE_MODE);
- } finally {
- // not really required
- FileUtils.close(bais);
- }
- }
-
- /**
- * Overridden from Zip class to deal with manifests and index lists.
- * @param is the stream to read data for the entry from. The
- * caller of the method is responsible for closing the stream.
- * @param zOut the zip output stream
- * @param vPath the name this entry shall have in the archive
- * @param lastModified last modification time for the entry.
- * @param fromArchive the original archive we are copying this
- * entry from, will be null if we are not copying from an archive.
- * @param mode the Unix permissions to set.
- * @throws IOException on error
- */
- protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath,
- long lastModified, File fromArchive, int mode)
- throws IOException {
- if (MANIFEST_NAME.equalsIgnoreCase(vPath)) {
- if (isFirstPass()) {
- filesetManifest(fromArchive, is);
- }
- } else if (INDEX_NAME.equalsIgnoreCase(vPath) && index) {
- logWhenWriting("Warning: selected " + archiveType
- + " files include a " + INDEX_NAME + " which will"
- + " be replaced by a newly generated one.",
- Project.MSG_WARN);
- } else {
- if (index && vPath.indexOf("/") == -1) {
- rootEntries.addElement(vPath);
- }
- super.zipFile(is, zOut, vPath, lastModified, fromArchive, mode);
- }
- }
-
- private void filesetManifest(File file, InputStream is) throws IOException {
- if (manifestFile != null && manifestFile.equals(file)) {
- // If this is the same name specified in 'manifest', this
- // is the manifest to use
- log("Found manifest " + file, Project.MSG_VERBOSE);
- try {
- if (is != null) {
- InputStreamReader isr;
- if (manifestEncoding == null) {
- isr = new InputStreamReader(is);
- } else {
- isr = new InputStreamReader(is, manifestEncoding);
- }
- manifest = getManifest(isr);
- } else {
- manifest = getManifest(file);
- }
- } catch (UnsupportedEncodingException e) {
- throw new BuildException("Unsupported encoding while reading "
- + "manifest: " + e.getMessage(), e);
- }
- } else if (filesetManifestConfig != null
- && !filesetManifestConfig.getValue().equals("skip")) {
- // we add this to our group of fileset manifests
- logWhenWriting("Found manifest to merge in file " + file,
- Project.MSG_VERBOSE);
-
- try {
- Manifest newManifest = null;
- if (is != null) {
- InputStreamReader isr;
- if (manifestEncoding == null) {
- isr = new InputStreamReader(is);
- } else {
- isr = new InputStreamReader(is, manifestEncoding);
- }
- newManifest = getManifest(isr);
- } else {
- newManifest = getManifest(file);
- }
-
- if (filesetManifest == null) {
- filesetManifest = newManifest;
- } else {
- filesetManifest.merge(newManifest, false, mergeClassPaths);
- }
- } catch (UnsupportedEncodingException e) {
- throw new BuildException("Unsupported encoding while reading "
- + "manifest: " + e.getMessage(), e);
- } catch (ManifestException e) {
- log("Manifest in file " + file + " is invalid: "
- + e.getMessage(), Project.MSG_ERR);
- throw new BuildException("Invalid Manifest", e, getLocation());
- }
- } else {
- // assuming 'skip' otherwise
- // don't warn if skip has been requested explicitly, warn if user
- // didn't set the attribute
-
- // Hide warning also as it makes no sense since
- // the filesetmanifest attribute itself has been
- // hidden
-
- //int logLevel = filesetManifestConfig == null ?
- // Project.MSG_WARN : Project.MSG_VERBOSE;
- //log("File " + file
- // + " includes a META-INF/MANIFEST.MF which will be ignored. "
- // + "To include this file, set filesetManifest to a value other "
- // + "than 'skip'.", logLevel);
- }
- }
-
- /**
- * Collect the resources that are newer than the corresponding
- * entries (or missing) in the original archive.
- *
- * <p>If we are going to recreate the archive instead of updating
- * it, all resources should be considered as new, if a single one
- * is. Because of this, subclasses overriding this method must
- * call <code>super.getResourcesToAdd</code> and indicate with the
- * third arg if they already know that the archive is
- * out-of-date.</p>
- *
- * @param rcs The resource collections to grab resources from
- * @param zipFile intended archive file (may or may not exist)
- * @param needsUpdate whether we already know that the archive is
- * out-of-date. Subclasses overriding this method are supposed to
- * set this value correctly in their call to
- * super.getResourcesToAdd.
- * @return an array of resources to add for each fileset passed in as well
- * as a flag that indicates whether the archive is uptodate.
- *
- * @exception BuildException if it likes
- */
- protected ArchiveState getResourcesToAdd(ResourceCollection[] rcs,
- File zipFile,
- boolean needsUpdate)
- throws BuildException {
-
- if (skipWriting) {
- // this pass is only there to construct the merged
- // manifest this means we claim an update was needed and
- // only include the manifests, skipping any uptodate
- // checks here deferring them for the second run
- Resource[][] manifests = grabManifests(rcs);
- int count = 0;
- for (int i = 0; i < manifests.length; i++) {
- count += manifests[i].length;
- }
- log("found a total of " + count + " manifests in "
- + manifests.length + " resource collections",
- Project.MSG_VERBOSE);
- return new ArchiveState(true, manifests);
- }
-
- // need to handle manifest as a special check
- if (zipFile.exists()) {
- // if it doesn't exist, it will get created anyway, don't
- // bother with any up-to-date checks.
-
- try {
- originalManifest = getManifestFromJar(zipFile);
- if (originalManifest == null) {
- log("Updating jar since the current jar has"
- + " no manifest", Project.MSG_VERBOSE);
- needsUpdate = true;
- } else {
- Manifest mf = createManifest();
- if (!mf.equals(originalManifest)) {
- log("Updating jar since jar manifest has"
- + " changed", Project.MSG_VERBOSE);
- needsUpdate = true;
- }
- }
- } catch (Throwable t) {
- log("error while reading original manifest in file: "
- + zipFile.toString() + " due to " + t.getMessage(),
- Project.MSG_WARN);
- needsUpdate = true;
- }
-
- } else {
- // no existing archive
- needsUpdate = true;
- }
-
- createEmpty = needsUpdate;
- if (!needsUpdate && index) {
- try {
- needsUpdate = !jarHasIndex(zipFile);
- } catch (IOException e) {
- //if we couldn't read it, we might as well recreate it?
- needsUpdate = true;
- }
- }
- return super.getResourcesToAdd(rcs, zipFile, needsUpdate);
- }
-
- /**
- * Create an empty jar file.
- * @param zipFile the file to create
- * @return true for historic reasons
- * @throws BuildException on error
- */
- protected boolean createEmptyZip(File zipFile) throws BuildException {
- if (!createEmpty) {
- return true;
- }
-
- if (emptyBehavior.equals("skip")) {
- if (!skipWriting) {
- log("Warning: skipping " + archiveType + " archive "
- + zipFile + " because no files were included.",
- Project.MSG_WARN);
- }
- return true;
- } else if (emptyBehavior.equals("fail")) {
- throw new BuildException("Cannot create " + archiveType
- + " archive " + zipFile
- + ": no files were included.",
- getLocation());
- }
-
- ZipOutputStream zOut = null;
- try {
- if (!skipWriting) {
- log("Building MANIFEST-only jar: "
- + getDestFile().getAbsolutePath());
- }
- zOut = new ZipOutputStream(getDestFile());
-
- zOut.setEncoding(getEncoding());
- if (isCompress()) {
- zOut.setMethod(ZipOutputStream.DEFLATED);
- } else {
- zOut.setMethod(ZipOutputStream.STORED);
- }
- initZipOutputStream(zOut);
- finalizeZipOutputStream(zOut);
- } catch (IOException ioe) {
- throw new BuildException("Could not create almost empty JAR archive"
- + " (" + ioe.getMessage() + ")", ioe,
- getLocation());
- } finally {
- // Close the output stream.
- FileUtils.close(zOut);
- createEmpty = false;
- }
- return true;
- }
-
- /**
- * Make sure we don't think we already have a MANIFEST next time this task
- * gets executed.
- *
- * @see Zip#cleanUp
- */
- protected void cleanUp() {
- super.cleanUp();
- checkJarSpec();
-
- // we want to save this info if we are going to make another pass
- if (!doubleFilePass || !skipWriting) {
- manifest = null;
- configuredManifest = savedConfiguredManifest;
- filesetManifest = null;
- originalManifest = null;
- }
- rootEntries.removeAllElements();
- }
-
- // CheckStyle:LineLength OFF - Link is too long.
- /**
- * Check against packaging spec
- * @see "http://java.sun.com/j2se/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersioning"
- */
- // CheckStyle:LineLength ON
- private void checkJarSpec() {
- String br = System.getProperty("line.separator");
- StringBuffer message = new StringBuffer();
- Section mainSection = (configuredManifest == null)
- ? null
- : configuredManifest.getMainSection();
-
- if (mainSection == null) {
- message.append("No Implementation-Title set.");
- message.append("No Implementation-Version set.");
- message.append("No Implementation-Vendor set.");
- } else {
- if (mainSection.getAttribute("Implementation-Title") == null) {
- message.append("No Implementation-Title set.");
- }
- if (mainSection.getAttribute("Implementation-Version") == null) {
- message.append("No Implementation-Version set.");
- }
- if (mainSection.getAttribute("Implementation-Vendor") == null) {
- message.append("No Implementation-Vendor set.");
- }
- }
-
- if (message.length() > 0) {
- message.append(br);
- message.append("Location: ").append(getLocation());
- message.append(br);
- if (strict.getValue().equalsIgnoreCase("fail")) {
- throw new BuildException(message.toString(), getLocation());
- } else {
- logWhenWriting(message.toString(), strict.getLogLevel());
- }
- }
- }
-
- /**
- * reset to default values.
- *
- * @see Zip#reset
- *
- * @since 1.44, Ant 1.5
- */
- public void reset() {
- super.reset();
- emptyBehavior = "create";
- configuredManifest = null;
- filesetManifestConfig = null;
- mergeManifestsMain = false;
- manifestFile = null;
- index = false;
- }
-
- /**
- * The manifest config enumerated type.
- */
- public static class FilesetManifestConfig extends EnumeratedAttribute {
- /**
- * Get the list of valid strings.
- * @return the list of values - "skip", "merge" and "mergewithoutmain"
- */
- public String[] getValues() {
- return new String[] {"skip", "merge", "mergewithoutmain"};
- }
- }
-
- /**
- * Writes the directory entries from the first and the filenames
- * from the second list to the given writer, one entry per line.
- *
- * @param dirs a list of directories
- * @param files a list of files
- * @param writer the writer to write to
- * @throws IOException on error
- * @since Ant 1.6.2
- */
- protected final void writeIndexLikeList(List<String> dirs, List<String> files,
- PrintWriter writer)
- throws IOException {
- // JarIndex is sorting the directories by ascending order.
- // it has no value but cosmetic since it will be read into a
- // hashtable by the classloader, but we'll do so anyway.
- Collections.sort(dirs);
- Collections.sort(files);
- for (String dir : dirs) {
- // try to be smart, not to be fooled by a weird directory name
- dir = dir.replace('\\', '/');
- if (dir.startsWith("./")) {
- dir = dir.substring(2);
- }
- while (dir.startsWith("/")) {
- dir = dir.substring(1);
- }
- int pos = dir.lastIndexOf('/');
- if (pos != -1) {
- dir = dir.substring(0, pos);
- }
-
- // looks like nothing from META-INF should be added
- // and the check is not case insensitive.
- // see sun.misc.JarIndex
- // see also
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4408526
- if (!indexMetaInf && dir.startsWith("META-INF")) {
- continue;
- }
- // name newline
- writer.println(dir);
- }
-
- for (String file : files) {
- writer.println(file);
- }
- }
-
- /**
- * try to guess the name of the given file.
- *
- * <p>If this jar has a classpath attribute in its manifest, we
- * can assume that it will only require an index of jars listed
- * there. try to find which classpath entry is most likely the
- * one the given file name points to.</p>
- *
- * <p>In the absence of a classpath attribute, assume the other
- * files will be placed inside the same directory as this jar and
- * use their basename.</p>
- *
- * <p>if there is a classpath and the given file doesn't match any
- * of its entries, return null.</p>
- *
- * @param fileName the name to look for
- * @param classpath the classpath to look in (may be null)
- * @return the matching entry, or null if the file is not found
- * @since Ant 1.6.2
- */
- protected static String findJarName(String fileName,
- String[] classpath) {
- if (classpath == null) {
- return (new File(fileName)).getName();
- }
- fileName = fileName.replace(File.separatorChar, '/');
- TreeMap<String, String> matches = new TreeMap<String, String>(new Comparator<Object>() {
- // longest match comes first
- public int compare(Object o1, Object o2) {
- if (o1 instanceof String && o2 instanceof String) {
- return ((String) o2).length()
- - ((String) o1).length();
- }
- return 0;
- }
- });
-
- for (int i = 0; i < classpath.length; i++) {
- if (fileName.endsWith(classpath[i])) {
- matches.put(classpath[i], classpath[i]);
- } else {
- int slash = classpath[i].indexOf("/");
- String candidate = classpath[i];
- while (slash > -1) {
- candidate = candidate.substring(slash + 1);
- if (fileName.endsWith(candidate)) {
- matches.put(candidate, classpath[i]);
- break;
- }
- slash = candidate.indexOf("/");
- }
- }
- }
-
- return matches.size() == 0
- ? null : (String) matches.get(matches.firstKey());
- }
-
- /**
- * Grab lists of all root-level files and all directories
- * contained in the given archive.
- * @param file the zip file to examine
- * @param dirs where to place the directories found
- * @param files where to place the files found
- * @since Ant 1.7
- * @throws IOException on error
- */
- protected static void grabFilesAndDirs(String file, List<String> dirs,
- List<String> files)
- throws IOException {
- org.apache.tools.zip.ZipFile zf = null;
- try {
- zf = new org.apache.tools.zip.ZipFile(file, "utf-8");
- Enumeration<org.apache.tools.zip.ZipEntry> entries = zf.getEntries();
- HashSet<String> dirSet = new HashSet<String>();
- while (entries.hasMoreElements()) {
- org.apache.tools.zip.ZipEntry ze =
- entries.nextElement();
- String name = ze.getName();
- if (ze.isDirectory()) {
- dirSet.add(name);
- } else if (name.indexOf("/") == -1) {
- files.add(name);
- } else {
- // a file, not in the root
- // since the jar may be one without directory
- // entries, add the parent dir of this file as
- // well.
- dirSet.add(name.substring(0, name.lastIndexOf("/") + 1));
- }
- }
- dirs.addAll(dirSet);
- } finally {
- if (zf != null) {
- zf.close();
- }
- }
- }
-
- private Resource[][] grabManifests(ResourceCollection[] rcs) {
- Resource[][] manifests = new Resource[rcs.length][];
- for (int i = 0; i < rcs.length; i++) {
- Resource[][] resources = null;
- if (rcs[i] instanceof FileSet) {
- resources = grabResources(new FileSet[] {(FileSet) rcs[i]});
- } else {
- resources = grabNonFileSetResources(new ResourceCollection[] {
- rcs[i]
- });
- }
- for (int j = 0; j < resources[0].length; j++) {
- String name = resources[0][j].getName().replace('\\', '/');
- if (rcs[i] instanceof ArchiveFileSet) {
- ArchiveFileSet afs = (ArchiveFileSet) rcs[i];
- if (!"".equals(afs.getFullpath(getProject()))) {
- name = afs.getFullpath(getProject());
- } else if (!"".equals(afs.getPrefix(getProject()))) {
- String prefix = afs.getPrefix(getProject());
- if (!prefix.endsWith("/") && !prefix.endsWith("\\")) {
- prefix += "/";
- }
- name = prefix + name;
- }
- }
- if (name.equalsIgnoreCase(MANIFEST_NAME)) {
- manifests[i] = new Resource[] {resources[0][j]};
- break;
- }
- }
- if (manifests[i] == null) {
- manifests[i] = new Resource[0];
- }
- }
- return manifests;
- }
-
- /** The strict enumerated type. */
- public static class StrictMode extends EnumeratedAttribute {
- /** Public no arg constructor. */
- public StrictMode() {
- }
- /**
- * Constructor with an arg.
- * @param value the enumerated value as a string.
- */
- public StrictMode(String value) {
- setValue(value);
- }
- /**
- * Get List of valid strings.
- * @return the list of values.
- */
- public String[] getValues() {
- return new String[]{"fail", "warn", "ignore"};
- }
- /**
- * @return The log level according to the strict mode.
- */
- public int getLogLevel() {
- return (getValue().equals("ignore")) ? Project.MSG_VERBOSE : Project.MSG_WARN;
- }
- }
-}