📄 jar.java
字号:
/* * 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.FileOutputStream;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.Iterator;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.EnumeratedAttribute;import org.apache.tools.ant.types.Path;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 serviceList = new ArrayList(); /** 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 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 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 /** * 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"); rootEntries = new Vector(); } /** * 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; } /** * 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); } 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 e = zf.entries(); while (e.hasMoreElements()) { ZipEntry ze = (ZipEntry) 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) { // XXX - 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; } /** * 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -