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

Last change on this file since 2702 was 2620, checked in by jttt, 14 years ago

Remove OsmPrimitive.setIncomplete()

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