J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package java.util.jar; |
| 27 | |
| 28 | import java.io.DataInputStream; |
| 29 | import java.io.DataOutputStream; |
| 30 | import java.io.IOException; |
| 31 | import java.util.HashMap; |
| 32 | import java.util.Map; |
| 33 | import java.util.Set; |
| 34 | import java.util.Collection; |
| 35 | import java.util.AbstractSet; |
| 36 | import java.util.Iterator; |
| 37 | import java.util.logging.Logger; |
| 38 | import java.util.Comparator; |
| 39 | import sun.misc.ASCIICaseInsensitiveComparator; |
| 40 | |
| 41 | /** |
| 42 | * The Attributes class maps Manifest attribute names to associated string |
| 43 | * values. Valid attribute names are case-insensitive, are restricted to |
| 44 | * the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70 |
| 45 | * characters in length. Attribute values can contain any characters and |
| 46 | * will be UTF8-encoded when written to the output stream. See the |
| 47 | * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> |
| 48 | * for more information about valid attribute names and values. |
| 49 | * |
| 50 | * @author David Connelly |
| 51 | * @see Manifest |
| 52 | * @since 1.2 |
| 53 | */ |
| 54 | public class Attributes implements Map<Object,Object>, Cloneable { |
| 55 | /** |
| 56 | * The attribute name-value mappings. |
| 57 | */ |
| 58 | protected Map<Object,Object> map; |
| 59 | |
| 60 | /** |
| 61 | * Constructs a new, empty Attributes object with default size. |
| 62 | */ |
| 63 | public Attributes() { |
| 64 | this(11); |
| 65 | } |
| 66 | |
| 67 | /** |
| 68 | * Constructs a new, empty Attributes object with the specified |
| 69 | * initial size. |
| 70 | * |
| 71 | * @param size the initial number of attributes |
| 72 | */ |
| 73 | public Attributes(int size) { |
| 74 | map = new HashMap(size); |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Constructs a new Attributes object with the same attribute name-value |
| 79 | * mappings as in the specified Attributes. |
| 80 | * |
| 81 | * @param attr the specified Attributes |
| 82 | */ |
| 83 | public Attributes(Attributes attr) { |
| 84 | map = new HashMap(attr); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | /** |
| 89 | * Returns the value of the specified attribute name, or null if the |
| 90 | * attribute name was not found. |
| 91 | * |
| 92 | * @param name the attribute name |
| 93 | * @return the value of the specified attribute name, or null if |
| 94 | * not found. |
| 95 | */ |
| 96 | public Object get(Object name) { |
| 97 | return map.get(name); |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Returns the value of the specified attribute name, specified as |
| 102 | * a string, or null if the attribute was not found. The attribute |
| 103 | * name is case-insensitive. |
| 104 | * <p> |
| 105 | * This method is defined as: |
| 106 | * <pre> |
| 107 | * return (String)get(new Attributes.Name((String)name)); |
| 108 | * </pre> |
| 109 | * |
| 110 | * @param name the attribute name as a string |
| 111 | * @return the String value of the specified attribute name, or null if |
| 112 | * not found. |
| 113 | * @throws IllegalArgumentException if the attribute name is invalid |
| 114 | */ |
| 115 | public String getValue(String name) { |
| 116 | return (String)get(new Attributes.Name(name)); |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Returns the value of the specified Attributes.Name, or null if the |
| 121 | * attribute was not found. |
| 122 | * <p> |
| 123 | * This method is defined as: |
| 124 | * <pre> |
| 125 | * return (String)get(name); |
| 126 | * </pre> |
| 127 | * |
| 128 | * @param name the Attributes.Name object |
| 129 | * @return the String value of the specified Attribute.Name, or null if |
| 130 | * not found. |
| 131 | */ |
| 132 | public String getValue(Name name) { |
| 133 | return (String)get(name); |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * Associates the specified value with the specified attribute name |
| 138 | * (key) in this Map. If the Map previously contained a mapping for |
| 139 | * the attribute name, the old value is replaced. |
| 140 | * |
| 141 | * @param name the attribute name |
| 142 | * @param value the attribute value |
| 143 | * @return the previous value of the attribute, or null if none |
| 144 | * @exception ClassCastException if the name is not a Attributes.Name |
| 145 | * or the value is not a String |
| 146 | */ |
| 147 | public Object put(Object name, Object value) { |
| 148 | return map.put((Attributes.Name)name, (String)value); |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * Associates the specified value with the specified attribute name, |
| 153 | * specified as a String. The attributes name is case-insensitive. |
| 154 | * If the Map previously contained a mapping for the attribute name, |
| 155 | * the old value is replaced. |
| 156 | * <p> |
| 157 | * This method is defined as: |
| 158 | * <pre> |
| 159 | * return (String)put(new Attributes.Name(name), value); |
| 160 | * </pre> |
| 161 | * |
| 162 | * @param name the attribute name as a string |
| 163 | * @param value the attribute value |
| 164 | * @return the previous value of the attribute, or null if none |
| 165 | * @exception IllegalArgumentException if the attribute name is invalid |
| 166 | */ |
| 167 | public String putValue(String name, String value) { |
| 168 | return (String)put(new Name(name), value); |
| 169 | } |
| 170 | |
| 171 | /** |
| 172 | * Removes the attribute with the specified name (key) from this Map. |
| 173 | * Returns the previous attribute value, or null if none. |
| 174 | * |
| 175 | * @param name attribute name |
| 176 | * @return the previous value of the attribute, or null if none |
| 177 | */ |
| 178 | public Object remove(Object name) { |
| 179 | return map.remove(name); |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * Returns true if this Map maps one or more attribute names (keys) |
| 184 | * to the specified value. |
| 185 | * |
| 186 | * @param value the attribute value |
| 187 | * @return true if this Map maps one or more attribute names to |
| 188 | * the specified value |
| 189 | */ |
| 190 | public boolean containsValue(Object value) { |
| 191 | return map.containsValue(value); |
| 192 | } |
| 193 | |
| 194 | /** |
| 195 | * Returns true if this Map contains the specified attribute name (key). |
| 196 | * |
| 197 | * @param name the attribute name |
| 198 | * @return true if this Map contains the specified attribute name |
| 199 | */ |
| 200 | public boolean containsKey(Object name) { |
| 201 | return map.containsKey(name); |
| 202 | } |
| 203 | |
| 204 | /** |
| 205 | * Copies all of the attribute name-value mappings from the specified |
| 206 | * Attributes to this Map. Duplicate mappings will be replaced. |
| 207 | * |
| 208 | * @param attr the Attributes to be stored in this map |
| 209 | * @exception ClassCastException if attr is not an Attributes |
| 210 | */ |
| 211 | public void putAll(Map<?,?> attr) { |
| 212 | // ## javac bug? |
| 213 | if (!Attributes.class.isInstance(attr)) |
| 214 | throw new ClassCastException(); |
| 215 | for (Map.Entry<?,?> me : (attr).entrySet()) |
| 216 | put(me.getKey(), me.getValue()); |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * Removes all attributes from this Map. |
| 221 | */ |
| 222 | public void clear() { |
| 223 | map.clear(); |
| 224 | } |
| 225 | |
| 226 | /** |
| 227 | * Returns the number of attributes in this Map. |
| 228 | */ |
| 229 | public int size() { |
| 230 | return map.size(); |
| 231 | } |
| 232 | |
| 233 | /** |
| 234 | * Returns true if this Map contains no attributes. |
| 235 | */ |
| 236 | public boolean isEmpty() { |
| 237 | return map.isEmpty(); |
| 238 | } |
| 239 | |
| 240 | /** |
| 241 | * Returns a Set view of the attribute names (keys) contained in this Map. |
| 242 | */ |
| 243 | public Set<Object> keySet() { |
| 244 | return map.keySet(); |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * Returns a Collection view of the attribute values contained in this Map. |
| 249 | */ |
| 250 | public Collection<Object> values() { |
| 251 | return map.values(); |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Returns a Collection view of the attribute name-value mappings |
| 256 | * contained in this Map. |
| 257 | */ |
| 258 | public Set<Map.Entry<Object,Object>> entrySet() { |
| 259 | return map.entrySet(); |
| 260 | } |
| 261 | |
| 262 | /** |
| 263 | * Compares the specified Attributes object with this Map for equality. |
| 264 | * Returns true if the given object is also an instance of Attributes |
| 265 | * and the two Attributes objects represent the same mappings. |
| 266 | * |
| 267 | * @param o the Object to be compared |
| 268 | * @return true if the specified Object is equal to this Map |
| 269 | */ |
| 270 | public boolean equals(Object o) { |
| 271 | return map.equals(o); |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * Returns the hash code value for this Map. |
| 276 | */ |
| 277 | public int hashCode() { |
| 278 | return map.hashCode(); |
| 279 | } |
| 280 | |
| 281 | /** |
| 282 | * Returns a copy of the Attributes, implemented as follows: |
| 283 | * <pre> |
| 284 | * public Object clone() { return new Attributes(this); } |
| 285 | * </pre> |
| 286 | * Since the attribute names and values are themselves immutable, |
| 287 | * the Attributes returned can be safely modified without affecting |
| 288 | * the original. |
| 289 | */ |
| 290 | public Object clone() { |
| 291 | return new Attributes(this); |
| 292 | } |
| 293 | |
| 294 | /* |
| 295 | * Writes the current attributes to the specified data output stream. |
| 296 | * XXX Need to handle UTF8 values and break up lines longer than 72 bytes |
| 297 | */ |
| 298 | void write(DataOutputStream os) throws IOException { |
| 299 | Iterator it = entrySet().iterator(); |
| 300 | while (it.hasNext()) { |
| 301 | Map.Entry e = (Map.Entry)it.next(); |
| 302 | StringBuffer buffer = new StringBuffer( |
| 303 | ((Name)e.getKey()).toString()); |
| 304 | buffer.append(": "); |
| 305 | |
| 306 | String value = (String)e.getValue(); |
| 307 | if (value != null) { |
| 308 | byte[] vb = value.getBytes("UTF8"); |
| 309 | value = new String(vb, 0, 0, vb.length); |
| 310 | } |
| 311 | buffer.append(value); |
| 312 | |
| 313 | buffer.append("\r\n"); |
| 314 | Manifest.make72Safe(buffer); |
| 315 | os.writeBytes(buffer.toString()); |
| 316 | } |
| 317 | os.writeBytes("\r\n"); |
| 318 | } |
| 319 | |
| 320 | /* |
| 321 | * Writes the current attributes to the specified data output stream, |
| 322 | * make sure to write out the MANIFEST_VERSION or SIGNATURE_VERSION |
| 323 | * attributes first. |
| 324 | * |
| 325 | * XXX Need to handle UTF8 values and break up lines longer than 72 bytes |
| 326 | */ |
| 327 | void writeMain(DataOutputStream out) throws IOException |
| 328 | { |
| 329 | // write out the *-Version header first, if it exists |
| 330 | String vername = Name.MANIFEST_VERSION.toString(); |
| 331 | String version = getValue(vername); |
| 332 | if (version == null) { |
| 333 | vername = Name.SIGNATURE_VERSION.toString(); |
| 334 | version = getValue(vername); |
| 335 | } |
| 336 | |
| 337 | if (version != null) { |
| 338 | out.writeBytes(vername+": "+version+"\r\n"); |
| 339 | } |
| 340 | |
| 341 | // write out all attributes except for the version |
| 342 | // we wrote out earlier |
| 343 | Iterator it = entrySet().iterator(); |
| 344 | while (it.hasNext()) { |
| 345 | Map.Entry e = (Map.Entry)it.next(); |
| 346 | String name = ((Name)e.getKey()).toString(); |
| 347 | if ((version != null) && ! (name.equalsIgnoreCase(vername))) { |
| 348 | |
| 349 | StringBuffer buffer = new StringBuffer(name); |
| 350 | buffer.append(": "); |
| 351 | |
| 352 | String value = (String)e.getValue(); |
| 353 | if (value != null) { |
| 354 | byte[] vb = value.getBytes("UTF8"); |
| 355 | value = new String(vb, 0, 0, vb.length); |
| 356 | } |
| 357 | buffer.append(value); |
| 358 | |
| 359 | buffer.append("\r\n"); |
| 360 | Manifest.make72Safe(buffer); |
| 361 | out.writeBytes(buffer.toString()); |
| 362 | } |
| 363 | } |
| 364 | out.writeBytes("\r\n"); |
| 365 | } |
| 366 | |
| 367 | /* |
| 368 | * Reads attributes from the specified input stream. |
| 369 | * XXX Need to handle UTF8 values. |
| 370 | */ |
| 371 | void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException { |
| 372 | String name = null, value = null; |
| 373 | byte[] lastline = null; |
| 374 | |
| 375 | int len; |
| 376 | while ((len = is.readLine(lbuf)) != -1) { |
| 377 | boolean lineContinued = false; |
| 378 | if (lbuf[--len] != '\n') { |
| 379 | throw new IOException("line too long"); |
| 380 | } |
| 381 | if (len > 0 && lbuf[len-1] == '\r') { |
| 382 | --len; |
| 383 | } |
| 384 | if (len == 0) { |
| 385 | break; |
| 386 | } |
| 387 | int i = 0; |
| 388 | if (lbuf[0] == ' ') { |
| 389 | // continuation of previous line |
| 390 | if (name == null) { |
| 391 | throw new IOException("misplaced continuation line"); |
| 392 | } |
| 393 | lineContinued = true; |
| 394 | byte[] buf = new byte[lastline.length + len - 1]; |
| 395 | System.arraycopy(lastline, 0, buf, 0, lastline.length); |
| 396 | System.arraycopy(lbuf, 1, buf, lastline.length, len - 1); |
| 397 | if (is.peek() == ' ') { |
| 398 | lastline = buf; |
| 399 | continue; |
| 400 | } |
| 401 | value = new String(buf, 0, buf.length, "UTF8"); |
| 402 | lastline = null; |
| 403 | } else { |
| 404 | while (lbuf[i++] != ':') { |
| 405 | if (i >= len) { |
| 406 | throw new IOException("invalid header field"); |
| 407 | } |
| 408 | } |
| 409 | if (lbuf[i++] != ' ') { |
| 410 | throw new IOException("invalid header field"); |
| 411 | } |
| 412 | name = new String(lbuf, 0, 0, i - 2); |
| 413 | if (is.peek() == ' ') { |
| 414 | lastline = new byte[len - i]; |
| 415 | System.arraycopy(lbuf, i, lastline, 0, len - i); |
| 416 | continue; |
| 417 | } |
| 418 | value = new String(lbuf, i, len - i, "UTF8"); |
| 419 | } |
| 420 | try { |
| 421 | if ((putValue(name, value) != null) && (!lineContinued)) { |
| 422 | Logger.getLogger("java.util.jar").warning( |
| 423 | "Duplicate name in Manifest: " + name |
| 424 | + ".\n" |
| 425 | + "Ensure that the manifest does not " |
| 426 | + "have duplicate entries, and\n" |
| 427 | + "that blank lines separate " |
| 428 | + "individual sections in both your\n" |
| 429 | + "manifest and in the META-INF/MANIFEST.MF " |
| 430 | + "entry in the jar file."); |
| 431 | } |
| 432 | } catch (IllegalArgumentException e) { |
| 433 | throw new IOException("invalid header field name: " + name); |
| 434 | } |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | /** |
| 439 | * The Attributes.Name class represents an attribute name stored in |
| 440 | * this Map. Valid attribute names are case-insensitive, are restricted |
| 441 | * to the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed |
| 442 | * 70 characters in length. Attribute values can contain any characters |
| 443 | * and will be UTF8-encoded when written to the output stream. See the |
| 444 | * <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a> |
| 445 | * for more information about valid attribute names and values. |
| 446 | */ |
| 447 | public static class Name { |
| 448 | private String name; |
| 449 | private int hashCode = -1; |
| 450 | |
| 451 | /** |
| 452 | * Constructs a new attribute name using the given string name. |
| 453 | * |
| 454 | * @param name the attribute string name |
| 455 | * @exception IllegalArgumentException if the attribute name was |
| 456 | * invalid |
| 457 | * @exception NullPointerException if the attribute name was null |
| 458 | */ |
| 459 | public Name(String name) { |
| 460 | if (name == null) { |
| 461 | throw new NullPointerException("name"); |
| 462 | } |
| 463 | if (!isValid(name)) { |
| 464 | throw new IllegalArgumentException(name); |
| 465 | } |
| 466 | this.name = name.intern(); |
| 467 | } |
| 468 | |
| 469 | private static boolean isValid(String name) { |
| 470 | int len = name.length(); |
| 471 | if (len > 70 || len == 0) { |
| 472 | return false; |
| 473 | } |
| 474 | for (int i = 0; i < len; i++) { |
| 475 | if (!isValid(name.charAt(i))) { |
| 476 | return false; |
| 477 | } |
| 478 | } |
| 479 | return true; |
| 480 | } |
| 481 | |
| 482 | private static boolean isValid(char c) { |
| 483 | return isAlpha(c) || isDigit(c) || c == '_' || c == '-'; |
| 484 | } |
| 485 | |
| 486 | private static boolean isAlpha(char c) { |
| 487 | return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); |
| 488 | } |
| 489 | |
| 490 | private static boolean isDigit(char c) { |
| 491 | return c >= '0' && c <= '9'; |
| 492 | } |
| 493 | |
| 494 | /** |
| 495 | * Compares this attribute name to another for equality. |
| 496 | * @param o the object to compare |
| 497 | * @return true if this attribute name is equal to the |
| 498 | * specified attribute object |
| 499 | */ |
| 500 | public boolean equals(Object o) { |
| 501 | if (o instanceof Name) { |
| 502 | Comparator c = ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER; |
| 503 | return c.compare(name, ((Name)o).name) == 0; |
| 504 | } else { |
| 505 | return false; |
| 506 | } |
| 507 | } |
| 508 | |
| 509 | /** |
| 510 | * Computes the hash value for this attribute name. |
| 511 | */ |
| 512 | public int hashCode() { |
| 513 | if (hashCode == -1) { |
| 514 | hashCode = ASCIICaseInsensitiveComparator.lowerCaseHashCode(name); |
| 515 | } |
| 516 | return hashCode; |
| 517 | } |
| 518 | |
| 519 | /** |
| 520 | * Returns the attribute name as a String. |
| 521 | */ |
| 522 | public String toString() { |
| 523 | return name; |
| 524 | } |
| 525 | |
| 526 | /** |
| 527 | * <code>Name</code> object for <code>Manifest-Version</code> |
| 528 | * manifest attribute. This attribute indicates the version number |
| 529 | * of the manifest standard to which a JAR file's manifest conforms. |
| 530 | * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest"> |
| 531 | * Manifest and Signature Specification</a> |
| 532 | */ |
| 533 | public static final Name MANIFEST_VERSION = new Name("Manifest-Version"); |
| 534 | |
| 535 | /** |
| 536 | * <code>Name</code> object for <code>Signature-Version</code> |
| 537 | * manifest attribute used when signing JAR files. |
| 538 | * @see <a href="../../../../technotes/guides/jar/jar.html#JAR Manifest"> |
| 539 | * Manifest and Signature Specification</a> |
| 540 | */ |
| 541 | public static final Name SIGNATURE_VERSION = new Name("Signature-Version"); |
| 542 | |
| 543 | /** |
| 544 | * <code>Name</code> object for <code>Content-Type</code> |
| 545 | * manifest attribute. |
| 546 | */ |
| 547 | public static final Name CONTENT_TYPE = new Name("Content-Type"); |
| 548 | |
| 549 | /** |
| 550 | * <code>Name</code> object for <code>Class-Path</code> |
| 551 | * manifest attribute. Bundled extensions can use this attribute |
| 552 | * to find other JAR files containing needed classes. |
| 553 | * @see <a href="../../../../technotes/guides/extensions/spec.html#bundled"> |
| 554 | * Extensions Specification</a> |
| 555 | */ |
| 556 | public static final Name CLASS_PATH = new Name("Class-Path"); |
| 557 | |
| 558 | /** |
| 559 | * <code>Name</code> object for <code>Main-Class</code> manifest |
| 560 | * attribute used for launching applications packaged in JAR files. |
| 561 | * The <code>Main-Class</code> attribute is used in conjunction |
| 562 | * with the <code>-jar</code> command-line option of the |
| 563 | * <tt>java</tt> application launcher. |
| 564 | */ |
| 565 | public static final Name MAIN_CLASS = new Name("Main-Class"); |
| 566 | |
| 567 | /** |
| 568 | * <code>Name</code> object for <code>Sealed</code> manifest attribute |
| 569 | * used for sealing. |
| 570 | * @see <a href="../../../../technotes/guides/extensions/spec.html#sealing"> |
| 571 | * Extension Sealing</a> |
| 572 | */ |
| 573 | public static final Name SEALED = new Name("Sealed"); |
| 574 | |
| 575 | /** |
| 576 | * <code>Name</code> object for <code>Extension-List</code> manifest attribute |
| 577 | * used for declaring dependencies on installed extensions. |
| 578 | * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> |
| 579 | * Installed extension dependency</a> |
| 580 | */ |
| 581 | public static final Name EXTENSION_LIST = new Name("Extension-List"); |
| 582 | |
| 583 | /** |
| 584 | * <code>Name</code> object for <code>Extension-Name</code> manifest attribute |
| 585 | * used for declaring dependencies on installed extensions. |
| 586 | * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> |
| 587 | * Installed extension dependency</a> |
| 588 | */ |
| 589 | public static final Name EXTENSION_NAME = new Name("Extension-Name"); |
| 590 | |
| 591 | /** |
| 592 | * <code>Name</code> object for <code>Extension-Name</code> manifest attribute |
| 593 | * used for declaring dependencies on installed extensions. |
| 594 | * @see <a href="../../../../technotes/guides/extensions/spec.html#dependency"> |
| 595 | * Installed extension dependency</a> |
| 596 | */ |
| 597 | public static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation"); |
| 598 | |
| 599 | /** |
| 600 | * <code>Name</code> object for <code>Implementation-Title</code> |
| 601 | * manifest attribute used for package versioning. |
| 602 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 603 | * Java Product Versioning Specification</a> |
| 604 | */ |
| 605 | public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title"); |
| 606 | |
| 607 | /** |
| 608 | * <code>Name</code> object for <code>Implementation-Version</code> |
| 609 | * manifest attribute used for package versioning. |
| 610 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 611 | * Java Product Versioning Specification</a> |
| 612 | */ |
| 613 | public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version"); |
| 614 | |
| 615 | /** |
| 616 | * <code>Name</code> object for <code>Implementation-Vendor</code> |
| 617 | * manifest attribute used for package versioning. |
| 618 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 619 | * Java Product Versioning Specification</a> |
| 620 | */ |
| 621 | public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor"); |
| 622 | |
| 623 | /** |
| 624 | * <code>Name</code> object for <code>Implementation-Vendor-Id</code> |
| 625 | * manifest attribute used for package versioning. |
| 626 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 627 | * Java Product Versioning Specification</a> |
| 628 | */ |
| 629 | public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id"); |
| 630 | |
| 631 | /** |
| 632 | * <code>Name</code> object for <code>Implementation-Vendor-URL</code> |
| 633 | * manifest attribute used for package versioning. |
| 634 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 635 | * Java Product Versioning Specification</a> |
| 636 | */ |
| 637 | public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL"); |
| 638 | |
| 639 | /** |
| 640 | * <code>Name</code> object for <code>Specification-Title</code> |
| 641 | * manifest attribute used for package versioning. |
| 642 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 643 | * Java Product Versioning Specification</a> |
| 644 | */ |
| 645 | public static final Name SPECIFICATION_TITLE = new Name("Specification-Title"); |
| 646 | |
| 647 | /** |
| 648 | * <code>Name</code> object for <code>Specification-Version</code> |
| 649 | * manifest attribute used for package versioning. |
| 650 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 651 | * Java Product Versioning Specification</a> |
| 652 | */ |
| 653 | public static final Name SPECIFICATION_VERSION = new Name("Specification-Version"); |
| 654 | |
| 655 | /** |
| 656 | * <code>Name</code> object for <code>Specification-Vendor</code> |
| 657 | * manifest attribute used for package versioning. |
| 658 | * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> |
| 659 | * Java Product Versioning Specification</a> |
| 660 | */ |
| 661 | public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); |
| 662 | } |
| 663 | } |