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 }