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

Last change on this file since 1705 was 1647, checked in by stoecker, 15 years ago

fixed plugin handling a bit

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.plugins;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.IOException;
9import java.io.InputStream;
10import java.net.URL;
11import java.net.MalformedURLException;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.LinkedList;
15import java.util.List;
16import java.util.Map;
17import java.util.TreeMap;
18import java.util.jar.Attributes;
19import java.util.jar.JarInputStream;
20import java.util.jar.Manifest;
21
22import org.openstreetmap.josm.Main;
23
24/**
25 * Encapsulate general information about a plugin. This information is available
26 * without the need of loading any class from the plugin jar file.
27 *
28 * @author imi
29 */
30public class PluginInformation {
31 public File file = null;
32 public String name = null;
33 public int mainversion = 0;
34 public String className = null;
35 public String requires = null;
36 public String link = null;
37 public String description = null;
38 public boolean early = false;
39 public String author = null;
40 public int stage = 50;
41 public String version = null;
42 public String downloadlink = null;
43 public List<URL> libraries = new LinkedList<URL>();
44
45 public final Map<String, String> attr = new TreeMap<String, String>();
46
47 /**
48 * Used in the Plugin constructor to make the information of the plugin
49 * that is currently initializing available.
50 *
51 * If you think this is hacky, you are probably right. But it is
52 * convinient anyway ;-)
53 */
54 static PluginInformation currentPluginInitialization = null;
55
56 /**
57 * @param file the plugin jar file.
58 */
59 public PluginInformation(File file) {
60 this(file, file.getName().substring(0, file.getName().length()-4));
61 }
62
63 public PluginInformation(File file, String name) {
64 this.name = name;
65 this.file = file;
66 try {
67 JarInputStream jar = new JarInputStream(new FileInputStream(file));
68 Manifest manifest = jar.getManifest();
69 if (manifest == null)
70 throw new IOException(file+" contains no manifest.");
71 scanManifest(manifest);
72 libraries.add(0, fileToURL(file));
73 jar.close();
74 } catch (IOException e) {
75 throw new PluginException(null, name, e);
76 }
77 }
78
79 public PluginInformation(InputStream manifestStream, String name) {
80 this.name = name;
81 try {
82 Manifest manifest = new Manifest();
83 manifest.read(manifestStream);
84 scanManifest(manifest);
85 } catch (IOException e) {
86 throw new PluginException(null, name, e);
87 }
88 }
89
90 private void scanManifest(Manifest manifest)
91 {
92 String lang = Main.getLanguageCode()+"_";
93 Attributes attr = manifest.getMainAttributes();
94 className = attr.getValue("Plugin-Class");
95 String s = attr.getValue(lang+"Plugin-Link");
96 if(s == null)
97 s = attr.getValue("Plugin-Link");
98 link = s;
99 requires = attr.getValue("Plugin-Requires");
100 s = attr.getValue(lang+"Plugin-Description");
101 if(s == null)
102 {
103 s = attr.getValue("Plugin-Description");
104 if(s != null)
105 s = tr(s);
106 }
107 description = s;
108 early = Boolean.parseBoolean(attr.getValue("Plugin-Early"));
109 String stageStr = attr.getValue("Plugin-Stage");
110 stage = stageStr == null ? 50 : Integer.parseInt(stageStr);
111 version = attr.getValue("Plugin-Version");
112 try { mainversion = Integer.parseInt(attr.getValue("Plugin-Mainversion")); }
113 catch(NumberFormatException e) {}
114 author = attr.getValue("Author");
115
116 String classPath = attr.getValue(Attributes.Name.CLASS_PATH);
117 if (classPath != null) {
118 for (String entry : classPath.split(" ")) {
119 File entryFile;
120 if (new File(entry).isAbsolute())
121 entryFile = new File(entry);
122 else
123 entryFile = new File(file.getParent(), entry);
124
125 libraries.add(fileToURL(entryFile));
126 }
127 }
128 for (Object o : attr.keySet())
129 this.attr.put(o.toString(), attr.getValue(o.toString()));
130 }
131
132 public String getLinkDescription()
133 {
134 String d = description == null ? tr("no description available") : description;
135 if(link != null)
136 d += " <A HREF=\""+link+"\">"+tr("More details")+"</A>";
137 return d;
138 }
139
140 /**
141 * Load and instantiate the plugin
142 */
143 public PluginProxy load(Class<?> klass) {
144 try {
145 currentPluginInitialization = this;
146 return new PluginProxy(klass.newInstance(), this);
147 } catch (Exception e) {
148 throw new PluginException(null, name, e);
149 }
150 }
151
152 /**
153 * Load the class of the plugin
154 */
155 public Class<?> loadClass(ClassLoader classLoader) {
156 if (className == null)
157 return null;
158 try {
159 Class<?> realClass = Class.forName(className, true, classLoader);
160 return realClass;
161 } catch (Exception e) {
162 throw new PluginException(null, name, e);
163 }
164 }
165
166 public static URL fileToURL(File f) {
167 try {
168 return f.toURI().toURL();
169 } catch (MalformedURLException ex) {
170 return null;
171 }
172 }
173
174 /**
175 * Try to find a plugin after some criterias. Extract the plugin-information
176 * from the plugin and return it. The plugin is searched in the following way:
177 *
178 *<li>first look after an MANIFEST.MF in the package org.openstreetmap.josm.plugins.<plugin name>
179 * (After removing all fancy characters from the plugin name).
180 * If found, the plugin is loaded using the bootstrap classloader.
181 *<li>If not found, look for a jar file in the user specific plugin directory
182 * (~/.josm/plugins/<plugin name>.jar)
183 *<li>If not found and the environment variable JOSM_RESSOURCES + "/plugins/" exist, look there.
184 *<li>Try for the java property josm.ressources + "/plugins/" (set via java -Djosm.plugins.path=...)
185 *<li>If the environment variable ALLUSERSPROFILE and APPDATA exist, look in
186 * ALLUSERSPROFILE/<the last stuff from APPDATA>/JOSM/plugins.
187 * (*sic* There is no easy way under Windows to get the All User's application
188 * directory)
189 *<li>Finally, look in some typical unix paths:<ul>
190 * <li>/usr/local/share/josm/plugins/
191 * <li>/usr/local/lib/josm/plugins/
192 * <li>/usr/share/josm/plugins/
193 * <li>/usr/lib/josm/plugins/
194 *
195 * If a plugin class or jar file is found earlier in the list but seem not to
196 * be working, an PluginException is thrown rather than continuing the search.
197 * This is so JOSM can detect broken user-provided plugins and do not go silently
198 * ignore them.
199 *
200 * The plugin is not initialized. If the plugin is a .jar file, it is not loaded
201 * (only the manifest is extracted). In the classloader-case, the class is
202 * bootstraped (e.g. static {} - declarations will run. However, nothing else is done.
203 *
204 * @param pluginName The name of the plugin (in all lowercase). E.g. "lang-de"
205 * @return Information about the plugin or <code>null</code>, if the plugin
206 * was nowhere to be found.
207 * @throws PluginException In case of broken plugins.
208 */
209 public static PluginInformation findPlugin(String pluginName) throws PluginException {
210 String name = pluginName;
211 name = name.replaceAll("[-. ]", "");
212 InputStream manifestStream = PluginInformation.class.getResourceAsStream("/org/openstreetmap/josm/plugins/"+name+"/MANIFEST.MF");
213 if (manifestStream != null)
214 return new PluginInformation(manifestStream, pluginName);
215
216 Collection<String> locations = getPluginLocations();
217
218 for (String s : locations) {
219 File pluginFile = new File(s, pluginName + ".jar");
220 if (pluginFile.exists()) {
221 PluginInformation info = new PluginInformation(pluginFile);
222 return info;
223 }
224 }
225 return null;
226 }
227
228 public static Collection<String> getPluginLocations() {
229 Collection<String> locations = Main.pref.getAllPossiblePreferenceDirs();
230 Collection<String> all = new ArrayList<String>(locations.size());
231 for (String s : locations)
232 all.add(s+"plugins");
233 return all;
234 }
235}
236
Note: See TracBrowser for help on using the repository browser.