/** Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.util.jar;import java.io.DataOutputStream;import java.io.IOException;import java.util.Collection;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;import java.util.Objects;import java.util.Set;import sun.util.logging.PlatformLogger;/*** The Attributes class maps Manifest attribute names to associated string* values. Valid attribute names are case-insensitive, are restricted to* the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70* characters in length. There must be a colon and a SPACE after the name;* the combined length will not exceed 72 characters.* Attribute values can contain any characters and* will be UTF8-encoded when written to the output stream. See the* <a href="{@docRoot}/../specs/jar/jar.html">JAR File Specification</a>* for more information about valid attribute names and values.** <p>This map and its views have a predictable iteration order, namely the* order that keys were inserted into the map, as with {@link LinkedHashMap}.** @author David Connelly* @see Manifest* @since 1.2*/public class Attributes implements Map<Object,Object>, Cloneable {/*** The attribute name-value mappings.*/protected Map<Object,Object> map;/*** Constructs a new, empty Attributes object with default size.*/public Attributes() {this(11);}/*** Constructs a new, empty Attributes object with the specified* initial size.** @param size the initial number of attributes*/public Attributes(int size) {map = new LinkedHashMap<>(size);}/*** Constructs a new Attributes object with the same attribute name-value* mappings as in the specified Attributes.** @param attr the specified Attributes*/public Attributes(Attributes attr) {map = new LinkedHashMap<>(attr);}/*** Returns the value of the specified attribute name, or null if the* attribute name was not found.** @param name the attribute name* @return the value of the specified attribute name, or null if* not found.*/public Object get(Object name) {return map.get(name);}/*** Returns the value of the specified attribute name, specified as* a string, or null if the attribute was not found. The attribute* name is case-insensitive.* <p>* This method is defined as:* <pre>* return (String)get(new Attributes.Name((String)name));* </pre>** @param name the attribute name as a string* @return the String value of the specified attribute name, or null if* not found.* @throws IllegalArgumentException if the attribute name is invalid*/public String getValue(String name) {return (String)get(Name.of(name));}/*** Returns the value of the specified Attributes.Name, or null if the* attribute was not found.* <p>* This method is defined as:* <pre>* return (String)get(name);* </pre>** @param name the Attributes.Name object* @return the String value of the specified Attribute.Name, or null if* not found.*/public String getValue(Name name) {return (String)get(name);}/*** Associates the specified value with the specified attribute name* (key) in this Map. If the Map previously contained a mapping for* the attribute name, the old value is replaced.** @param name the attribute name* @param value the attribute value* @return the previous value of the attribute, or null if none* @exception ClassCastException if the name is not a Attributes.Name* or the value is not a String*/public Object put(Object name, Object value) {return map.put((Attributes.Name)name, (String)value);}/*** Associates the specified value with the specified attribute name,* specified as a String. The attributes name is case-insensitive.* If the Map previously contained a mapping for the attribute name,* the old value is replaced.* <p>* This method is defined as:* <pre>* return (String)put(new Attributes.Name(name), value);* </pre>** @param name the attribute name as a string* @param value the attribute value* @return the previous value of the attribute, or null if none* @exception IllegalArgumentException if the attribute name is invalid*/public String putValue(String name, String value) {return (String)put(Name.of(name), value);}/*** Removes the attribute with the specified name (key) from this Map.* Returns the previous attribute value, or null if none.** @param name attribute name* @return the previous value of the attribute, or null if none*/public Object remove(Object name) {return map.remove(name);}/*** Returns true if this Map maps one or more attribute names (keys)* to the specified value.** @param value the attribute value* @return true if this Map maps one or more attribute names to* the specified value*/public boolean containsValue(Object value) {return map.containsValue(value);}/*** Returns true if this Map contains the specified attribute name (key).** @param name the attribute name* @return true if this Map contains the specified attribute name*/public boolean containsKey(Object name) {return map.containsKey(name);}/*** Copies all of the attribute name-value mappings from the specified* Attributes to this Map. Duplicate mappings will be replaced.** @param attr the Attributes to be stored in this map* @exception ClassCastException if attr is not an Attributes*/public void putAll(Map<?,?> attr) {// ## javac bug?if (!Attributes.class.isInstance(attr))throw new ClassCastException();for (Map.Entry<?,?> me : (attr).entrySet())put(me.getKey(), me.getValue());}/*** Removes all attributes from this Map.*/public void clear() {map.clear();}/*** Returns the number of attributes in this Map.*/public int size() {return map.size();}/*** Returns true if this Map contains no attributes.*/public boolean isEmpty() {return map.isEmpty();}/*** Returns a Set view of the attribute names (keys) contained in this Map.*/public Set<Object> keySet() {return map.keySet();}/*** Returns a Collection view of the attribute values contained in this Map.*/public Collection<Object> values() {return map.values();}/*** Returns a Collection view of the attribute name-value mappings* contained in this Map.*/public Set<Map.Entry<Object,Object>> entrySet() {return map.entrySet();}/*** Compares the specified Attributes object with this Map for equality.* Returns true if the given object is also an instance of Attributes* and the two Attributes objects represent the same mappings.** @param o the Object to be compared* @return true if the specified Object is equal to this Map*/public boolean equals(Object o) {return map.equals(o);}/*** Returns the hash code value for this Map.*/public int hashCode() {return map.hashCode();}/*** Returns a copy of the Attributes, implemented as follows:* <pre>* public Object clone() { return new Attributes(this); }* </pre>* Since the attribute names and values are themselves immutable,* the Attributes returned can be safely modified without affecting* the original.*/public Object clone() {return new Attributes(this);}/** Writes the current attributes to the specified data output stream.* XXX Need to handle UTF8 values and break up lines longer than 72 bytes*/@SuppressWarnings("deprecation")void write(DataOutputStream os) throws IOException {for (Entry<Object, Object> e : entrySet()) {StringBuffer buffer = new StringBuffer(((Name) e.getKey()).toString());buffer.append(": ");String value = (String) e.getValue();if (value != null) {byte[] vb = value.getBytes("UTF8");value = new String(vb, 0, 0, vb.length);}buffer.append(value);Manifest.make72Safe(buffer);buffer.append("\r\n");os.writeBytes(buffer.toString());}os.writeBytes("\r\n");}/** Writes the current attributes to the specified data output stream,* make sure to write out the MANIFEST_VERSION or SIGNATURE_VERSION* attributes first.** XXX Need to handle UTF8 values and break up lines longer than 72 bytes*/@SuppressWarnings("deprecation")void writeMain(DataOutputStream out) throws IOException{// write out the *-Version header first, if it existsString vername = Name.MANIFEST_VERSION.toString();String version = getValue(vername);if (version == null) {vername = Name.SIGNATURE_VERSION.toString();version = getValue(vername);}if (version != null) {out.writeBytes(vername+": "+version+"\r\n");}// write out all attributes except for the version// we wrote out earlierfor (Entry<Object, Object> e : entrySet()) {String name = ((Name) e.getKey()).toString();if ((version != null) && !(name.equalsIgnoreCase(vername))) {StringBuffer buffer = new StringBuffer(name);buffer.append(": ");String value = (String) e.getValue();if (value != null) {byte[] vb = value.getBytes("UTF8");value = new String(vb, 0, 0, vb.length);}buffer.append(value);Manifest.make72Safe(buffer);buffer.append("\r\n");out.writeBytes(buffer.toString());}}out.writeBytes("\r\n");}/** Reads attributes from the specified input stream.* XXX Need to handle UTF8 values.*/@SuppressWarnings("deprecation")void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException {String name = null, value;byte[] lastline = null;int len;while ((len = is.readLine(lbuf)) != -1) {boolean lineContinued = false;byte c = lbuf[--len];if (c != '\n' && c != '\r') {throw new IOException("line too long");}if (len > 0 && lbuf[len-1] == '\r') {--len;}if (len == 0) {break;}int i = 0;if (lbuf[0] == ' ') {// continuation of previous lineif (name == null) {throw new IOException("misplaced continuation line");}lineContinued = true;byte[] buf = new byte[lastline.length + len - 1];System.arraycopy(lastline, 0, buf, 0, lastline.length);System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);if (is.peek() == ' ') {lastline = buf;continue;}value = new String(buf, 0, buf.length, "UTF8");lastline = null;} else {while (lbuf[i++] != ':') {if (i >= len) {throw new IOException("invalid header field");}}if (lbuf[i++] != ' ') {throw new IOException("invalid header field");}name = new String(lbuf, 0, 0, i - 2);if (is.peek() == ' ') {lastline = new byte[len - i];System.arraycopy(lbuf, i, lastline, 0, len - i);continue;}value = new String(lbuf, i, len - i, "UTF8");}try {if ((putValue(name, value) != null) && (!lineContinued)) {PlatformLogger.getLogger("java.util.jar").warning("Duplicate name in Manifest: " + name+ ".\n"+ "Ensure that the manifest does not "+ "have duplicate entries, and\n"+ "that blank lines separate "+ "individual sections in both your\n"+ "manifest and in the META-INF/MANIFEST.MF "+ "entry in the jar file.");}} catch (IllegalArgumentException e) {throw new IOException("invalid header field name: " + name);}}}/*** The Attributes.Name class represents an attribute name stored in* this Map. Valid attribute names are case-insensitive, are restricted* to the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed* 70 characters in length. Attribute values can contain any characters* and will be UTF8-encoded when written to the output stream. See the* <a href="{@docRoot}/../specs/jar/jar.html">JAR File Specification</a>* for more information about valid attribute names and values.*/public static class Name {private final String name;private final int hashCode;/*** Avoid allocation for common Names*/private static final Map<String, Name> KNOWN_NAMES;static final Name of(String name) {Name n = KNOWN_NAMES.get(name);if (n != null) {return n;}return new Name(name);}/*** Constructs a new attribute name using the given string name.** @param name the attribute string name* @exception IllegalArgumentException if the attribute name was* invalid* @exception NullPointerException if the attribute name was null*/public Name(String name) {this.hashCode = hash(name);this.name = name.intern();}// Checks the string is validprivate final int hash(String name) {Objects.requireNonNull(name, "name");int len = name.length();if (len > 70 || len == 0) {throw new IllegalArgumentException(name);}// Calculate hash code case insensitivelyint h = 0;for (int i = 0; i < len; i++) {char c = name.charAt(i);if (c >= 'a' && c <= 'z') {// hashcode must be identical for upper and lower caseh = h * 31 + (c - 0x20);} else if ((c >= 'A' && c <= 'Z' ||c >= '0' && c <= '9' ||c == '_' || c == '-')) {h = h * 31 + c;} else {throw new IllegalArgumentException(name);}}return h;}/*** Compares this attribute name to another for equality.* @param o the object to compare* @return true if this attribute name is equal to the* specified attribute object*/public boolean equals(Object o) {if (this == o) {return true;}if (o instanceof Name) {Name other = (Name)o;return other.name.equalsIgnoreCase(name);} else {return false;}}/*** Computes the hash value for this attribute name.*/public int hashCode() {return hashCode;}/*** Returns the attribute name as a String.*/public String toString() {return name;}/*** {@code Name} object for {@code Manifest-Version}* manifest attribute. This attribute indicates the version number* of the manifest standard to which a JAR file's manifest conforms.* @see <a href="{@docRoot}/../specs/jar/jar.html#JAR_Manifest">* Manifest and Signature Specification</a>*/public static final Name MANIFEST_VERSION = new Name("Manifest-Version");/*** {@code Name} object for {@code Signature-Version}* manifest attribute used when signing JAR files.* @see <a href="{@docRoot}/../specs/jar/jar.html#JAR_Manifest">* Manifest and Signature Specification</a>*/public static final Name SIGNATURE_VERSION = new Name("Signature-Version");/*** {@code Name} object for {@code Content-Type}* manifest attribute.*/public static final Name CONTENT_TYPE = new Name("Content-Type");/*** {@code Name} object for {@code Class-Path}* manifest attribute.* @see <a href="{@docRoot}/../specs/jar/jar.html#classpath">* JAR file specification</a>*/public static final Name CLASS_PATH = new Name("Class-Path");/*** {@code Name} object for {@code Main-Class} manifest* attribute used for launching applications packaged in JAR files.* The {@code Main-Class} attribute is used in conjunction* with the {@code -jar} command-line option of the* {@code java} application launcher.*/public static final Name MAIN_CLASS = new Name("Main-Class");/*** {@code Name} object for {@code Sealed} manifest attribute* used for sealing.* @see <a href="{@docRoot}/../specs/jar/jar.html#package-sealing">* Package Sealing</a>*/public static final Name SEALED = new Name("Sealed");/*** {@code Name} object for {@code Extension-List} manifest attribute* used for the extension mechanism that is no longer supported.*/public static final Name EXTENSION_LIST = new Name("Extension-List");/*** {@code Name} object for {@code Extension-Name} manifest attribute.* used for the extension mechanism that is no longer supported.*/public static final Name EXTENSION_NAME = new Name("Extension-Name");/*** {@code Name} object for {@code Extension-Installation} manifest attribute.** @deprecated Extension mechanism is no longer supported.*/@Deprecatedpublic static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation");/*** {@code Name} object for {@code Implementation-Title}* manifest attribute used for package versioning.*/public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title");/*** {@code Name} object for {@code Implementation-Version}* manifest attribute used for package versioning.*/public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version");/*** {@code Name} object for {@code Implementation-Vendor}* manifest attribute used for package versioning.*/public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");/*** {@code Name} object for {@code Implementation-Vendor-Id}* manifest attribute.** @deprecated Extension mechanism is no longer supported.*/@Deprecatedpublic static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");/*** {@code Name} object for {@code Implementation-URL}* manifest attribute.** @deprecated Extension mechanism is no longer supported.*/@Deprecatedpublic static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");/*** {@code Name} object for {@code Specification-Title}* manifest attribute used for package versioning.*/public static final Name SPECIFICATION_TITLE = new Name("Specification-Title");/*** {@code Name} object for {@code Specification-Version}* manifest attribute used for package versioning.*/public static final Name SPECIFICATION_VERSION = new Name("Specification-Version");/*** {@code Name} object for {@code Specification-Vendor}* manifest attribute used for package versioning.*/public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");/*** {@code Name} object for {@code Multi-Release}* manifest attribute that indicates this is a multi-release JAR file.** @since 9*/public static final Name MULTI_RELEASE = new Name("Multi-Release");private static void addName(Map<String, Name> names, Name name) {names.put(name.name, name);}static {var names = new HashMap<String, Name>(64);addName(names, MANIFEST_VERSION);addName(names, SIGNATURE_VERSION);addName(names, CONTENT_TYPE);addName(names, CLASS_PATH);addName(names, MAIN_CLASS);addName(names, SEALED);addName(names, EXTENSION_LIST);addName(names, EXTENSION_NAME);addName(names, IMPLEMENTATION_TITLE);addName(names, IMPLEMENTATION_VERSION);addName(names, IMPLEMENTATION_VENDOR);addName(names, SPECIFICATION_TITLE);addName(names, SPECIFICATION_VERSION);addName(names, SPECIFICATION_VENDOR);addName(names, MULTI_RELEASE);// Common attributes used in MANIFEST.MF et.al; adding these has a// small footprint cost, but is likely to be quickly paid for by// reducing allocation when reading and parsing typical manifestsaddName(names, new Name("Add-Exports"));addName(names, new Name("Add-Opens"));addName(names, new Name("Ant-Version"));addName(names, new Name("Archiver-Version"));addName(names, new Name("Build-Jdk"));addName(names, new Name("Built-By"));addName(names, new Name("Bnd-LastModified"));addName(names, new Name("Bundle-Description"));addName(names, new Name("Bundle-DocURL"));addName(names, new Name("Bundle-License"));addName(names, new Name("Bundle-ManifestVersion"));addName(names, new Name("Bundle-Name"));addName(names, new Name("Bundle-Vendor"));addName(names, new Name("Bundle-Version"));addName(names, new Name("Bundle-SymbolicName"));addName(names, new Name("Created-By"));addName(names, new Name("Export-Package"));addName(names, new Name("Import-Package"));addName(names, new Name("Name"));addName(names, new Name("SHA1-Digest"));addName(names, new Name("X-Compile-Source-JDK"));addName(names, new Name("X-Compile-Target-JDK"));KNOWN_NAMES = names;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。