Index: /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 17570)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 17571)
@@ -185,5 +185,5 @@
         public String getText() {
             StringBuilder b = new StringBuilder();
-            for (Entry<String, String> e : info.attr.entrySet()) {
+            for (Entry<Object, Object> e : info.attr.entrySet()) {
                 b.append(e.getKey());
                 b.append(": ");
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 17570)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 17571)
@@ -19,5 +19,4 @@
 import java.util.Map;
 import java.util.Optional;
-import java.util.TreeMap;
 import java.util.jar.Attributes;
 import java.util.jar.JarInputStream;
@@ -94,5 +93,5 @@
     public List<URL> libraries = new LinkedList<>();
     /** All manifest attributes. */
-    public final Map<String, String> attr = new TreeMap<>();
+    public Attributes attr;
     /** Invalid manifest entries */
     final List<String> invalidManifestEntries = new ArrayList<>();
@@ -134,5 +133,5 @@
             if (manifest == null)
                 throw new PluginException(tr("The plugin file ''{0}'' does not include a Manifest.", file.toString()));
-            scanManifest(manifest, false);
+            scanManifest(manifest.getMainAttributes(), false);
             libraries.add(0, Utils.fileToURL(file));
         } catch (IOException | InvalidPathException e) {
@@ -151,5 +150,4 @@
      */
     public PluginInformation(InputStream manifestStream, String name, String url) throws PluginException {
-        this.name = name;
         try {
             Manifest manifest = new Manifest();
@@ -158,8 +156,25 @@
                 downloadlink = url;
             }
-            scanManifest(manifest, url != null);
+            scanManifest(manifest.getMainAttributes(), url != null);
         } catch (IOException e) {
             throw new PluginException(name, e);
         }
+    }
+
+    /**
+     * Creates a plugin information object by reading plugin information in Manifest format
+     * from the input stream {@code manifestStream}.
+     *
+     * @param attr the manifest attributes
+     * @param name the plugin name
+     * @param url the download URL for the plugin
+     * @throws PluginException if the plugin information can't be read from the input stream
+     */
+    public PluginInformation(Attributes attr, String name, String url) throws PluginException {
+        this.name = name;
+        if (url != null) {
+            downloadlink = url;
+        }
+        scanManifest(attr, url != null);
     }
 
@@ -189,6 +204,5 @@
         this.canloadatruntime = other.canloadatruntime;
         this.libraries = other.libraries;
-        this.attr.clear();
-        this.attr.putAll(other.attr);
+        this.attr = new Attributes(other.attr);
         this.invalidManifestEntries.clear();
         this.invalidManifestEntries.addAll(other.invalidManifestEntries);
@@ -215,7 +229,6 @@
     }
 
-    private void scanManifest(Manifest manifest, boolean oldcheck) {
+    private void scanManifest(Attributes attr, boolean oldcheck) {
         String lang = LanguageInfo.getLanguageCodeManifest();
-        Attributes attr = manifest.getMainAttributes();
         className = attr.getValue("Plugin-Class");
         String s = Optional.ofNullable(attr.getValue(lang+"Plugin-Link")).orElseGet(() -> attr.getValue("Plugin-Link"));
@@ -318,7 +331,5 @@
             }
         }
-        for (Object o : attr.keySet()) {
-            this.attr.put(o.toString(), attr.getValue(o.toString()));
-        }
+        this.attr = attr;
     }
 
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginListParser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginListParser.java	(revision 17570)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginListParser.java	(revision 17571)
@@ -5,5 +5,4 @@
 
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -12,4 +11,5 @@
 import java.util.LinkedList;
 import java.util.List;
+import java.util.jar.Attributes;
 
 import org.openstreetmap.josm.tools.Logging;
@@ -30,12 +30,12 @@
      * @param name the plugin name
      * @param url the plugin download url
-     * @param manifest the plugin manifest
+     * @param manifest the plugin manifest attributes
      * @return a plugin information object
      * @throws PluginListParseException if plugin manifest cannot be parsed
      */
