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

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

fix #1903 - don't download plugins for newer JOSM versions

  • 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 {
113 mainversion = Integer.parseInt(attr.getValue("Plugin-Mainversion"));
114 } catch(NumberFormatException e) {
115 e.printStackTrace();
116 }
117 author = attr.getValue("Author");
118
119 String classPath = attr.getValue(Attributes.Name.CLASS_PATH);
120 if (classPath != null) {
121 for (String entry : classPath.split(" ")) {
122 File entryFile;
123 if (new File(entry).isAbsolute())
124 entryFile = new File(entry);
125 else
126 entryFile = new File(file.getParent(), entry);
127
128 libraries.add(fileToURL(entryFile));
129 }
130 }
131 for (Object o : attr.keySet())
132 this.attr.put(o.toString(), attr.getValue(o.toString()));
133 }
134
135 public String getLinkDescription()
136 {
137 String d = description == null ? tr("no description available") : description;
138 if(link != null)
139 d += " <A HREF=\""+link+"\">"+tr("More details")+"</A>";
140 return d;
141 }
142
143 /**
144 * Load and instantiate the plugin
145 */
146 public PluginProxy load(Class<?> klass) {
147 try {
148 currentPluginInitialization = this;
149 return new PluginProxy(klass.newInstance(), this);
150 } catch (Exception e) {
151 throw new PluginException(null, name, e);
152 }
153 }
154
155 /**
156 * Load the class of the plugin
157 */
158 public Class<?> loadClass(ClassLoader classLoader) {
159 if (className == null)
160 return null;
161 try {
162 Class<?> realClass = Class.forName(className, true, classLoader);
163 return realClass;
164 } catch (Exception e) {
165 throw new PluginException(null, name, e);
166 }
167 }
168
169 public static URL fileToURL(File f) {
170 try {
171 return f.toURI().toURL();
172 } catch (MalformedURLException ex) {
173 return null;
174 }
175 }
176
177 /**
178 * Try to find a plugin after some criterias. Extract the plugin-information
179 * from the plugin and return it. The plugin is searched in the following way:
180 *
181 *<li>first look after an MANIFEST.MF in the package org.openstreetmap.josm.plugins.<plugin name>
182 * (After removing all fancy characters from the plugin name).
183 * If found, the plugin is loaded using the bootstrap classloader.
184 *<li>If not found, look for a jar file in the user specific plugin directory
185 * (~/.josm/plugins/<plugin name>.jar)
186 *<li>If not found and the environment variable JOSM_RESSOURCES + "/plugins/" exist, look there.
187 *<li>Try for the java property josm.ressources + "/plugins/" (set via java -Djosm.plugins.path=...)
188 *<li>If the environment variable ALLUSERSPROFILE and APPDATA exist, look in
189 * ALLUSERSPROFILE/<the last stuff from APPDATA>/JOSM/plugins.
190 * (*sic* There is no easy way under Windows to get the All User's application
191 * directory)
192 *<li>Finally, look in some typical unix paths:<ul>
193 * <li>/usr/local/share/josm/plugins/
194 * <li>/usr/local/lib/josm/plugins/
195 * <li>/usr/share/josm/plugins/
196 * <li>/usr/lib/josm/plugins/
197 *
198 * If a plugin class or jar file is found earlier in the list but seem not to
199 * be working, an PluginException is thrown rather than continuing the search.
200 * This is so JOSM can detect broken user-provided plugins and do not go silently
201 * ignore them.
202 *
203 * The plugin is not initialized. If the plugin is a .jar file, it is not loaded
204 * (only the manifest is extracted). In the classloader-case, the class is
205 * bootstraped (e.g. static {} - declarations will run. However, nothing else is done.
206 *
207 * @param pluginName The name of the plugin (in all lowercase). E.g. "lang-de"
208 * @return Information about the plugin or <code>null</code>, if the plugin
209 * was nowhere to be found.
210 * @throws PluginException In case of broken plugins.
211 */
212 public static PluginInformation findPlugin(String pluginName) throws PluginException {
213 String name = pluginName;
214 name = name.replaceAll("[-. ]", "");
215 InputStream manifestStream = PluginInformation.class.getResourceAsStream("/org/openstreetmap/josm/plugins/"+name+"/MANIFEST.MF");
216 if (manifestStream != null)
217 return new PluginInformation(manifestStream, pluginName);
218
219 Collection<String> locations = getPluginLocations();
220
221 for (String s : locations) {
222 File pluginFile = new File(s, pluginName + ".jar");
223 if (pluginFile.exists()) {
224 PluginInformation info = new PluginInformation(pluginFile);
225 return info;
226 }
227 }
228 return null;
229 }
230
231 public static Collection<String> getPluginLocations() {
232 Collection<String> locations = Main.pref.getAllPossiblePreferenceDirs();
233 Collection<String> all = new ArrayList<String>(locations.size());
234 for (String s : locations)
235 all.add(s+"plugins");
236 return all;
237 }
238}
239
Note: See TracBrowser for help on using the repository browser.