001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.plugins;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.io.BufferedReader;
007 import java.io.ByteArrayInputStream;
008 import java.io.IOException;
009 import java.io.InputStream;
010 import java.io.InputStreamReader;
011 import java.io.UnsupportedEncodingException;
012 import java.util.LinkedList;
013 import java.util.List;
014
015 /**
016 * A parser for the plugin list provided by a JOSM Plugin Download Site.
017 *
018 * See <a href="http://josm.openstreetmap.de/plugin">http://josm.openstreetmap.de/plugin</a>
019 * for a sample of the document. The format is a custom format, kind of mix of CSV and RFC822 style
020 * name/value-pairs.
021 *
022 */
023 public class PluginListParser {
024
025 /**
026 * Creates the plugin information object
027 *
028 * @param name the plugin name
029 * @param url the plugin download url
030 * @param manifest the plugin manifest
031 * @return a plugin information object
032 * @throws PluginListParseException
033 */
034 protected static PluginInformation createInfo(String name, String url, String manifest) throws PluginListParseException{
035 try {
036 return new PluginInformation(
037 new ByteArrayInputStream(manifest.getBytes("utf-8")),
038 name.substring(0, name.length() - 4),
039 url
040 );
041 } catch(UnsupportedEncodingException e) {
042 throw new PluginListParseException(tr("Failed to create plugin information from manifest for plugin ''{0}''", name), e);
043 } catch (PluginException e) {
044 throw new PluginListParseException(tr("Failed to create plugin information from manifest for plugin ''{0}''", name), e);
045 }
046 }
047
048 /**
049 * Parses a plugin information document and replies a list of plugin information objects.
050 *
051 * See <a href="http://josm.openstreetmap.de/plugin">http://josm.openstreetmap.de/plugin</a>
052 * for a sample of the document. The format is a custom format, kind of mix of CSV and RFC822 style
053 * name/value-pairs.
054 *
055 * @param in the input stream from which to parse
056 * @return the list of plugin information objects
057 * @throws PluginListParseException thrown if something goes wrong while parsing
058 */
059 public List<PluginInformation> parse(InputStream in) throws PluginListParseException{
060 List<PluginInformation> ret = new LinkedList<PluginInformation>();
061 BufferedReader r = null;
062 try {
063 r = new BufferedReader(new InputStreamReader(in, "utf-8"));
064 String name = null;
065 String url = null;
066 StringBuilder manifest = new StringBuilder();
067 /*
068 code structure:
069 for () {
070 A;
071 B;
072 C;
073 }
074 B;
075 */
076 for (String line = r.readLine(); line != null; line = r.readLine()) {
077 if (line.startsWith("\t")) {
078 line = line.substring(1);
079 while (line.length() > 70) {
080 manifest.append(line.substring(0, 70)).append("\n");
081 line = " " + line.substring(70);
082 }
083 manifest.append(line).append("\n");
084 continue;
085 }
086 addPluginInformation(ret, name, url, manifest.toString());
087 String x[] = line.split(";");
088 if(x.length != 2)
089 throw new IOException(tr("Illegal entry in plugin list."));
090 name = x[0];
091 url = x[1];
092 manifest = new StringBuilder();
093
094 }
095 addPluginInformation(ret, name, url, manifest.toString());
096 return ret;
097 } catch (IOException e) {
098 throw new PluginListParseException(e);
099 }
100 }
101
102 private static void addPluginInformation(List<PluginInformation> ret, String name, String url, String manifest) {
103 try {
104 if (name != null) {
105 PluginInformation info = createInfo(name, url, manifest.toString());
106 if (info != null) {
107 for (PluginProxy plugin : PluginHandler.pluginList) {
108 if (plugin.getPluginInformation().name.equals(info.getName())) {
109 info.localversion = plugin.getPluginInformation().localversion;
110 }
111 }
112 ret.add(info);
113 }
114 }
115 } catch (PluginListParseException ex) {
116 ex.printStackTrace();
117 }
118 }
119
120 }