-    public static PluginInformation createInfo(String name, String url, String manifest) throws PluginListParseException {
+    public static PluginInformation createInfo(String name, String url, Attributes manifest) throws PluginListParseException {
         try {
             return new PluginInformation(
-                    new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8)),
+                    manifest,
                     name.substring(0, name.length() - 4),
                     url
@@ -62,19 +62,12 @@
             String name = null;
             String url = null;
-            StringBuilder manifest = new StringBuilder();
+            Attributes manifest = new Attributes();
             for (String line = r.readLine(); line != null; line = r.readLine()) {
                 if (line.startsWith("\t")) {
-                    line = line.substring(1);
-                    /* NOTE: Although manifest specification says line should not be longer than 72 bytes it
-                       supports more than 500 bytes and thus even the longest possible 72 character UTF-8, so
-                       this code correctly splits the text at 70 characters, not bytes. */
-                    while (line.length() > 70) {
-                        manifest.append(line.substring(0, 70)).append('\n');
-                        line = ' ' + line.substring(70);
-                    }
-                    manifest.append(line).append('\n');
+                    final String[] keyValue = line.split("\\s*:\\s*", 2);
+                    manifest.put(new Attributes.Name(keyValue[0].substring(1)), keyValue[1]);
                     continue;
                 }
-                addPluginInformation(ret, name, url, manifest.toString());
+                addPluginInformation(ret, name, url, manifest);
                 String[] x = line.split(";", -1);
                 if (x.length != 2)
@@ -82,7 +75,7 @@
                 name = x[0];
                 url = x[1];
-                manifest = new StringBuilder();
+                manifest = new Attributes();
             }
-            addPluginInformation(ret, name, url, manifest.toString());
+            addPluginInformation(ret, name, url, manifest);
             return ret;
         } catch (IOException e) {
@@ -91,5 +84,5 @@
     }
 
-    private static void addPluginInformation(List<PluginInformation> ret, String name, String url, String manifest) {
+    private static void addPluginInformation(List<PluginInformation> ret, String name, String url, Attributes manifest) {
         try {
             if (name != null) {
Index: /trunk/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java	(revision 17570)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java	(revision 17571)
@@ -22,4 +22,5 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.jar.Attributes;
 
 import javax.swing.JComponent;
@@ -205,5 +206,5 @@
     private static PluginInformation newPluginInformation(String plugin) throws PluginListParseException {
         return PluginListParser.createInfo(plugin+".jar", "https://josm.openstreetmap.de/osmsvn/applications/editors/josm/dist/"+plugin+".jar",
-                "");
+                new Attributes());
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java	(revision 17570)
+++ /trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java	(revision 17571)
@@ -154,16 +154,16 @@
     void testPluginInformationAction() throws PluginException {
         TestUtils.assumeWorkingJMockit();
-        final String expectedText = "Ant-Version: Apache Ant 1.9.6\n" +
-            "Author: Don-vip\n" +
-            "Created-By: 1.7.0_91-b02 (Oracle Corporation)\n" +
-            "Manifest-Version: 1.0\n" +
-            "Plugin-Canloadatruntime: true\n" +
-            "Plugin-Class: org.openstreetmap.josm.plugins.fr.epci.EpciPlugin\n" +
-            "Plugin-Date: 2015-11-19T08:21:07.645033Z\n" +
-            "Plugin-Description: Handling of French EPCIs (boundary=local_authority)\n" +
-            "Plugin-Early: true\n" +
-            "Plugin-Link: http://wiki.openstreetmap.org/wiki/FR:JOSM/Fr:Plugin/EPCI-fr\n" +
-            "Plugin-Mainversion: 7001\n" +
-            "Plugin-Version: 31772\n";
+        final String expectedText = "Manifest-Version: 1.0\n" +
+                "Ant-Version: Apache Ant 1.9.6\n" +
+                "Created-By: 1.7.0_91-b02 (Oracle Corporation)\n" +
+                "Plugin-Mainversion: 7001\n" +
+                "Plugin-Version: 31772\n" +
+                "Plugin-Class: org.openstreetmap.josm.plugins.fr.epci.EpciPlugin\n" +
+                "Plugin-Description: Handling of French EPCIs (boundary=local_authority)\n" +
+                "Plugin-Date: 2015-11-19T08:21:07.645033Z\n" +
+                "Author: Don-vip\n" +
+                "Plugin-Link: http://wiki.openstreetmap.org/wiki/FR:JOSM/Fr:Plugin/EPCI-fr\n" +
+                "Plugin-Early: true\n" +
+                "Plugin-Canloadatruntime: true\n";
         final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker() {
             @Override
