source: josm/src/org/openstreetmap/josm/plugins/PluginInformation.java@ 277

Last change on this file since 277 was 277, checked in by imi, 17 years ago
  • added Plugin Manager to download new plugins from within JOSM
File size: 6.5 KB
Line 
1package org.openstreetmap.josm.plugins;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.IOException;
6import java.io.InputStream;
7import java.net.URL;
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.List;
11import java.util.Map;
12import java.util.TreeMap;
13import java.util.jar.Attributes;
14import java.util.jar.JarInputStream;
15import java.util.jar.Manifest;
16
17import org.openstreetmap.josm.Main;
18
19/**
20 * Encapsulate general information about a plugin. This information is available
21 * without the need of loading any class from the plugin jar file.
22 *
23 * @author imi
24 */
25public class PluginInformation {
26
27 public final File file;
28 public final String name;
29 public final String className;
30 public final String description;
31 public final boolean early;
32 public final String author;
33 public final int stage;
34 public final String version;
35 public final List<URL> libraries = new ArrayList<URL>();
36
37 public final Map<String, String> attr = new TreeMap<String, String>();
38
39 /**
40 * @param file the plugin jar file.
41 */
42 public PluginInformation(File file) {
43 this(file, file.getName().substring(0, file.getName().length()-4), null);
44 }
45
46 public PluginInformation(File file, String name, InputStream manifestStream) {
47 this.name = name;
48 this.file = file;
49 try {
50 Manifest manifest;
51 JarInputStream jar = null;
52 if (file != null) {
53 jar = new JarInputStream(new FileInputStream(file));
54 manifest = jar.getManifest();
55 if (manifest == null)
56 throw new IOException(file+" contains no manifest.");
57 } else {
58 manifest = new Manifest();
59 manifest.read(manifestStream);
60 }
61 Attributes attr = manifest.getMainAttributes();
62 className = attr.getValue("Plugin-Class");
63 description = attr.getValue("Plugin-Description");
64 early = Boolean.parseBoolean(attr.getValue("Plugin-Early"));
65 String stageStr = attr.getValue("Plugin-Stage");
66 stage = stageStr == null ? 50 : Integer.parseInt(stageStr);
67 version = attr.getValue("Plugin-Version");
68 author = attr.getValue("Author");
69 if (file != null)
70 libraries.add(new URL(getURLString(file.getAbsolutePath())));
71 String classPath = attr.getValue(Attributes.Name.CLASS_PATH);
72 if (classPath != null) {
73 String[] cp = classPath.split(" ");
74 StringBuilder entry = new StringBuilder();
75 for (String s : cp) {
76 entry.append(s);
77 if (s.endsWith("\\")) {
78 entry.setLength(entry.length()-1);
79 entry.append("%20"); // append the split character " " as html-encode
80 continue;
81 }
82 s = entry.toString();
83 entry = new StringBuilder();
84 if (!s.startsWith("/") && !s.startsWith("\\") && !s.matches("^.\\:") && file != null)
85 s = file.getParent() + File.separator + s;
86 libraries.add(new URL(getURLString(s)));
87 }
88 }
89
90 for (Object o : attr.keySet())
91 this.attr.put(o.toString(), attr.getValue(o.toString()));
92 if (jar != null)
93 jar.close();
94 } catch (IOException e) {
95 throw new PluginException(null, name, e);
96 }
97 }
98
99 /**
100 * Load and instantiate the plugin
101 */
102 public PluginProxy load(Class<?> klass) {
103 try {
104 return new PluginProxy(klass.newInstance(), this);
105 } catch (Exception e) {
106 throw new PluginException(null, name, e);
107 }
108 }
109
110 /**
111 * Load the class of the plugin
112 */
113 public Class<?> loadClass(ClassLoader classLoader) {
114 try {
115 Class<?> realClass = Class.forName(className, true, classLoader);
116 return realClass;
117 } catch (Exception e) {
118 throw new PluginException(null, name, e);
119 }
120 }
121
122 public static String getURLString(String fileName) {
123 if (System.getProperty("os.name").startsWith("Windows"))
124 return "file:/"+fileName;
125 return "file://"+fileName;
126 }
127
128 /**
129 * Try to find a plugin after some criterias. Extract the plugin-information
130 * from the plugin and return it. The plugin is searched in the following way:
131 *
132 *<li>first look after an MANIFEST.MF in the package org.openstreetmap.josm.plugins.<plugin name>
133 * (After removing all fancy characters from the plugin name).
134 * If found, the plugin is loaded using the bootstrap classloader.
135 *<li>If not found, look for a jar file in the user specific plugin directory
136 * (~/.josm/plugins/<plugin name>.jar)
137 *<li>If not found and the environment variable JOSM_RESSOURCES + "/plugins/" exist, look there.
138 *<li>Try for the java property josm.ressources + "/plugins/" (set via java -Djosm.plugins.path=...)
139 *<li>If the environment variable ALLUSERSPROFILE and APPDATA exist, look in
140 * ALLUSERSPROFILE/<the last stuff from APPDATA>/JOSM/plugins.
141 * (*sic* There is no easy way under Windows to get the All User's application
142 * directory)
143 *<li>Finally, look in some typical unix paths:<ul>
144 * <li>/usr/local/share/josm/plugins/
145 * <li>/usr/local/lib/josm/plugins/
146 * <li>/usr/share/josm/plugins/
147 * <li>/usr/lib/josm/plugins/
148 *
149 * If a plugin class or jar file is found earlier in the list but seem not to
150 * be working, an PluginException is thrown rather than continuing the search.
151 * This is so JOSM can detect broken user-provided plugins and do not go silently
152 * ignore them.
153 *
154 * The plugin is not initialized. If the plugin is a .jar file, it is not loaded
155 * (only the manifest is extracted). In the classloader-case, the class is
156 * bootstraped (e.g. static {} - declarations will run. However, nothing else is done.
157 *
158 * @param pluginName The name of the plugin (in all lowercase). E.g. "lang-de"
159 * @return Information about the plugin or <code>null</code>, if the plugin
160 * was nowhere to be found.
161 * @throws PluginException In case of broken plugins.
162 */
163 public static PluginInformation findPlugin(String pluginName) throws PluginException {
164 String name = pluginName;
165 name = name.replaceAll("[-. ]", "");
166 InputStream manifestStream = PluginInformation.class.getResourceAsStream("/org/openstreetmap/josm/plugins/"+name+"/MANIFEST.MF");
167 if (manifestStream != null)
168 return new PluginInformation(null, pluginName, manifestStream);
169
170 Collection<String> locations = getPluginLocations();
171
172 for (String s : locations) {
173 File pluginFile = new File(s+"/"+pluginName+".jar");
174 if (pluginFile.exists()) {
175 PluginInformation info = new PluginInformation(pluginFile);
176 return info;
177 }
178 }
179 return null;
180 }
181
182 public static Collection<String> getPluginLocations() {
183 Collection<String> locations = Main.pref.getAllPossiblePreferenceDirs();
184 Collection<String> all = new ArrayList<String>(locations.size());
185 for (String s : locations)
186 all.add(s+"plugins");
187 return all;
188 }
189}
190
Note: See TracBrowser for help on using the repository browser.