| 1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others |
|---|
| 2 | package org.openstreetmap.josm.plugins; |
|---|
| 3 | |
|---|
| 4 | import java.io.File; |
|---|
| 5 | import java.io.FileNotFoundException; |
|---|
| 6 | import java.io.FileOutputStream; |
|---|
| 7 | import java.io.IOException; |
|---|
| 8 | import java.io.InputStream; |
|---|
| 9 | import java.net.URL; |
|---|
| 10 | import java.net.URLClassLoader; |
|---|
| 11 | import java.util.List; |
|---|
| 12 | |
|---|
| 13 | import org.openstreetmap.josm.Main; |
|---|
| 14 | import org.openstreetmap.josm.gui.MapFrame; |
|---|
| 15 | import org.openstreetmap.josm.gui.download.DownloadSelection; |
|---|
| 16 | import org.openstreetmap.josm.gui.preferences.PreferenceSetting; |
|---|
| 17 | |
|---|
| 18 | /** |
|---|
| 19 | * For all purposes of loading dynamic resources, the Plugin's class loader should be used |
|---|
| 20 | * (or else, the plugin jar will not be within the class path). |
|---|
| 21 | * |
|---|
| 22 | * A plugin may subclass this abstract base class (but it is optional). |
|---|
| 23 | * |
|---|
| 24 | * The actual implementation of this class is optional, as all functions will be called |
|---|
| 25 | * via reflection. This is to be able to change this interface without the need of |
|---|
| 26 | * recompiling or even breaking the plugins. If your class does not provide a |
|---|
| 27 | * function here (or does provide a function with a mismatching signature), it will not |
|---|
| 28 | * be called. That simple. |
|---|
| 29 | * |
|---|
| 30 | * Or in other words: See this base class as an documentation of what automatic callbacks |
|---|
| 31 | * are provided (you can register yourself to more callbacks in your plugin class |
|---|
| 32 | * constructor). |
|---|
| 33 | * |
|---|
| 34 | * Subclassing Plugin and overriding some functions makes it easy for you to keep sync |
|---|
| 35 | * with the correct actual plugin architecture of JOSM. |
|---|
| 36 | * |
|---|
| 37 | * @author Immanuel.Scholz |
|---|
| 38 | */ |
|---|
| 39 | public abstract class Plugin { |
|---|
| 40 | |
|---|
| 41 | /** |
|---|
| 42 | * This is the info available for this plugin. You can access this from your |
|---|
| 43 | * constructor. |
|---|
| 44 | * |
|---|
| 45 | * (The actual implementation to request the info from a static variable |
|---|
| 46 | * is a bit hacky, but it works). |
|---|
| 47 | */ |
|---|
| 48 | private PluginInformation info = null; |
|---|
| 49 | |
|---|
| 50 | /** |
|---|
| 51 | * Creates the plugin |
|---|
| 52 | * |
|---|
| 53 | * @param info the plugin information describing the plugin. |
|---|
| 54 | */ |
|---|
| 55 | public Plugin(PluginInformation info) { |
|---|
| 56 | this.info = info; |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | /** |
|---|
| 60 | * Replies the plugin information object for this plugin |
|---|
| 61 | * |
|---|
| 62 | * @return the plugin information object |
|---|
| 63 | */ |
|---|
| 64 | public PluginInformation getPluginInformation() { |
|---|
| 65 | return info; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | /** |
|---|
| 69 | * Sets the plugin information object for this plugin |
|---|
| 70 | * |
|---|
| 71 | * @parma info the plugin information object |
|---|
| 72 | */ |
|---|
| 73 | public void setPluginInformation(PluginInformation info) { |
|---|
| 74 | this.info = info; |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | /** |
|---|
| 78 | * @return The directory for the plugin to store all kind of stuff. |
|---|
| 79 | */ |
|---|
| 80 | public String getPluginDir() { |
|---|
| 81 | return new File(Main.pref.getPluginsDirectory(), info.name).getPath(); |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | /** |
|---|
| 85 | * Called after Main.mapFrame is initalized. (After the first data is loaded). |
|---|
| 86 | * You can use this callback to tweak the newFrame to your needs, as example install |
|---|
| 87 | * an alternative Painter. |
|---|
| 88 | */ |
|---|
| 89 | public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {} |
|---|
| 90 | |
|---|
| 91 | /** |
|---|
| 92 | * Called in the preferences dialog to create a preferences page for the plugin, |
|---|
| 93 | * if any available. |
|---|
| 94 | */ |
|---|
| 95 | public PreferenceSetting getPreferenceSetting() { return null; } |
|---|
| 96 | |
|---|
| 97 | /** |
|---|
| 98 | * Called in the download dialog to give the plugin a chance to modify the list |
|---|
| 99 | * of bounding box selectors. |
|---|
| 100 | */ |
|---|
| 101 | public void addDownloadSelection(List<DownloadSelection> list) {} |
|---|
| 102 | |
|---|
| 103 | /** |
|---|
| 104 | * Copies the resource 'from' to the file in the plugin directory named 'to'. |
|---|
| 105 | */ |
|---|
| 106 | public void copy(String from, String to) throws FileNotFoundException, IOException { |
|---|
| 107 | String pluginDirName = getPluginDir(); |
|---|
| 108 | File pluginDir = new File(pluginDirName); |
|---|
| 109 | if (!pluginDir.exists()) { |
|---|
| 110 | pluginDir.mkdirs(); |
|---|
| 111 | } |
|---|
| 112 | FileOutputStream out = new FileOutputStream(new File(pluginDirName, to)); |
|---|
| 113 | InputStream in = getClass().getResourceAsStream(from); |
|---|
| 114 | byte[] buffer = new byte[8192]; |
|---|
| 115 | for(int len = in.read(buffer); len > 0; len = in.read(buffer)) { |
|---|
| 116 | out.write(buffer, 0, len); |
|---|
| 117 | } |
|---|
| 118 | in.close(); |
|---|
| 119 | out.close(); |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | /** |
|---|
| 123 | * Get a class loader for loading resources from the plugin jar. |
|---|
| 124 | * |
|---|
| 125 | * This can be used to avoid getting a file from another plugin that |
|---|
| 126 | * happens to have a file with the same file name and path. |
|---|
| 127 | * |
|---|
| 128 | * Usage: Instead of |
|---|
| 129 | * getClass().getResource("/resources/pluginProperties.properties"); |
|---|
| 130 | * write |
|---|
| 131 | * getPluginResourceClassLoader().getResource("resources/pluginProperties.properties"); |
|---|
| 132 | * |
|---|
| 133 | * (Note the missing leading "/".) |
|---|
| 134 | */ |
|---|
| 135 | public ClassLoader getPluginResourceClassLoader() { |
|---|
| 136 | File pluginDir = Main.pref.getPluginsDirectory(); |
|---|
| 137 | File pluginJar = new File(pluginDir, info.name + ".jar"); |
|---|
| 138 | URL pluginJarUrl = PluginInformation.fileToURL(pluginJar); |
|---|
| 139 | URLClassLoader pluginClassLoader = new URLClassLoader(new URL[] { pluginJarUrl } , Main.class.getClassLoader()); |
|---|
| 140 | return pluginClassLoader; |
|---|
| 141 | } |
|---|
| 142 | } |
|---|