diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java')
-rw-r--r-- | bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java | 94 |
1 files changed, 58 insertions, 36 deletions
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java index 1ef321071..10616c3a9 100644 --- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java +++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/ManifestElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2013 IBM Corporation and others. + * Copyright (c) 2003, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -376,7 +376,7 @@ public class ManifestElement { } else directive = true; } - if (c == ';' || c == ',' || c == '\0') /* more */{ + if (c == ';' || c == ',' || c == '\0') /* more */ { headerValues.add(next); headerValue.append(";").append(next); //$NON-NLS-1$ if (SupplementDebug.STATIC_DEBUG_MANIFEST) @@ -425,7 +425,7 @@ public class ManifestElement { throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR, e); } c = tokenizer.getChar(); - if (c == ';') /* more */{ + if (c == ';') /* more */ { next = tokenizer.getToken("=:"); //$NON-NLS-1$ if (next == null) throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR); @@ -501,19 +501,13 @@ public class ManifestElement { public static Map<String, String> parseBundleManifest(InputStream manifest, Map<String, String> headers) throws IOException, BundleException { if (headers == null) headers = new HashMap<String, String>(); - BufferedReader br; - try { - br = new BufferedReader(new InputStreamReader(manifest, "UTF8")); //$NON-NLS-1$ - } catch (UnsupportedEncodingException e) { - br = new BufferedReader(new InputStreamReader(manifest)); - } + + manifest = new BufferedInputStream(manifest); try { - String header = null; - StringBuffer value = new StringBuffer(256); - boolean firstLine = true; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(256); while (true) { - String line = br.readLine(); + String line = readLine(manifest, buffer); /* The java.util.jar classes in JDK 1.3 use the value of the last * encountered manifest header. So we do the same to emulate * this behavior. We no longer throw a BundleException @@ -522,40 +516,21 @@ public class ManifestElement { if ((line == null) || (line.length() == 0)) /* EOF or empty line */ { - if (!firstLine) /* flush last line */ - { - headers.put(header, value.toString().trim()); - } break; /* done processing main attributes */ } - if (line.charAt(0) == ' ') /* continuation */ - { - if (firstLine) /* if no previous line */ - { - throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_SPACE, line), BundleException.MANIFEST_ERROR); - } - value.append(line.substring(1)); - continue; - } - - if (!firstLine) { - headers.put(header, value.toString().trim()); - value.setLength(0); /* clear StringBuffer */ - } - int colon = line.indexOf(':'); if (colon == -1) /* no colon */ { throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_LINE_NOCOLON, line), BundleException.MANIFEST_ERROR); } - header = line.substring(0, colon).trim(); - value.append(line.substring(colon + 1)); - firstLine = false; + String header = line.substring(0, colon).trim(); + String value = line.substring(colon + 1).trim(); + headers.put(header, value); } } finally { try { - br.close(); + manifest.close(); } catch (IOException ee) { // do nothing } @@ -563,6 +538,53 @@ public class ManifestElement { return headers; } + private static String readLine(InputStream input, ByteArrayOutputStream buffer) throws IOException { + // Read a header 'line' + // A header line may span multiple lines with line continuations using a beginning space. + // This method reads all the line continuations into a single string. + // Care must be taken for cases where double byte UTF characters are split + // across line continuations. + // This is why BufferedReader.readLine is not used here. We must process the + // CR LF chars ourselves + lineLoop: while (true) { + int c = input.read(); + if (c == '\n') { // LF + // next char is either a continuation (space) char or the first char of the next header + input.mark(1); + c = input.read(); + if (c != ' ') { + // This first char of the next header, reset so we don't loose the char + input.reset(); + break lineLoop; + } + // This is a continuation, skip the space and read the next char + c = input.read(); + } else if (c == '\r') { // CR + // next char is either a continuation (space) char, LF or the first char of the next header + input.mark(1); + c = input.read(); + if (c == '\n') { // LF + // next char is either a continuation (space) char or the first char of the next header + input.mark(1); + c = input.read(); + } + if (c != ' ') { + // This first char of the next header, reset so we don't loose the char + input.reset(); + break lineLoop; + } + c = input.read(); + } + if (c == -1) { + break lineLoop; + } + buffer.write(c); + } + String result = buffer.toString("UTF8"); //$NON-NLS-1$ + buffer.reset(); + return result; + } + public String toString() { Enumeration<String> attrKeys = getKeys(); Enumeration<String> directiveKeys = getDirectiveKeys(); |