1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.plugins;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.io.BufferedReader;
|
---|
7 | import java.io.ByteArrayInputStream;
|
---|
8 | import java.io.IOException;
|
---|
9 | import java.io.InputStream;
|
---|
10 | import java.io.InputStreamReader;
|
---|
11 | import java.nio.charset.StandardCharsets;
|
---|
12 | import java.util.LinkedList;
|
---|
13 | import java.util.List;
|
---|
14 |
|
---|
15 | import org.openstreetmap.josm.tools.Logging;
|
---|
16 |
|
---|
17 | /**
|
---|
18 | * A parser for the plugin list provided by a JOSM Plugin Download Site.
|
---|
19 | *
|
---|
20 | * See <a href="https://josm.openstreetmap.de/plugin">https://josm.openstreetmap.de/plugin</a>
|
---|
21 | * for a sample of the document. The format is a custom format, kind of mix of CSV and RFC822 style
|
---|
22 | * name/value-pairs.
|
---|
23 | *
|
---|
24 | */
|
---|
25 | public class PluginListParser {
|
---|
26 |
|
---|
27 | /**
|
---|
28 | * Creates the plugin information object
|
---|
29 | *
|
---|
30 | * @param name the plugin name
|
---|
31 | * @param url the plugin download url
|
---|
32 | * @param manifest the plugin manifest
|
---|
33 | * @return a plugin information object
|
---|
34 | * @throws PluginListParseException if plugin manifest cannot be parsed
|
---|
35 | */
|
---|
36 | public static PluginInformation createInfo(String name, String url, String manifest) throws PluginListParseException {
|
---|
37 | try {
|
---|
38 | return new PluginInformation(
|
---|
39 | new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8)),
|
---|
40 | name.substring(0, name.length() - 4),
|
---|
41 | url
|
---|
42 | );
|
---|
43 | } catch (PluginException e) {
|
---|
44 | throw new PluginListParseException(tr("Failed to create plugin information from manifest for plugin ''{0}''", name), e);
|
---|
45 | }
|
---|
46 | }
|
---|
47 |
|
---|
48 | /**
|
---|
49 | * Parses a plugin information document and replies a list of plugin information objects.
|
---|
50 | *
|
---|
51 | * See <a href="https://josm.openstreetmap.de/plugin">https://josm.openstreetmap.de/plugin</a>
|
---|
52 | * for a sample of the document. The format is a custom format, kind of mix of CSV and RFC822 style
|
---|
53 | * name/value-pairs.
|
---|
54 | *
|
---|
55 | * @param in the input stream from which to parse
|
---|
56 | * @return the list of plugin information objects
|
---|
57 | * @throws PluginListParseException if something goes wrong while parsing
|
---|
58 | */
|
---|
59 | public List<PluginInformation> parse(InputStream in) throws PluginListParseException {
|
---|
60 | List<PluginInformation> ret = new LinkedList<>();
|
---|
61 | BufferedReader r = null;
|
---|
62 | try {
|
---|
63 | r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
|
---|
64 | String name = null;
|
---|
65 | String url = null;
|
---|
66 | StringBuilder manifest = new StringBuilder();
|
---|
67 | for (String line = r.readLine(); line != null; line = r.readLine()) {
|
---|
68 | if (line.startsWith("\t")) {
|
---|
69 | line = line.substring(1);
|
---|
70 | /* NOTE: Although manifest specification says line should not be longer than 72 bytes it
|
---|
71 | supports more than 500 bytes and thus even the longest possible 72 character UTF-8, so
|
---|
72 | this code correctly splits the text at 70 characters, not bytes. */
|
---|
73 | while (line.length() > 70) {
|
---|
74 | manifest.append(line.substring(0, 70)).append('\n');
|
---|
75 | line = ' ' + line.substring(70);
|
---|
76 | }
|
---|
77 | manifest.append(line).append('\n');
|
---|
78 | continue;
|
---|
79 | }
|
---|
80 | addPluginInformation(ret, name, url, manifest.toString());
|
---|
81 | String[] x = line.split(";");
|
---|
82 | if (x.length != 2)
|
---|
83 | throw new IOException(tr("Illegal entry in plugin list."));
|
---|
84 | name = x[0];
|
---|
85 | url = x[1];
|
---|
86 | manifest = new StringBuilder();
|
---|
87 |
|
---|
88 | }
|
---|
89 | addPluginInformation(ret, name, url, manifest.toString());
|
---|
90 | return ret;
|
---|
91 | } catch (IOException e) {
|
---|
92 | throw new PluginListParseException(e);
|
---|
93 | }
|
---|
94 | }
|
---|
95 |
|
---|
96 | private static void addPluginInformation(List<PluginInformation> ret, String name, String url, String manifest) {
|
---|
97 | try {
|
---|
98 | if (name != null) {
|
---|
99 | PluginInformation info = createInfo(name, url, manifest);
|
---|
100 | for (PluginProxy plugin : PluginHandler.pluginList) {
|
---|
101 | if (plugin.getPluginInformation().name.equals(info.getName())) {
|
---|
102 | info.localversion = plugin.getPluginInformation().localversion;
|
---|
103 | }
|
---|
104 | }
|
---|
105 | ret.add(info);
|
---|
106 | }
|
---|
107 | } catch (PluginListParseException ex) {
|
---|
108 | Logging.error(ex);
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | }
|
---|