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    }