| /* |
| * 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 java.util.jar; |
| |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * The {@code Attributes} class is used to store values for manifest entries. |
| * Attribute keys are generally instances of {@code Attributes.Name}. Values |
| * associated with attribute keys are of type {@code String}. |
| */ |
| public class Attributes implements Cloneable, Map<Object, Object> { |
| |
| /** |
| * The {@code Attributes} as name/value pairs. Maps the attribute names (as |
| * {@link Attributes.Name}) of a JAR file manifest to arbitrary values. The |
| * attribute names thus are obtained from the {@link Manifest} for |
| * convenience. |
| */ |
| protected Map<Object, Object> map; |
| |
| /** |
| * The name part of the name/value pairs constituting an attribute as |
| * defined by the specification of the JAR manifest. May be composed of the |
| * following ASCII signs as defined in the EBNF below: |
| * |
| * <pre> |
| * name = alphanum *headerchar |
| * headerchar = alphanum | - | _ |
| * alphanum = {A-Z} | {a-z} | {0-9} |
| * </pre> |
| */ |
| public static class Name { |
| private final String name; |
| |
| /** The class path (a main attribute). */ |
| public static final Name CLASS_PATH = new Name("Class-Path"); |
| |
| /** The version of the manifest file (a main attribute). */ |
| public static final Name MANIFEST_VERSION = new Name("Manifest-Version"); |
| |
| /** The main class's name (for stand-alone applications). */ |
| public static final Name MAIN_CLASS = new Name("Main-Class"); |
| |
| /** Defines the signature version of the JAR file. */ |
| public static final Name SIGNATURE_VERSION = new Name("Signature-Version"); |
| |
| /** The {@code Content-Type} manifest attribute. */ |
| public static final Name CONTENT_TYPE = new Name("Content-Type"); |
| |
| /** |
| * The {@code Sealed} manifest attribute which may have the value |
| * {@code true} for sealed archives. |
| */ |
| public static final Name SEALED = new Name("Sealed"); |
| |
| /** |
| * The {@code Implementation-Title} attribute whose value is a string |
| * that defines the title of the extension implementation. |
| */ |
| public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title"); |
| |
| /** |
| * The {@code Implementation-Version} attribute defining the version of |
| * the extension implementation. |
| */ |
| public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version"); |
| |
| /** |
| * The {@code Implementation-Vendor} attribute defining the organization |
| * that maintains the extension implementation. |
| */ |
| public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor"); |
| |
| /** |
| * The {@code Specification-Title} attribute defining the title of the |
| * extension specification. |
| */ |
| public static final Name SPECIFICATION_TITLE = new Name("Specification-Title"); |
| |
| /** |
| * The {@code Specification-Version} attribute defining the version of |
| * the extension specification. |
| */ |
| public static final Name SPECIFICATION_VERSION = new Name("Specification-Version"); |
| |
| /** |
| * The {@code Specification-Vendor} attribute defining the organization |
| * that maintains the extension specification. |
| */ |
| public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); |
| |
| /** |
| * The {@code Extension-List} attribute defining the extensions that are |
| * needed by the applet. |
| */ |
| public static final Name EXTENSION_LIST = new Name("Extension-List"); |
| |
| /** |
| * The {@code Extension-Name} attribute which defines the unique name of |
| * the extension. |
| */ |
| public static final Name EXTENSION_NAME = new Name("Extension-Name"); |
| |
| /** |
| * The {@code Extension-Installation} attribute. |
| */ |
| public static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation"); |
| |
| /** |
| * The {@code Implementation-Vendor-Id} attribute specifies the vendor |
| * of an extension implementation if the applet requires an |
| * implementation from a specific vendor. |
| */ |
| public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id"); |
| |
| /** |
| * The {@code Implementation-URL} attribute specifying a URL that can be |
| * used to obtain the most recent version of the extension if the |
| * required version is not already installed. |
| */ |
| public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL"); |
| |
| static final Name NAME = new Name("Name"); |
| |
| public Name(String name) { |
| // encoded name + "\r\n" must be <= 72 bytes; ASCII-only so byte count equals char count |
| if (name.isEmpty() || name.length() > Manifest.LINE_LENGTH_LIMIT - 2) { |
| throw new IllegalArgumentException(name); |
| } |
| |
| for (int i = 0; i < name.length(); i++) { |
| char ch = name.charAt(i); |
| if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') |
| || ch == '_' || ch == '-' || (ch >= '0' && ch <= '9'))) { |
| throw new IllegalArgumentException(name); |
| } |
| } |
| |
| this.name = name; |
| } |
| |
| String getName() { |
| return name; |
| } |
| |
| @Override public boolean equals(Object object) { |
| return object instanceof Name |
| && ((Name) object).name.equalsIgnoreCase(name); |
| } |
| |
| @Override public int hashCode() { |
| return name.toLowerCase(Locale.US).hashCode(); |
| } |
| |
| @Override public String toString() { |
| return name; |
| } |
| } |
| |
| /** |
| * Constructs an {@code Attributes} instance. |
| */ |
| public Attributes() { |
| map = new HashMap<Object, Object>(); |
| } |
| |
| /** |
| * Constructs an {@code Attributes} instance obtaining keys and values from |
| * the parameter {@code attrib}. |
| * |
| * @param attrib |
| * The attributes to obtain entries from. |
| */ |
| @SuppressWarnings("unchecked") |
| public Attributes(Attributes attrib) { |
| map = (Map<Object, Object>) ((HashMap) attrib.map).clone(); |
| } |
| |
| /** |
| * Constructs an {@code Attributes} instance with initial capacity of size |
| * {@code size}. |
| * |
| * @param size |
| * Initial size of this {@code Attributes} instance. |
| */ |
| public Attributes(int size) { |
| map = new HashMap<Object, Object>(size); |
| } |
| |
| /** |
| * Removes all key/value pairs from this {@code Attributes}. |
| */ |
| public void clear() { |
| map.clear(); |
| } |
| |
| /** |
| * Determines whether this {@code Attributes} contains the specified key. |
| * |
| * @param key |
| * The key to search for. |
| * @return {@code true} if the key is found, {@code false} otherwise. |
| */ |
| public boolean containsKey(Object key) { |
| return map.containsKey(key); |
| } |
| |
| /** |
| * Determines whether this {@code Attributes} contains the specified value. |
| * |
| * @param value |
| * the value to search for. |
| * @return {@code true} if the value is found, {@code false} otherwise. |
| */ |
| public boolean containsValue(Object value) { |
| return map.containsValue(value); |
| } |
| |
| /** |
| * Returns a set containing map entries for each of the key/value pair |
| * contained in this {@code Attributes}. |
| * |
| * @return a set of Map.Entry's |
| */ |
| public Set<Map.Entry<Object, Object>> entrySet() { |
| return map.entrySet(); |
| } |
| |
| /** |
| * Returns the value associated with the parameter key. |
| * |
| * @param key |
| * the key to search for. |
| * @return Object associated with key, or {@code null} if key does not |
| * exist. |
| */ |
| public Object get(Object key) { |
| return map.get(key); |
| } |
| |
| /** |
| * Determines whether this {@code Attributes} contains any keys. |
| * |
| * @return {@code true} if one or more keys exist, {@code false} otherwise. |
| */ |
| public boolean isEmpty() { |
| return map.isEmpty(); |
| } |
| |
| /** |
| * Returns a {@code Set} containing all the keys found in this {@code |
| * Attributes}. |
| * |
| * @return a {@code Set} of all keys. |
| */ |
| public Set<Object> keySet() { |
| return map.keySet(); |
| } |
| |
| /** |
| * Stores key/value pairs in this {@code Attributes}. |
| * |
| * @param key |
| * the key to associate with value. |
| * @param value |
| * the value to store in this {@code Attributes}. |
| * @return the value being stored. |
| * @exception ClassCastException |
| * when key is not an {@code Attributes.Name} or value is not |
| * a {@code String}. |
| */ |
| @SuppressWarnings("cast") |
| // Require cast to force ClassCastException |
| public Object put(Object key, Object value) { |
| return map.put((Name) key, (String) value); |
| } |
| |
| /** |
| * Stores all the key/value pairs in the argument in this {@code |
| * Attributes}. |
| * |
| * @param attrib |
| * the associations to store (must be of type {@code |
| * Attributes}). |
| */ |
| public void putAll(Map<?, ?> attrib) { |
| if (attrib == null || !(attrib instanceof Attributes)) { |
| throw new ClassCastException(attrib.getClass().getName() + " not an Attributes"); |
| } |
| this.map.putAll(attrib); |
| } |
| |
| /** |
| * Deletes the key/value pair with key {@code key} from this {@code |
| * Attributes}. |
| * |
| * @param key |
| * the key to remove. |
| * @return the values associated with the removed key, {@code null} if not |
| * present. |
| */ |
| public Object remove(Object key) { |
| return map.remove(key); |
| } |
| |
| /** |
| * Returns the number of key/value pairs associated with this {@code |
| * Attributes}. |
| * |
| * @return the size of this {@code Attributes}. |
| */ |
| public int size() { |
| return map.size(); |
| } |
| |
| /** |
| * Returns a collection of all the values present in this {@code |
| * Attributes}. |
| * |
| * @return a collection of all values present. |
| */ |
| public Collection<Object> values() { |
| return map.values(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Object clone() { |
| Attributes clone; |
| try { |
| clone = (Attributes) super.clone(); |
| } catch (CloneNotSupportedException e) { |
| throw new AssertionError(e); |
| } |
| clone.map = (Map<Object, Object>) ((HashMap) map).clone(); |
| return clone; |
| } |
| |
| /** |
| * Returns the hash code of this {@code Attributes}. |
| * |
| * @return the hash code of this object. |
| */ |
| @Override |
| public int hashCode() { |
| return map.hashCode(); |
| } |
| |
| /** |
| * Determines if this {@code Attributes} and the parameter {@code |
| * Attributes} are equal. Two {@code Attributes} instances are equal if they |
| * contain the same keys and values. |
| * |
| * @param obj |
| * the object with which this {@code Attributes} is compared. |
| * @return {@code true} if the {@code Attributes} are equal, {@code false} |
| * otherwise. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof Attributes) { |
| return map.equals(((Attributes) obj).map); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns the value associated with the parameter {@code Attributes.Name} |
| * key. |
| * |
| * @param name |
| * the key to obtain the value for. |
| * @return the {@code String} associated with name, or {@code null} if name |
| * is not a valid key. |
| */ |
| public String getValue(Attributes.Name name) { |
| return (String) map.get(name); |
| } |
| |
| /** |
| * Returns the string associated with the parameter name. |
| * |
| * @param name |
| * the key to obtain the value for. |
| * @return the string associated with name, or {@code null} if name is not a |
| * valid key. |
| */ |
| public String getValue(String name) { |
| return (String) map.get(new Attributes.Name(name)); |
| } |
| |
| /** |
| * Stores the value {@code val} associated with the key {@code name} in this |
| * {@code Attributes}. |
| * |
| * @param name |
| * the key to store. |
| * @param val |
| * the value to store in this {@code Attributes}. |
| * @return the value being stored. |
| */ |
| public String putValue(String name, String val) { |
| return (String) map.put(new Attributes.Name(name), val); |
| } |
| } |