Changeset 1169 in josm for trunk/src/org/openstreetmap/josm/plugins
- Timestamp:
- 2008-12-23T15:07:05+01:00 (16 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/plugins
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/plugins/Plugin.java
r873 r1169 24 24 * 25 25 * The actual implementation of this class is optional, as all functions will be called 26 * via reflection. This is to be able to change this interface without the need of 26 * via reflection. This is to be able to change this interface without the need of 27 27 * recompiling or even breaking the plugins. If your class does not provide a 28 28 * function here (or does provide a function with a mismatching signature), it will not … … 32 32 * are provided (you can register yourself to more callbacks in your plugin class 33 33 * constructor). 34 * 34 * 35 35 * Subclassing Plugin and overriding some functions makes it easy for you to keep sync 36 36 * with the correct actual plugin architecture of JOSM. … … 40 40 public abstract class Plugin { 41 41 42 43 44 45 46 47 48 49 42 /** 43 * This is the info available for this plugin. You can access this from your 44 * constructor. 45 * 46 * (The actual implementation to request the info from a static variable 47 * is a bit hacky, but it works). 48 */ 49 public final PluginInformation info = PluginInformation.currentPluginInitialization; 50 50 51 52 53 54 55 56 51 /** 52 * @return The directory for the plugin to store all kind of stuff. 53 */ 54 public final String getPluginDir() { 55 return new File(Main.pref.getPluginsDirFile(), info.name).getPath(); 56 } 57 57 58 59 60 61 62 63 58 /** 59 * Called after Main.mapFrame is initalized. (After the first data is loaded). 60 * You can use this callback to tweak the newFrame to your needs, as example install 61 * an alternative Painter. 62 */ 63 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {} 64 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 65 /** 66 * Called in the preferences dialog to create a preferences page for the plugin, 67 * if any available. 68 */ 69 public PreferenceSetting getPreferenceSetting() { return null; } 70 71 /** 72 * Called in the download dialog to give the plugin a chance to modify the list 73 * of bounding box selectors. 74 */ 75 public void addDownloadSelection(List<DownloadSelection> list) {} 76 77 /** 78 * Copies the ressource 'from' to the file in the plugin directory named 'to'. 79 */ 80 public void copy(String from, String to) throws FileNotFoundException, IOException { 81 String pluginDirName = Main.pref.getPreferencesDir()+"plugins/"+info.name+"/"; 82 82 File pluginDir = new File(pluginDirName); 83 83 if (!pluginDir.exists()) 84 84 pluginDir.mkdirs(); 85 85 FileOutputStream out = new FileOutputStream(pluginDirName+to); 86 86 InputStream in = getClass().getResourceAsStream(from); 87 87 byte[] buffer = new byte[8192]; 88 88 for(int len = in.read(buffer); len > 0; len = in.read(buffer)) 89 89 out.write(buffer, 0, len); 90 90 in.close(); 91 91 out.close(); -
trunk/src/org/openstreetmap/josm/plugins/PluginDownloader.java
r1073 r1169 1 1 //License: GPL. Copyright 2007 by Immanuel Scholz and others 2 2 /** 3 * 3 * 4 4 */ 5 5 package org.openstreetmap.josm.plugins; … … 34 34 public class PluginDownloader { 35 35 36 37 38 39 36 private static final class UpdateTask extends PleaseWaitRunnable { 37 private final Collection<PluginDescription> toUpdate; 38 private String errors = ""; 39 private int count = 0; 40 40 41 42 43 44 41 private UpdateTask(Collection<PluginDescription> toUpdate) { 42 super(tr("Update Plugins")); 43 this.toUpdate = toUpdate; 44 } 45 45 46 47 48 46 @Override protected void cancel() { 47 finish(); 48 } 49 49 50 51 52 53 54 55 50 @Override protected void finish() { 51 if (errors.length() > 0) 52 JOptionPane.showMessageDialog(Main.parent, tr("There were problems with the following plugins:\n\n {0}",errors)); 53 else 54 JOptionPane.showMessageDialog(Main.parent, trn("{0} Plugin successfully updated. Please restart JOSM.", "{0} Plugins successfully updated. Please restart JOSM.", count, count)); 55 } 56 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 57 @Override protected void realRun() throws SAXException, IOException { 58 File pluginDir = Main.pref.getPluginsDirFile(); 59 if (!pluginDir.exists()) 60 pluginDir.mkdirs(); 61 for (PluginDescription d : toUpdate) { 62 File pluginFile = new File(pluginDir, d.name + ".jar.new"); 63 if (download(d.resource, pluginFile)) 64 count++; 65 else 66 errors += d.name + "\n"; 67 } 68 PluginDownloader.moveUpdatedPlugins(); 69 } 70 } 71 71 72 72 private static final Pattern wiki = Pattern.compile("^</td></tr><tr><td><a class=\"ext-link\" href=\"([^\"]*)\"><span class=\"icon\">([^<]*)</span></a></td><td>([^<]*)</td><td>([^<].*)</td><td>(.*)"); 73 73 74 74 private final static String[] pluginSites = {"http://josm.openstreetmap.de/wiki/Plugins"}; 75 75 76 77 78 76 public static Collection<String> getSites() { 77 return Main.pref.getCollection("pluginmanager.sites", Arrays.asList(pluginSites)); 78 } 79 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 80 public static int downloadDescription() { 81 int count = 0; 82 for (String site : getSites()) { 83 try { 84 BufferedReader r = new BufferedReader(new InputStreamReader(new URL(site).openStream())); 85 CharSequence txt; 86 if (site.toLowerCase().endsWith(".xml")) 87 txt = readXml(r); 88 else 89 txt = readWiki(r); 90 r.close(); 91 new File(Main.pref.getPreferencesDir()+"plugins").mkdir(); 92 FileWriter out = new FileWriter(new File(Main.pref 93 .getPluginsDirFile(), count + "-site-" 94 + site.replaceAll("[/:\\\\ <>|]", "_") + ".xml")); 95 out.append(txt); 96 out.close(); 97 count++; 98 } catch (IOException x) { 99 } 100 } 101 return count; 102 } 103 103 104 105 106 107 108 109 104 private static CharSequence readXml(BufferedReader r) throws IOException { 105 StringBuilder b = new StringBuilder(); 106 for (String line = r.readLine(); line != null; line = r.readLine()) 107 b.append(line+"\n"); 108 return b; 109 } 110 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 111 private static CharSequence readWiki(BufferedReader r) throws IOException { 112 StringBuilder b = new StringBuilder("<plugins>\n"); 113 for (String line = r.readLine(); line != null; line = r.readLine()) { 114 Matcher m = wiki.matcher(line); 115 if (!m.matches()) 116 continue; 117 b.append(" <plugin>\n"); 118 b.append(" <name>"+escape(m.group(2))+"</name>\n"); 119 b.append(" <resource>"+escape(m.group(1))+"</resource>\n"); 120 b.append(" <author>"+escape(m.group(3))+"</author>\n"); 121 b.append(" <description>"+escape(m.group(4))+"</description>\n"); 122 b.append(" <version>"+escape(m.group(5))+"</version>\n"); 123 b.append(" </plugin>\n"); 124 } 125 b.append("</plugins>\n"); 126 return b; 127 } 128 128 129 130 131 129 private static String escape(String s) { 130 return s.replaceAll("<", "<").replaceAll(">", ">"); 131 } 132 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 133 public static boolean downloadPlugin(PluginDescription pd) { 134 File file = new File(Main.pref.getPluginsDirFile(), pd.name + ".jar"); 135 if (!download(pd.resource, file)) { 136 JOptionPane.showMessageDialog(Main.parent, tr("Could not download plugin: {0} from {1}", pd.name, pd.resource)); 137 } else { 138 try { 139 PluginInformation.findPlugin(pd.name); 140 return true; 141 } catch (Exception e) { 142 e.printStackTrace(); 143 JOptionPane.showMessageDialog(Main.parent, tr("The plugin {0} seem to be broken or could not be downloaded automatically.", pd.name)); 144 } 145 } 146 if (file.exists()) 147 file.delete(); 148 return false; 149 } 150 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 151 private static boolean download(String url, File file) { 152 try { 153 InputStream in = new URL(url).openStream(); 154 OutputStream out = new FileOutputStream(file); 155 byte[] buffer = new byte[8192]; 156 for (int read = in.read(buffer); read != -1; read = in.read(buffer)) 157 out.write(buffer, 0, read); 158 out.close(); 159 in.close(); 160 return true; 161 } catch (MalformedURLException e) { 162 e.printStackTrace(); 163 } catch (FileNotFoundException e) { 164 e.printStackTrace(); 165 } catch (IOException e) { 166 e.printStackTrace(); 167 } 168 return false; 169 } 170 170 171 172 173 174 175 176 177 178 179 180 181 171 public static void update(Collection<PluginDescription> update) { 172 Main.worker.execute(new UpdateTask(update)); 173 } 174 175 public static boolean moveUpdatedPlugins() { 176 File pluginDir = Main.pref.getPluginsDirFile(); 177 boolean ok = true; 178 if (pluginDir.exists() && pluginDir.isDirectory() && pluginDir.canWrite()) { 179 final File[] files = pluginDir.listFiles(new FilenameFilter() { 180 public boolean accept(File dir, String name) { 181 return name.endsWith(".new"); 182 182 }}); 183 184 185 186 187 188 189 190 183 for (File updatedPlugin : files) { 184 final String filePath = updatedPlugin.getPath(); 185 File plugin = new File(filePath.substring(0, filePath.length() - 4)); 186 ok = (plugin.delete() || !plugin.exists()) && updatedPlugin.renameTo(plugin) && ok; 187 } 188 } 189 return ok; 190 } 191 191 } -
trunk/src/org/openstreetmap/josm/plugins/PluginException.java
r1116 r1169 8 8 * and there is no particular reason to use this within the plugin itself (although there 9 9 * is also no reason against this.. ;) 10 * 10 * 11 11 * @author Immanuel.Scholz 12 12 */ 13 13 public class PluginException extends RuntimeException { 14 15 14 public final PluginProxy plugin; 15 public final String name; 16 16 17 18 19 20 17 public PluginException(PluginProxy plugin, String name, Throwable cause) { 18 super(tr("An error occured in plugin {0}", name), cause); 19 this.plugin = plugin; 20 this.name = name; 21 21 } 22 22 } -
trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
r1073 r1169 29 29 */ 30 30 public class PluginInformation { 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 * 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 * 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 * 177 178 179 180 181 * 182 183 184 185 186 187 188 *was nowhere to be found.189 190 191 192 193 194 195 196 31 32 public final File file; 33 public final String name; 34 public final String mainversion; 35 public final String className; 36 public final String description; 37 public final boolean early; 38 public final String author; 39 public final int stage; 40 public final String version; 41 public final List<URL> libraries = new LinkedList<URL>(); 42 43 public final Map<String, String> attr = new TreeMap<String, String>(); 44 45 /** 46 * Used in the Plugin constructor to make the information of the plugin 47 * that is currently initializing available. 48 * 49 * If you think this is hacky, you are probably right. But it is 50 * convinient anyway ;-) 51 */ 52 static PluginInformation currentPluginInitialization = null; 53 54 /** 55 * @param file the plugin jar file. 56 */ 57 public PluginInformation(File file) { 58 this(file, file.getName().substring(0, file.getName().length()-4), null); 59 } 60 61 public PluginInformation(File file, String name, InputStream manifestStream) { 62 this.name = name; 63 this.file = file; 64 try { 65 Manifest manifest; 66 JarInputStream jar = null; 67 if (file != null) { 68 jar = new JarInputStream(new FileInputStream(file)); 69 manifest = jar.getManifest(); 70 if (manifest == null) 71 throw new IOException(file+" contains no manifest."); 72 } else { 73 manifest = new Manifest(); 74 manifest.read(manifestStream); 75 } 76 if (manifest != null) { 77 Attributes attr = manifest.getMainAttributes(); 78 className = attr.getValue("Plugin-Class"); 79 description = attr.getValue("Plugin-Description"); 80 early = Boolean.parseBoolean(attr.getValue("Plugin-Early")); 81 String stageStr = attr.getValue("Plugin-Stage"); 82 stage = stageStr == null ? 50 : Integer.parseInt(stageStr); 83 version = attr.getValue("Plugin-Version"); 84 mainversion = attr.getValue("Plugin-Mainversion"); 85 author = attr.getValue("Author"); 86 87 String classPath = attr.getValue(Attributes.Name.CLASS_PATH); 88 if (classPath != null) { 89 for (String entry : classPath.split(" ")) { 90 File entryFile; 91 if (new File(entry).isAbsolute()) { 92 entryFile = new File(entry); 93 } else { 94 entryFile = new File(file.getParent(), entry); 95 } 96 97 libraries.add(fileToURL(entryFile)); 98 } 99 } 100 for (Object o : attr.keySet()) 101 this.attr.put(o.toString(), attr.getValue(o.toString())); 102 } else { 103 // resource-only plugin 104 className = null; 105 mainversion = null; 106 description = tr("unknown"); 107 early = false; 108 stage = 50; 109 version = null; 110 author = null; 111 } 112 if (file != null) 113 libraries.add(0, fileToURL(file)); 114 115 if (jar != null) 116 jar.close(); 117 } catch (IOException e) { 118 throw new PluginException(null, name, e); 119 } 120 } 121 122 /** 123 * Load and instantiate the plugin 124 */ 125 public PluginProxy load(Class<?> klass) { 126 try { 127 currentPluginInitialization = this; 128 return new PluginProxy(klass.newInstance(), this); 129 } catch (Exception e) { 130 throw new PluginException(null, name, e); 131 } 132 } 133 134 /** 135 * Load the class of the plugin 136 */ 137 public Class<?> loadClass(ClassLoader classLoader) { 138 if (className == null) 139 return null; 140 try { 141 Class<?> realClass = Class.forName(className, true, classLoader); 142 return realClass; 143 } catch (Exception e) { 144 throw new PluginException(null, name, e); 145 } 146 } 147 148 public static URL fileToURL(File f) { 149 try { 150 return f.toURI().toURL(); 151 } catch (MalformedURLException ex) { 152 return null; 153 } 154 } 155 156 /** 157 * Try to find a plugin after some criterias. Extract the plugin-information 158 * from the plugin and return it. The plugin is searched in the following way: 159 * 160 *<li>first look after an MANIFEST.MF in the package org.openstreetmap.josm.plugins.<plugin name> 161 * (After removing all fancy characters from the plugin name). 162 * If found, the plugin is loaded using the bootstrap classloader. 163 *<li>If not found, look for a jar file in the user specific plugin directory 164 * (~/.josm/plugins/<plugin name>.jar) 165 *<li>If not found and the environment variable JOSM_RESSOURCES + "/plugins/" exist, look there. 166 *<li>Try for the java property josm.ressources + "/plugins/" (set via java -Djosm.plugins.path=...) 167 *<li>If the environment variable ALLUSERSPROFILE and APPDATA exist, look in 168 * ALLUSERSPROFILE/<the last stuff from APPDATA>/JOSM/plugins. 169 * (*sic* There is no easy way under Windows to get the All User's application 170 * directory) 171 *<li>Finally, look in some typical unix paths:<ul> 172 * <li>/usr/local/share/josm/plugins/ 173 * <li>/usr/local/lib/josm/plugins/ 174 * <li>/usr/share/josm/plugins/ 175 * <li>/usr/lib/josm/plugins/ 176 * 177 * If a plugin class or jar file is found earlier in the list but seem not to 178 * be working, an PluginException is thrown rather than continuing the search. 179 * This is so JOSM can detect broken user-provided plugins and do not go silently 180 * ignore them. 181 * 182 * The plugin is not initialized. If the plugin is a .jar file, it is not loaded 183 * (only the manifest is extracted). In the classloader-case, the class is 184 * bootstraped (e.g. static {} - declarations will run. However, nothing else is done. 185 * 186 * @param pluginName The name of the plugin (in all lowercase). E.g. "lang-de" 187 * @return Information about the plugin or <code>null</code>, if the plugin 188 * was nowhere to be found. 189 * @throws PluginException In case of broken plugins. 190 */ 191 public static PluginInformation findPlugin(String pluginName) throws PluginException { 192 String name = pluginName; 193 name = name.replaceAll("[-. ]", ""); 194 InputStream manifestStream = PluginInformation.class.getResourceAsStream("/org/openstreetmap/josm/plugins/"+name+"/MANIFEST.MF"); 195 if (manifestStream != null) 196 return new PluginInformation(null, pluginName, manifestStream); 197 197 198 198 Collection<String> locations = getPluginLocations(); 199 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 } 217 218 219 220 221 * 222 223 224 * 225 226 227 228 229 230 231 232 233 200 for (String s : locations) { 201 File pluginFile = new File(s, pluginName + ".jar"); 202 if (pluginFile.exists()) { 203 PluginInformation info = new PluginInformation(pluginFile); 204 return info; 205 } 206 } 207 return null; 208 } 209 210 public static Collection<String> getPluginLocations() { 211 Collection<String> locations = Main.pref.getAllPossiblePreferenceDirs(); 212 Collection<String> all = new ArrayList<String>(locations.size()); 213 for (String s : locations) 214 all.add(s+"plugins"); 215 return all; 216 } 217 218 219 /** 220 * Return information about a loaded plugin. 221 * 222 * Note that if you call this in your plugins bootstrap, you may get <code>null</code> if 223 * the plugin requested is not loaded yet. 224 * 225 * @return The PluginInformation to a specific plugin, but only if the plugin is loaded. 226 * If it is not loaded, <code>null</code> is returned. 227 */ 228 public static PluginInformation getLoaded(String pluginName) { 229 for (PluginProxy p : Main.plugins) 230 if (p.info.name.equals(pluginName)) 231 return p.info; 232 return null; 233 } 234 234 } 235 235 -
trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java
r627 r1169 18 18 public class PluginProxy extends Plugin { 19 19 20 21 20 public final Object plugin; 21 public final PluginInformation info; 22 22 23 24 25 23 public PluginProxy(Object plugin, PluginInformation info) { 24 this.plugin = plugin; 25 this.info = info; 26 26 } 27 27 28 29 30 28 @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 29 try { 30 plugin.getClass().getMethod("mapFrameInitialized", MapFrame.class, MapFrame.class).invoke(plugin, oldFrame, newFrame); 31 31 } catch (NoSuchMethodException e) { 32 32 } catch (Exception e) { 33 33 throw new PluginException(this, info.name, e); 34 34 } 35 35 } 36 36 37 38 39 40 41 42 43 44 37 @Override public PreferenceSetting getPreferenceSetting() { 38 try { 39 return (PreferenceSetting)plugin.getClass().getMethod("getPreferenceSetting").invoke(plugin); 40 } catch (NoSuchMethodException e) { 41 return null; 42 } catch (Exception e) { 43 throw new PluginException(this, info.name, e); 44 } 45 45 } 46 47 48 49 50 51 52 53 54 55 46 47 @Override public void addDownloadSelection(List<DownloadSelection> list) { 48 try { 49 plugin.getClass().getMethod("addDownloadSelection", List.class).invoke(plugin, list); 50 } catch (NoSuchMethodException e) { 51 // ignore 52 } catch (Exception e) { 53 throw new PluginException(this, info.name, e); 54 } 55 } 56 56 }
Note:
See TracChangeset
for help on using the changeset viewer.