diff options
author | Raif S. Naffah <raif@swiftdsl.com.au> | 2006-03-07 18:37:00 +0000 |
---|---|---|
committer | Raif S. Naffah <raif@swiftdsl.com.au> | 2006-03-07 18:37:00 +0000 |
commit | 170b6ab41aea7f1ea2391ddf3e63e74093b5d3c6 (patch) | |
tree | b59655f42b4adc5d5be3756426912a1ae790f1ba /java/util | |
parent | d0ef654db55b0d4065cdf1c52d48e57f0c9de61a (diff) | |
download | classpath-170b6ab41aea7f1ea2391ddf3e63e74093b5d3c6.tar.gz |
2006-03-08 Raif S. Naffah <raif@swiftdsl.com.au>
* java/util/jar/Manifest.java: Removed unused imports.
(CRLF): New constant.
(read): Added method documentation.
Use UTF-8 encoding instead of 8859_1.
(write): Added method documentation.
Use BufferedOutputStream (w/ 4K buffer) instead of PrintWriter.
(write_main_section): Replace PrintWriter arg with OutputStream.
Replace JarException with IOException.
(write_version_info): Likewise.
(write_main_attributes): Likewise.
(write_attribute_entry): Likewise.
(write_individual_sections): Likewise.
(write_entry_attributes): Likewise.
(write_header): Replace PrintWriter arg with OutputStream.
Re-implemented.
Diffstat (limited to 'java/util')
-rw-r--r-- | java/util/jar/Manifest.java | 164 |
1 files changed, 104 insertions, 60 deletions
diff --git a/java/util/jar/Manifest.java b/java/util/jar/Manifest.java index ff82aa2db..64876f9da 100644 --- a/java/util/jar/Manifest.java +++ b/java/util/jar/Manifest.java @@ -37,14 +37,12 @@ exception statement from your version. */ package java.util.jar; +import java.io.BufferedOutputStream; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; @@ -60,6 +58,9 @@ public class Manifest implements Cloneable { // Fields + /** Platform-independent line-ending. */ + private static final byte[] CRLF = new byte[] { 0x0D, 0x0A }; + /** The main attributes of the manifest (jar file). */ private final Attributes mainAttr; @@ -156,12 +157,14 @@ public class Manifest implements Cloneable } /** - * XXX + * Read and merge a <code>Mainfest</code> from the designated input stream. + * + * @param in the input stream to read from. + * @throws IOException if an I/O related exception occurs during the process. */ public void read(InputStream in) throws IOException { - BufferedReader br = - new BufferedReader(new InputStreamReader(in, "8859_1")); + BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); read_main_section(getMainAttributes(), br); read_individual_sections(getEntries(), br); } @@ -310,32 +313,35 @@ public class Manifest implements Cloneable } /** - * XXX + * Writes the contents of this <code>Manifest</code> to the designated + * output stream. Line-endings are platform-independent and consist of the + * 2-codepoint sequence <code>0x0D</code> and <code>0x0A</code>. + * + * @param out the output stream to write this <code>Manifest</code> to. + * @throws IOException if an I/O related exception occurs during the process. */ public void write(OutputStream out) throws IOException { - PrintWriter pw = - new PrintWriter(new - BufferedWriter(new OutputStreamWriter(out, "8859_1"))); - write_main_section(getMainAttributes(), pw); - pw.println(); - write_individual_sections(getEntries(), pw); - if (pw.checkError()) - { - throw new JarException("Error while writing manifest"); - } + BufferedOutputStream bos = out instanceof BufferedOutputStream + ? (BufferedOutputStream) out + : new BufferedOutputStream(out, 4096); + write_main_section(getMainAttributes(), bos); + bos.write(CRLF); + write_individual_sections(getEntries(), bos); + bos.flush(); } // Private Static functions for writing the Manifest file to a PrintWriter - private static void write_main_section(Attributes attr, - PrintWriter pw) throws JarException + private static void write_main_section(Attributes attr, OutputStream out) + throws IOException { - write_version_info(attr, pw); - write_main_attributes(attr, pw); + write_version_info(attr, out); + write_main_attributes(attr, out); } - private static void write_version_info(Attributes attr, PrintWriter pw) + private static void write_version_info(Attributes attr, OutputStream out) + throws IOException { // First check if there is already a version attribute set String version = attr.getValue(Attributes.Name.MANIFEST_VERSION); @@ -343,40 +349,80 @@ public class Manifest implements Cloneable { version = "1.0"; } - write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw); + write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, out); } - private static void write_header(String name, String value, PrintWriter pw) + /** + * The basic method for writing <code>Mainfest</code> attributes. This + * implementation respects the rule stated in the Jar Specification concerning + * the maximum allowed line length; i.e. + * + * <pre> + * No line may be longer than 72 bytes (not characters), in its UTF8-encoded + * form. If a value would make the initial line longer than this, it should + * be continued on extra lines (each starting with a single SPACE). + * </pre> + * and + * <pre> + * Because header names cannot be continued, the maximum length of a header + * name is 70 bytes (there must be a colon and a SPACE after the name). + * </pre> + * + * @param name the name of the attribute. + * @param value the value of the attribute. + * @param out the output stream to write the attribute's name/value pair to. + * @throws IOException if an I/O related exception occurs during the process. + */ + private static void write_header(String name, String value, OutputStream out) + throws IOException { - pw.print(name + ": "); + String target = name + ": "; + byte[] b = target.getBytes("UTF-8"); + if (b.length > 72) + throw new IOException("Attribute's name already longer than 70 bytes"); - int last = 68 - name.length(); - if (last > value.length()) + if (b.length == 72) { - pw.println(value); + out.write(b); + out.write(CRLF); + target = " " + value; } else + target = target + value; + + int n; + while (true) { - pw.println(value.substring(0, last)); - } - while (last < value.length()) - { - pw.print(" "); - int end = (last + 69); - if (end > value.length()) - { - pw.println(value.substring(last)); - } - else - { - pw.println(value.substring(last, end)); - } - last = end; + b = target.getBytes("UTF-8"); + if (b.length < 73) + { + out.write(b); + break; + } + + // find an appropriate character position to break on + n = 72; + while (true) + { + b = target.substring(0, n).getBytes("UTF-8"); + if (b.length < 73) + break; + + n--; + if (n < 1) + throw new IOException("Header is unbreakable and longer than 72 bytes"); + } + + out.write(b); + out.write(CRLF); + target = " " + target.substring(n); } + + out.write(CRLF); } - private static void write_main_attributes(Attributes attr, PrintWriter pw) - throws JarException + private static void write_main_attributes(Attributes attr, OutputStream out) + throws IOException { Iterator it = attr.entrySet().iterator(); while (it.hasNext()) @@ -384,14 +430,12 @@ public class Manifest implements Cloneable Map.Entry entry = (Map.Entry) it.next(); // Don't print the manifest version again if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey())) - { - write_attribute_entry(entry, pw); - } + write_attribute_entry(entry, out); } } - private static void write_attribute_entry(Map.Entry entry, PrintWriter pw) - throws JarException + private static void write_attribute_entry(Map.Entry entry, OutputStream out) + throws IOException { String name = entry.getKey().toString(); String value = entry.getValue().toString(); @@ -406,31 +450,31 @@ public class Manifest implements Cloneable JarException("Header cannot start with the four letters 'From'" + name); } - write_header(name, value, pw); + write_header(name, value, out); } - private static void write_individual_sections(Map entries, PrintWriter pw) - throws JarException + private static void write_individual_sections(Map entries, OutputStream out) + throws IOException { Iterator it = entries.entrySet().iterator(); while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - write_header("Name", entry.getKey().toString(), pw); - write_entry_attributes((Attributes) entry.getValue(), pw); - pw.println(); + Map.Entry entry = (Map.Entry) it.next(); + write_header("Name", entry.getKey().toString(), out); + write_entry_attributes((Attributes) entry.getValue(), out); + out.write(CRLF); } } - private static void write_entry_attributes(Attributes attr, PrintWriter pw) - throws JarException + private static void write_entry_attributes(Attributes attr, OutputStream out) + throws IOException { Iterator it = attr.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); - write_attribute_entry(entry, pw); + write_attribute_entry(entry, out); } } |