diff --git a/src/org/openstreetmap/josm/plugins/PluginInformation.java b/src/org/openstreetmap/josm/plugins/PluginInformation.java
index b510cbd3b..dfae76790 100644
--- a/src/org/openstreetmap/josm/plugins/PluginInformation.java
+++ b/src/org/openstreetmap/josm/plugins/PluginInformation.java
@@ -18,7 +18,6 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
-import java.util.TreeMap;
 import java.util.jar.Attributes;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -93,7 +92,7 @@ public class PluginInformation {
     /** The libraries referenced in Class-Path manifest attribute. */
     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<>();
     /** Empty icon for these plugins which have none */
@@ -133,7 +132,7 @@ public class PluginInformation {
             Manifest manifest = jar.getManifest();
             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) {
             throw new PluginException(name, e);
@@ -150,19 +149,35 @@ public class PluginInformation {
      * @throws PluginException if the plugin information can't be read from the input stream
      */
     public PluginInformation(InputStream manifestStream, String name, String url) throws PluginException {
-        this.name = name;
         try {
             Manifest manifest = new Manifest();
             manifest.read(manifestStream);
             if (url != null) {
                 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);
+    }
+
     /**
      * Updates the plugin information of this plugin information object with the
      * plugin information in a plugin information object retrieved from a plugin
@@ -188,8 +203,7 @@ public class PluginInformation {
         this.iconPath = other.iconPath;
         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);
     }
@@ -214,9 +228,8 @@ public class PluginInformation {
         this.file = other.file;
     }
 
-    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"));
         if (s != null && !Utils.isValidUrl(s)) {
@@ -317,9 +330,7 @@ public class PluginInformation {
                 libraries.add(Utils.fileToURL(entryFile));
             }
         }
-        for (Object o : attr.keySet()) {
-            this.attr.put(o.toString(), attr.getValue(o.toString()));
-        }
+        this.attr = attr;
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/plugins/PluginListParser.java b/src/org/openstreetmap/josm/plugins/PluginListParser.java
index 4009e0221..e7a050e92 100644
--- a/src/org/openstreetmap/josm/plugins/PluginListParser.java
+++ b/src/org/openstreetmap/josm/plugins/PluginListParser.java
@@ -11,6 +11,7 @@ import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.jar.Attributes;
 
 import org.openstreetmap.josm.tools.Logging;
 
@@ -29,14 +30,14 @@ public class PluginListParser {
      *
      * @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
                     );
@@ -61,36 +62,29 @@ public class PluginListParser {
         try (BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
             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)
                     throw new IOException(tr("Illegal entry in plugin list.") + " " + line);
                 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) {
             throw new PluginListParseException(e);
         }
     }
 
-    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) {
                 PluginInformation info = createInfo(name, url, manifest);
diff --git a/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java b/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java
index 14a922b3b..51fdfb44b 100644
--- a/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/MainApplicationTest.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.jar.Attributes;
 
 import javax.swing.JComponent;
 import javax.swing.JPanel;
@@ -204,7 +205,7 @@ public class MainApplicationTest {
 
     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());
     }
 
     /**
