summaryrefslogtreecommitdiff
path: root/java/util
diff options
context:
space:
mode:
authorRaif S. Naffah <raif@swiftdsl.com.au>2006-03-07 18:37:00 +0000
committerRaif S. Naffah <raif@swiftdsl.com.au>2006-03-07 18:37:00 +0000
commit170b6ab41aea7f1ea2391ddf3e63e74093b5d3c6 (patch)
treeb59655f42b4adc5d5be3756426912a1ae790f1ba /java/util
parentd0ef654db55b0d4065cdf1c52d48e57f0c9de61a (diff)
downloadclasspath-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.java164
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);
}
}