< prev index next >

src/java.base/share/classes/java/util/jar/Attributes.java

Print this page
rev 53080 : 8066619: Fix deprecation warnings in java.util.jar
Reviewed-by: rriggs, lancea
Contributed-by: philipp.kunz@paratix.ch


  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.jar;
  27 
  28 import java.io.DataOutputStream;
  29 import java.io.IOException;
  30 import java.util.Collection;
  31 import java.util.HashMap;
  32 import java.util.LinkedHashMap;
  33 import java.util.Map;
  34 import java.util.Objects;
  35 import java.util.Set;
  36 
  37 import sun.util.logging.PlatformLogger;
  38 


  39 /**
  40  * The Attributes class maps Manifest attribute names to associated string
  41  * values. Valid attribute names are case-insensitive, are restricted to
  42  * the ASCII characters in the set [0-9a-zA-Z_-], and cannot exceed 70
  43  * characters in length. There must be a colon and a SPACE after the name;
  44  * the combined length will not exceed 72 characters.
  45  * Attribute values can contain any characters and
  46  * will be UTF8-encoded when written to the output stream.  See the
  47  * <a href="{@docRoot}/../specs/jar/jar.html">JAR File Specification</a>
  48  * for more information about valid attribute names and values.
  49  *
  50  * <p>This map and its views have a predictable iteration order, namely the
  51  * order that keys were inserted into the map, as with {@link LinkedHashMap}.
  52  *
  53  * @author  David Connelly
  54  * @see     Manifest
  55  * @since   1.2
  56  */
  57 public class Attributes implements Map<Object,Object>, Cloneable {
  58     /**


 281         return map.hashCode();
 282     }
 283 
 284     /**
 285      * Returns a copy of the Attributes, implemented as follows:
 286      * <pre>
 287      *     public Object clone() { return new Attributes(this); }
 288      * </pre>
 289      * Since the attribute names and values are themselves immutable,
 290      * the Attributes returned can be safely modified without affecting
 291      * the original.
 292      */
 293     public Object clone() {
 294         return new Attributes(this);
 295     }
 296 
 297     /*
 298      * Writes the current attributes to the specified data output stream.
 299      * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
 300      */
 301      @SuppressWarnings("deprecation")
 302      void write(DataOutputStream os) throws IOException {
 303          for (Entry<Object, Object> e : entrySet()) {
 304              StringBuffer buffer = new StringBuffer(
 305                                          ((Name) e.getKey()).toString());
 306              buffer.append(": ");
 307 
 308              String value = (String) e.getValue();
 309              if (value != null) {
 310                  byte[] vb = value.getBytes("UTF8");
 311                  value = new String(vb, 0, 0, vb.length);
 312              }
 313              buffer.append(value);
 314 
 315              Manifest.make72Safe(buffer);
 316              buffer.append("\r\n");
 317              os.writeBytes(buffer.toString());
 318          }
 319         os.writeBytes("\r\n");
 320     }
 321 
 322     /*
 323      * Writes the current attributes to the specified data output stream,
 324      * make sure to write out the MANIFEST_VERSION or SIGNATURE_VERSION
 325      * attributes first.
 326      *
 327      * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
 328      */
 329     @SuppressWarnings("deprecation")
 330     void writeMain(DataOutputStream out) throws IOException
 331     {
 332         // write out the *-Version header first, if it exists
 333         String vername = Name.MANIFEST_VERSION.toString();
 334         String version = getValue(vername);
 335         if (version == null) {
 336             vername = Name.SIGNATURE_VERSION.toString();
 337             version = getValue(vername);
 338         }
 339 
 340         if (version != null) {
 341             out.writeBytes(vername+": "+version+"\r\n");




 342         }
 343 
 344         // write out all attributes except for the version
 345         // we wrote out earlier
 346         for (Entry<Object, Object> e : entrySet()) {
 347             String name = ((Name) e.getKey()).toString();
 348             if ((version != null) && !(name.equalsIgnoreCase(vername))) {
 349 
 350                 StringBuffer buffer = new StringBuffer(name);
 351                 buffer.append(": ");
 352 
 353                 String value = (String) e.getValue();
 354                 if (value != null) {
 355                     byte[] vb = value.getBytes("UTF8");
 356                     value = new String(vb, 0, 0, vb.length);
 357                 }
 358                 buffer.append(value);
 359 
 360                 Manifest.make72Safe(buffer);
 361                 buffer.append("\r\n");
 362                 out.writeBytes(buffer.toString());
 363             }
 364         }
 365         out.writeBytes("\r\n");

 366     }
 367 
 368     /*
 369      * Reads attributes from the specified input stream.
 370      * XXX Need to handle UTF8 values.
 371      */
 372     void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException {
 373         read(is, lbuf, null, 0);
 374     }
 375 
 376     @SuppressWarnings("deprecation")
 377     int read(Manifest.FastInputStream is, byte[] lbuf, String filename, int lineNumber) throws IOException {
 378         String name = null, value;
 379         byte[] lastline = null;
 380 
 381         int len;
 382         while ((len = is.readLine(lbuf)) != -1) {
 383             boolean lineContinued = false;
 384             byte c = lbuf[--len];
 385             lineNumber++;
 386 
 387             if (c != '\n' && c != '\r') {
 388                 throw new IOException("line too long ("
 389                             + Manifest.getErrorPosition(filename, lineNumber) + ")");
 390             }
 391             if (len > 0 && lbuf[len-1] == '\r') {
 392                 --len;
 393             }
 394             if (len == 0) {
 395                 break;
 396             }
 397             int i = 0;
 398             if (lbuf[0] == ' ') {
 399                 // continuation of previous line
 400                 if (name == null) {
 401                     throw new IOException("misplaced continuation line ("
 402                                 + Manifest.getErrorPosition(filename, lineNumber) + ")");
 403                 }
 404                 lineContinued = true;
 405                 byte[] buf = new byte[lastline.length + len - 1];
 406                 System.arraycopy(lastline, 0, buf, 0, lastline.length);
 407                 System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
 408                 if (is.peek() == ' ') {
 409                     lastline = buf;
 410                     continue;
 411                 }
 412                 value = new String(buf, 0, buf.length, "UTF8");
 413                 lastline = null;
 414             } else {
 415                 while (lbuf[i++] != ':') {
 416                     if (i >= len) {
 417                         throw new IOException("invalid header field ("
 418                                     + Manifest.getErrorPosition(filename, lineNumber) + ")");
 419                     }
 420                 }
 421                 if (lbuf[i++] != ' ') {
 422                     throw new IOException("invalid header field ("
 423                                 + Manifest.getErrorPosition(filename, lineNumber) + ")");
 424                 }
 425                 name = new String(lbuf, 0, 0, i - 2);
 426                 if (is.peek() == ' ') {
 427                     lastline = new byte[len - i];
 428                     System.arraycopy(lbuf, i, lastline, 0, len - i);
 429                     continue;
 430                 }
 431                 value = new String(lbuf, i, len - i, "UTF8");
 432             }
 433             try {
 434                 if ((putValue(name, value) != null) && (!lineContinued)) {
 435                     PlatformLogger.getLogger("java.util.jar").warning(
 436                                      "Duplicate name in Manifest: " + name
 437                                      + ".\n"
 438                                      + "Ensure that the manifest does not "
 439                                      + "have duplicate entries, and\n"
 440                                      + "that blank lines separate "
 441                                      + "individual sections in both your\n"
 442                                      + "manifest and in the META-INF/MANIFEST.MF "
 443                                      + "entry in the jar file.");
 444                 }
 445             } catch (IllegalArgumentException e) {
 446                 throw new IOException("invalid header field name: " + name
 447                             + " (" + Manifest.getErrorPosition(filename, lineNumber) + ")");
 448             }
 449         }
 450         return lineNumber;
 451     }




  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.jar;
  27 
  28 import java.io.DataOutputStream;
  29 import java.io.IOException;
  30 import java.util.Collection;
  31 import java.util.HashMap;
  32 import java.util.LinkedHashMap;
  33 import java.util.Map;
  34 import java.util.Objects;
  35 import java.util.Set;
  36 
  37 import sun.util.logging.PlatformLogger;
  38 
  39 import static java.nio.charset.StandardCharsets.UTF_8;
  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. There must be a colon and a SPACE after the name;
  46  * the combined length will not exceed 72 characters.
  47  * Attribute values can contain any characters and
  48  * will be UTF8-encoded when written to the output stream.  See the
  49  * <a href="{@docRoot}/../specs/jar/jar.html">JAR File Specification</a>
  50  * for more information about valid attribute names and values.
  51  *
  52  * <p>This map and its views have a predictable iteration order, namely the
  53  * order that keys were inserted into the map, as with {@link LinkedHashMap}.
  54  *
  55  * @author  David Connelly
  56  * @see     Manifest
  57  * @since   1.2
  58  */
  59 public class Attributes implements Map<Object,Object>, Cloneable {
  60     /**


 283         return map.hashCode();
 284     }
 285 
 286     /**
 287      * Returns a copy of the Attributes, implemented as follows:
 288      * <pre>
 289      *     public Object clone() { return new Attributes(this); }
 290      * </pre>
 291      * Since the attribute names and values are themselves immutable,
 292      * the Attributes returned can be safely modified without affecting
 293      * the original.
 294      */
 295     public Object clone() {
 296         return new Attributes(this);
 297     }
 298 
 299     /*
 300      * Writes the current attributes to the specified data output stream.
 301      * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
 302      */
 303     void write(DataOutputStream out) throws IOException {
 304         StringBuilder buffer = new StringBuilder(72);
 305         for (Entry<Object, Object> e : entrySet()) {
 306             buffer.setLength(0);
 307             buffer.append(e.getKey().toString());
 308             buffer.append(": ");
 309             buffer.append(e.getValue());
 310             Manifest.println72(out, buffer.toString());









 311         }
 312         Manifest.println(out); // empty line after individual section
 313     }
 314 
 315     /*
 316      * Writes the current attributes to the specified data output stream,
 317      * make sure to write out the MANIFEST_VERSION or SIGNATURE_VERSION
 318      * attributes first.
 319      *
 320      * XXX Need to handle UTF8 values and break up lines longer than 72 bytes
 321      */
 322     void writeMain(DataOutputStream out) throws IOException {
 323         StringBuilder buffer = new StringBuilder(72);
 324 
 325         // write out the *-Version header first, if it exists
 326         String vername = Name.MANIFEST_VERSION.toString();
 327         String version = getValue(vername);
 328         if (version == null) {
 329             vername = Name.SIGNATURE_VERSION.toString();
 330             version = getValue(vername);
 331         }
 332 
 333         if (version != null) {
 334             buffer.append(vername);
 335             buffer.append(": ");
 336             buffer.append(version);
 337             out.write(buffer.toString().getBytes(UTF_8));
 338             Manifest.println(out);
 339         }
 340 
 341         // write out all attributes except for the version
 342         // we wrote out earlier
 343         for (Entry<Object, Object> e : entrySet()) {
 344             String name = ((Name) e.getKey()).toString();
 345             if ((version != null) && !(name.equalsIgnoreCase(vername))) {
 346                 buffer.setLength(0);
 347                 buffer.append(name);
 348                 buffer.append(": ");
 349                 buffer.append(e.getValue());
 350                 Manifest.println72(out, buffer.toString());









 351             }
 352         }
 353 
 354         Manifest.println(out); // empty line after main attributes section
 355     }
 356 
 357     /*
 358      * Reads attributes from the specified input stream.

 359      */
 360     void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException {
 361         read(is, lbuf, null, 0);
 362     }
 363 

 364     int read(Manifest.FastInputStream is, byte[] lbuf, String filename, int lineNumber) throws IOException {
 365         String name = null, value;
 366         byte[] lastline = null;
 367 
 368         int len;
 369         while ((len = is.readLine(lbuf)) != -1) {
 370             boolean lineContinued = false;
 371             byte c = lbuf[--len];
 372             lineNumber++;
 373 
 374             if (c != '\n' && c != '\r') {
 375                 throw new IOException("line too long ("
 376                             + Manifest.getErrorPosition(filename, lineNumber) + ")");
 377             }
 378             if (len > 0 && lbuf[len-1] == '\r') {
 379                 --len;
 380             }
 381             if (len == 0) {
 382                 break;
 383             }
 384             int i = 0;
 385             if (lbuf[0] == ' ') {
 386                 // continuation of previous line
 387                 if (name == null) {
 388                     throw new IOException("misplaced continuation line ("
 389                                 + Manifest.getErrorPosition(filename, lineNumber) + ")");
 390                 }
 391                 lineContinued = true;
 392                 byte[] buf = new byte[lastline.length + len - 1];
 393                 System.arraycopy(lastline, 0, buf, 0, lastline.length);
 394                 System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
 395                 if (is.peek() == ' ') {
 396                     lastline = buf;
 397                     continue;
 398                 }
 399                 value = new String(buf, 0, buf.length, UTF_8);
 400                 lastline = null;
 401             } else {
 402                 while (lbuf[i++] != ':') {
 403                     if (i >= len) {
 404                         throw new IOException("invalid header field ("
 405                                     + Manifest.getErrorPosition(filename, lineNumber) + ")");
 406                     }
 407                 }
 408                 if (lbuf[i++] != ' ') {
 409                     throw new IOException("invalid header field ("
 410                                 + Manifest.getErrorPosition(filename, lineNumber) + ")");
 411                 }
 412                 name = new String(lbuf, 0, i - 2, UTF_8);
 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, UTF_8);
 419             }
 420             try {
 421                 if ((putValue(name, value) != null) && (!lineContinued)) {
 422                     PlatformLogger.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                             + " (" + Manifest.getErrorPosition(filename, lineNumber) + ")");
 435             }
 436         }
 437         return lineNumber;
 438     }


< prev index next >