OSDN Git Service

c8babddab377d0f7f582ea166604c034338f5ace
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / util / jar / Attributes.java
1 /* Attributes.java -- Represents attribute name/value pairs from a Manifest
2    Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package java.util.jar;
39
40 import java.util.Collection;
41 import java.util.Hashtable;
42 import java.util.Map;
43 import java.util.Set;
44
45 /**
46  * Represents attribute name/value pairs from a Manifest as a Map.
47  * The names of an attribute are represented by the
48  * <code>Attributes.Name</code> class and should confirm to the restrictions
49  * described in that class. Note that the Map interface that Attributes
50  * implements allows you to put names and values into the attribute that don't
51  * follow these restriction (and are not really Atrribute.Names, but if you do
52  * that it might cause undefined behaviour later).
53  * <p>
54  * If you use the constants defined in the inner class Name then you can be
55  * sure that you always access the right attribute names. This makes
56  * manipulating the Attributes more or less type safe.
57  * <p>
58  * Most of the methods are wrappers to implement the Map interface. The really
59  * useful and often used methods are <code>getValue(Name)</code> and
60  * <code>getValue(String)</code>. If you actually want to set attributes you
61  * may want to use the <code>putValue(String, String)</code> method
62  * (sorry there is no public type safe <code>putValue(Name, String)</code>
63  * method).
64  *
65  * @see java.util.jar.Attributes.Name
66  * @author Mark Wielaard (mark@klomp.org)
67  */
68 public class Attributes implements Cloneable, Map
69 {
70
71   // Fields
72
73   /**
74    * The map that holds all the attribute name/value pairs. In this
75    * implementation it is actually a Hashtable, but that can be different in
76    * other implementations.
77    */
78   protected Map map;
79
80   // Inner class
81
82   /**
83    * Represents a name of a Manifest Attribute. Defines a couple of well
84    * know names for the general main attributes, stand alone application
85    * attributes, applet attributes, extension identification attributes,
86    * package versioning and sealing attributes, file contents attributes,
87    * bean objects attribute and signing attributes. See the 
88    * 
89    * <p>The characters of a Name must obey the following restrictions:</p>
90    * 
91    * <ul>
92    * <li>Must contain at least one character</li>
93    * <li>The first character must be alphanumeric (a-z, A-Z, 0-9)</li>
94    * <li>All other characters must be alphanumeric, a '-' or a '_'</li>
95    * </ul>
96    * 
97    * <p>When comparing Names (with <code>equals</code>) all characters are
98    * converted to lowercase. But you can get the original case sensitive
99    * string with the <code>toString()</code> method.</p>
100    *
101    * <p>Most important attributes have a constant defined in this
102    * class. Some other attributes used in Manifest files are:
103    * <ul>
104    * <li> "Created-By" - General main attribute, tool and version
105    * that created this Manifest file.</li>
106    * <li> "Java-Bean" - Bean objects attribute, whether the entry is a Bean.
107    * Value is either "true" or "false".</li>
108    * <li> "Magic" - Signing attribute, application specific signing attribute.
109    * Must be understood by the manifest parser when present to validate the
110    * jar (entry).</li>
111    * </ul>
112    *
113    * @since 1.2
114    * @author Mark Wielaard (mark@klomp.org)
115    */
116   public static class Name
117   {
118     // General Main Attributes
119
120     /**
121      * General main attribute -
122      * the version of this Manifest file.
123      */
124     public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
125     
126     /**
127      * General main attribute -
128      * the version of the jar file signature.
129      */
130     public static final Name SIGNATURE_VERSION
131       = new Name("Signature-Version");
132     
133     /**
134      * General main attribute -
135      * (relative) file paths of the libraries/classpaths that the Classes in
136      * this jar file depend on. Paths are separated by spaces.
137      */
138     public static final Name CLASS_PATH = new Name("Class-Path");
139
140     /**
141      * Stand alone application attribute -
142      * the entry (without the .class ending) that is the main
143      * class of this jar file.
144      */
145     public static final Name MAIN_CLASS = new Name("Main-Class");
146
147     /**
148      * Applet attribute -
149      * a list of extension libraries that the applet in this
150      * jar file depends on.
151      * For every named extension there should be some Attributes in the
152      * Manifest manifest file with the following Names:
153      * <ul>
154      * <li> &lt;extension&gt;-Extension-Name:
155      * unique name of the extension</li>
156      * <li> &lt;extension&gt;-Specification-Version:
157      * minimum specification version</li>
158      * <li> &lt;extension&gt;-Implementation-Version:
159      * minimum implementation version</li>
160      * <li> &lt;extension&gt;-Implementation-Vendor-Id:
161      * unique id of implementation vendor</li>
162      * <li> &lt;extension&gt;-Implementation-URL:
163      * where the latest version of the extension library can be found</li>
164      * </ul>
165      */
166     public static final Name EXTENSION_LIST = new Name("Extension-List");
167
168     /**
169      * Extension identification attribute -
170      * the name if the extension library contained in the jar.
171      */
172     public static final Name EXTENSION_NAME = new Name("Extension-Name");
173     
174     /**
175      * Extension identification attribute -
176      * synonym for <code>EXTENSTION_NAME</code>.
177      */
178     public static final Name EXTENSION_INSTALLATION = EXTENSION_NAME;
179
180     // Package versioning and sealing attributes
181     
182     /**
183      * Package versioning -
184      * name of extension library contained in this jar.
185      */
186     public static final Name IMPLEMENTATION_TITLE
187       = new Name("Implementation-Title");
188     
189     /**
190      * Package versioning -
191      * version of the extension library contained in this jar.
192      */
193     public static final Name IMPLEMENTATION_VERSION
194       = new Name("Implementation-Version");
195     
196     /**
197      * Package versioning -
198      * name of extension library creator contained in this jar.
199      */
200     public static final Name IMPLEMENTATION_VENDOR
201       = new Name("Implementation-Vendor");
202     
203     /**
204      * Package versioning -
205      * unique id of extension library creator.
206      */
207     public static final Name IMPLEMENTATION_VENDOR_ID
208       = new Name("Implementation-Vendor-Id");
209     
210     /**
211      * Package versioning -
212      * location where this implementation can be downloaded.
213      */
214     public static final Name IMPLEMENTATION_URL
215       = new Name("Implementation-URL");
216     
217     /**
218      * Package versioning -
219      * title of the specification contained in this jar.
220      */
221     public static final Name SPECIFICATION_TITLE
222       = new Name("Specification-Title");
223
224     /**
225      * Package versioning -
226      * version of the specification contained in this jar.
227      */
228     public static final Name SPECIFICATION_VERSION
229       = new Name("Specification-Version");
230
231     /**
232      * Package versioning -
233      * organisation that maintains the specification contains in this
234      * jar.
235      */
236     public static final Name SPECIFICATION_VENDOR
237       = new Name("Specification-Vendor");
238
239     /**
240      * Package sealing -
241      * whether (all) package(s) is(/are) sealed. Value is either "true"
242      * or "false".
243      */
244     public static final Name SEALED = new Name("Sealed");
245
246     /**
247      * File contents attribute -
248      * Mime type and subtype for the jar entry.
249      */
250     public static final Name CONTENT_TYPE = new Name("Content-Type");
251
252     /** The (lowercase) String representation of this Name */
253     private final String name;
254
255     /** The original String given to the constructor */
256     private final String origName;
257
258     // Constructor
259
260     /**
261      * Creates a new Name from the given String.
262      * Throws an IllegalArgumentException if the given String is empty or
263      * contains any illegal Name characters.
264      * 
265      * @param name the name of the new Name
266      * @exception IllegalArgumentException if name isn't a valid String
267      * representation of a Name
268      * @exception NullPointerException if name is null
269      */
270     public Name(String name) throws IllegalArgumentException,
271       NullPointerException
272     {
273       // name must not be null
274       // this will throw a NullPointerException if it is
275       char chars[] = name.toCharArray();
276
277       // there must be at least one character
278       if (chars.length == 0)
279         throw new
280           IllegalArgumentException
281           ("There must be at least one character in a name");
282
283       // first character must be alphanum
284       char c = chars[0];
285       if (!((c >= 'a' && c <= 'z') ||
286             (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')))
287         throw new
288           IllegalArgumentException("First character must be alphanum");
289
290       // all other characters must be alphanums, '-' or '_'
291       for (int i = 1; i < chars.length; i++)
292         {
293           c = chars[i];
294           if (!((c >= 'a' && c <= 'z') ||
295                 (c >= 'A' && c <= 'Z') ||
296                 (c >= '0' && c <= '9') || (c == '-') || (c == '_')))
297             throw new
298               IllegalArgumentException
299               ("Characters must be alphanums, '-' or '_'");
300         }
301
302       // Still here? Then convert to lower case and be done.
303       // Store the original name for toString();
304       this.origName = name;
305       this.name = name.toLowerCase();
306     }
307
308     /**
309      * Returns the hash code of the (lowercase) String representation of
310      * this Name.
311      */
312     public int hashCode()
313     {
314       return name.hashCode();
315     }
316
317     /**
318      * Checks if another object is equal to this Name object.
319      * Another object is equal to this Name object if it is an instance of
320      * Name and the (lowercase) string representation of the name is equal.
321      */
322     public boolean equals(Object o)
323     {
324       // Quick and dirty check
325       if (name == o)
326         return true;
327
328       try
329         {
330           // Note that the constructor already converts the strings to
331           // lowercase.
332           String otherName = ((Name) o).name;
333           return name.equals(otherName);
334         }
335       catch (ClassCastException cce)
336         {
337           return false;
338         }
339       catch (NullPointerException npe)
340         {
341           return false;
342         }
343     }
344
345     /**
346      * Returns the string representation of this Name as given to the
347      * constructor (not neccesarily the lower case representation).
348      */
349     public String toString()
350     {
351       return origName;
352     }
353   }
354
355   // Constructors
356
357   /**
358    * Creates an empty Attributes map.
359    */
360   public Attributes()
361   {
362     map = new Hashtable();
363   }
364
365   /**
366    * Creates an empty Attributes map with the given initial size.
367    * @param size the initial size of the underlying map
368    */
369   public Attributes(int size)
370   {
371     map = new Hashtable(size);
372   }
373
374   /**
375    * Creates an Attributes map with the initial values taken from another
376    * Attributes map.
377    * @param attr Attributes map to take the initial values from
378    */
379   public Attributes(Attributes attr)
380   {
381     map = new Hashtable(attr.map);
382   }
383
384   // Methods
385
386   /**
387    * Gets the value of an attribute name given as a String.
388    *
389    * @param name a String describing the Name to look for
390    * @return the value gotten from the map of null when not found
391    */
392   public String getValue(String name)
393   {
394     return (String) get(new Name(name));
395   }
396
397   /**
398    * Gets the value of the given attribute name.
399    *
400    * @param name the Name to look for
401    * @return the value gotten from the map of null when not found
402    */
403   public String getValue(Name name)
404   {
405     return (String) get(name);
406   }
407
408   /**
409    * Stores an attribute name (represented by a String) and value in this
410    * Attributes map.
411    * When the (case insensitive string) name already exists the value is
412    * replaced and the old value is returned.
413    *
414    * @param name a (case insensitive) String representation of the attribite
415    * name to add/replace
416    * @param value the (new) value of the attribute name
417    * @returns the old value of the attribute name or null if it didn't exist
418    * yet
419    */
420   public String putValue(String name, String value)
421   {
422     return putValue(new Name(name), value);
423   }
424
425   /**
426    * Stores an attribute name (represented by a String) and value in this
427    * Attributes map.
428    * When the name already exists the value is replaced and the old value
429    * is returned.
430    *
431    * @param name the attribite name to add/replace
432    * @param value the (new) value of the attribute name
433    * @returns the old value of the attribute name or null if it didn't exist
434    * yet
435    */
436   public String putValue(Name name, String value)
437   {
438     return (String) put(name, value);
439   }
440
441   // Methods from Cloneable interface
442
443   /**
444    * Return a clone of this attribute map.
445    */
446   public Object clone()
447   {
448     return new Attributes(this);
449   }
450
451   // Methods from Map interface
452
453   /**
454    * Removes all attributes.
455    */
456   public void clear()
457   {
458     map.clear();
459   }
460
461   /**
462    * Checks to see if there is an attribute with the specified name.
463    * XXX - what if the object is a String?
464    *
465    * @param attrName the name of the attribute to check
466    * @return true if there is an attribute with the specified name, false
467    * otherwise
468    */
469   public boolean containsKey(Object attrName)
470   {
471     return map.containsKey(attrName);
472   }
473
474   /**
475    * Checks to see if there is an attribute name with the specified value.
476    *
477    * @param attrValue the value of a attribute to check
478    * @return true if there is an attribute name with the specified value,
479    * false otherwise
480    */
481   public boolean containsValue(Object attrValue)
482   {
483     return map.containsValue(attrValue);
484   }
485
486   /**
487    * Gives a Set of attribute name and values pairs as MapEntries.
488    * @see java.util.Map.Entry
489    * @see java.util.Map#entrySet()
490    *
491    * @return a set of attribute name value pairs
492    */
493   public Set entrySet()
494   {
495     return map.entrySet();
496   }
497
498   /**
499    * Checks to see if two Attributes are equal. The supplied object must be
500    * a real instance of Attributes and contain the same attribute name/value
501    * pairs.
502    *
503    * @param o another Attribute object which should be checked for equality
504    * @return true if the object is an instance of Attributes and contains the
505    * same name/value pairs, false otherwise
506    */
507   public boolean equals(Object o)
508   {
509     // quick and dirty check
510     if (this == o)
511       return true;
512
513     try
514       {
515         return map.equals(((Attributes) o).map);
516       }
517     catch (ClassCastException cce)
518       {
519         return false;
520       }
521     catch (NullPointerException npe)
522       {
523         return false;
524       }
525   }
526
527   /**
528    * Gets the value of a specified attribute name.
529    * XXX - what if the object is a String?
530    *
531    * @param attrName the name of the attribute we want the value of
532    * @return the value of the specified attribute name or null when there is
533    * no such attribute name
534    */
535   public Object get(Object attrName)
536   {
537     return map.get(attrName);
538   }
539
540   /**
541    * Returns the hashcode of the attribute name/value map.
542    */
543   public int hashCode()
544   {
545     return map.hashCode();
546   }
547
548   /**
549    * Returns true if there are no attributes set, false otherwise.
550    */
551   public boolean isEmpty()
552   {
553     return map.isEmpty();
554   }
555
556   /**
557    * Gives a Set of all the values of defined attribute names.
558    */
559   public Set keySet()
560   {
561     return map.keySet();
562   }
563
564   /**
565    * Adds or replaces a attribute name/value pair.
566    * XXX - What if the name is a string? What if the name is neither a Name
567    * nor a String? What if the value is not a string?
568    *
569    * @param name the name of the attribute
570    * @param value the (new) value of the attribute
571    * @return the old value of the attribute or null when there was no old
572    * attribute with this name
573    */
574   public Object put(Object name, Object value)
575   {
576     return map.put(name, value);
577   }
578
579   /**
580    * Adds or replaces all attribute name/value pairs from another
581    * Attributes object to this one. The supplied Map must be an instance of
582    * Attributes.
583    *
584    * @param attr the Attributes object to merge with this one
585    * @exception ClassCastException if the supplied map is not an instance of
586    * Attributes
587    */
588   public void putAll(Map attr)
589   {
590     if (!(attr instanceof Attributes))
591       {
592         throw new
593           ClassCastException("Supplied Map is not an instance of Attributes");
594       }
595     map.putAll(attr);
596   }
597
598   /**
599    * Remove a attribute name/value pair.
600    * XXX - What if the name is a String?
601    *
602    * @param name the name of the attribute name/value pair to remove
603    * @return the old value of the attribute or null if the attribute didn't
604    * exist
605    */
606   public Object remove(Object name)
607   {
608     return map.remove(name);
609   }
610
611   /**
612    * Returns the number of defined attribute name/value pairs.
613    */
614   public int size()
615   {
616     return map.size();
617   }
618
619   /**
620    * Returns all the values of the defined attribute name/value pairs as a
621    * Collection.
622    */
623   public Collection values()
624   {
625     return map.values();
626   }
627 }