001: package org.objectweb.salome_tmf.plugins;
002:
003: import java.io.File;
004: import java.io.FileOutputStream;
005: import java.io.InputStream;
006: import java.net.URL;
007: import java.net.URLClassLoader;
008: import java.net.URLConnection;
009: import java.util.Hashtable;
010: import java.util.jar.JarFile;
011: import java.util.jar.JarInputStream;
012: import java.util.jar.Manifest;
013:
014: import org.objectweb.salome_tmf.api.Util;
015:
016: public class PluginClassLoader extends URLClassLoader {
017:
018: String tmpDir = System.getProperties()
019: .getProperty("java.io.tmpdir");
020: String fs = System.getProperties().getProperty("file.separator");
021: String salome_cache = "salome_cache";
022:
023: boolean useCacheFile = true;
024: boolean cacheAll = false;
025: Hashtable loadedJar;
026:
027: ClassLoader pClassLoader;
028:
029: /*PluginClassLoader(ClassLoader parent) {
030: super(new URL[0], parent);
031: init();
032: pClassLoader = parent;
033: }*/
034:
035: PluginClassLoader(ClassLoader parent) {
036: super (new URL[] {}, parent);
037: //ClassLoader.getSystemClassLoader()
038: init();
039: pClassLoader = parent;
040: loadedJar = new Hashtable();
041: }
042:
043: void init() {
044: if (useCacheFile) {
045: try {
046: cacheAll = create_cache_dir();
047: } catch (Exception e) {
048: useCacheFile = false;
049: }
050: }
051:
052: }
053:
054: public void AddJar(URL jar) {
055: File f = new File(jar.getFile());
056: String jarName = f.getName();
057: if (loadedJar.get(jarName) != null) {
058: return;
059: }
060: if (useCacheFile) {
061: jar = getCachedFile(jar);
062: }
063:
064: try {
065: Class pclC = pClassLoader.getClass();
066: pclC.getMethod("addLocalJar", new Class[] { URL.class })
067: .invoke(pClassLoader, new Object[] { jar });
068: Util.log("[PluginClassLoader->addJar] load" + jar
069: + ", with classloader " + pClassLoader);
070: loadedJar.put(jarName, jar);
071: } catch (Exception e) {
072: try {
073: addURL(jar);
074: //add(jar);
075: loadedJar.put(jarName, jar);
076: } catch (Exception e1) {
077: addURL(jar);
078: }
079:
080: }
081: }
082:
083: /***************************** CORE **************************************/
084: /*
085: Hashtable urlsIn = new Hashtable();
086: private boolean debug = false;
087:
088:
089: private boolean alreadyIn(String jarurl){
090: int slash = jarurl.lastIndexOf('/');// are urls always composed of / ?
091: String key = jarurl.substring(slash+1);
092: return (urlsIn.containsKey(key));
093: }
094:
095:
096: private void registerUrl(URL url){
097: int slash = url.toString().lastIndexOf('/');// are urls always composed of / ?
098: String key = url.toString().substring(slash+1);
099: urlsIn.put(key,url);
100: }
101:
102:
103: public void add(URL url) {
104: if (!alreadyIn(url.toString())){
105: super.addURL(url);
106: registerUrl(url);
107: }
108: }
109:
110:
111: public void add(URL[] urls) {
112: for (int i=0;i<urls.length;i++){
113: if (!alreadyIn(urls[i].toString())){
114: super.addURL(urls[i]);
115: registerUrl(urls[i]);
116: }
117: }
118: }
119:
120:
121: public void add(String jarurlname) {
122: URL jarurl = null;
123:
124: try {
125: if ( (jarurlname.startsWith("file:")) ||
126: (jarurlname.startsWith("http:")) ||
127: (jarurlname.startsWith("ftp:"))
128: )
129: jarurl = new URL(jarurlname);
130: else
131: jarurl = new URL("file:"+jarurlname);
132: } catch (MalformedURLException eurl) {
133: System.out.println("JarClassLoader Malformed URL "+eurl);
134: }
135: if (jarurl != null){
136: if (!alreadyIn(jarurl.toString())){
137: super.addURL(jarurl);
138: registerUrl(jarurl);
139: }
140: }
141: }
142:
143: public Class loadClassFromJar(String name) {
144: Class c = null;
145: c = getLoadedClass(name);
146: if (c!=null)
147: return c;
148: try {
149: c = findClass(name);
150: } catch (ClassNotFoundException e) {
151: if (debug) System.err.println("JarClassLoader loadClassFromJar Exception "+e);
152: } catch (NullPointerException ne){
153: if (debug) System.err.println("JarClassLoader loadClassFromJar Null Exception "+ne);
154: }
155: return c;
156: }
157:
158:
159: public Class loadMainClassFromJar(URL jarurl) {
160: // find main class name in manifest
161:
162: // add and register url if not already in
163: //resetClassLoader();
164: add(jarurl);
165:
166: boolean empty = true;
167: ManifestWrapper mf = null;
168: byte buffer[] = new byte[1024];
169: ZipInputStream zis = null;
170: try {
171:
172: InputStream inf = jarurl.openStream();
173: zis = new ZipInputStream(inf);
174: ZipEntry ent = null;
175:
176: while ((ent = zis.getNextEntry()) != null) {
177: empty = false;
178:
179: String name = ent.getName();
180: String type = new String();
181:
182:
183: ByteArrayOutputStream baos = new ByteArrayOutputStream();
184:
185:
186:
187: for (;;) {
188: int len = zis.read(buffer);
189: if (len < 0) {
190: break;
191: }
192: baos.write(buffer, 0, len);
193: }
194:
195: byte[] buf = baos.toByteArray();
196: int size = buf.length;
197:
198: if (ManifestWrapper.isManifestName(name)) {
199: type = "manifest/manifest";
200: }
201:
202: if (type.equals("manifest/manifest")) {
203: mf = new ManifestWrapper(buf);
204: }
205: }
206:
207: } catch (IOException ex) {
208: System.out.println("IOException loading archive: " + ex);
209: } catch (Throwable th) {
210: System.out.println("Caught " + th + " in loadit()");
211: } finally {
212: if (zis != null) {
213: try {
214: zis.close();
215: } catch (Exception ex) {
216: // ignore
217: }
218: }
219: }
220:
221: // Unfortunately ZipInputStream doesn't throw an exception if you hand
222: // it a non-Zip file. Our only way of spotting an invalid Jar file
223: // is if there no ZIP entries.
224: if (empty) {
225: System.out.println("jar file empty");
226:
227: return null;
228: }
229:
230: // find class name
231:
232:
233: if (mf==null)
234: return null;
235: String res = null;
236: // Vector manifestHeaders = mf.;
237: for (Enumeration e = mf.entries() ; e.hasMoreElements() ;) {
238: MessageHeader mh = (MessageHeader)e.nextElement();
239:
240:
241: res = mh.findValue("Main-Class");
242: if (res==null) res = mh.findValue("Name");
243: if (res!=null) break;
244: }
245:
246:
247: if (res==null)
248: return null;
249:
250: String name = res;
251: Class c = null;
252:
253: c = getLoadedClass(name);
254: if (c!=null)
255: return c;
256:
257: try {
258: c = findClass(name);
259: } catch (ClassNotFoundException e) {
260: if (debug) System.err.println("JarClassLoader loadClassFromJar Exception "+e);
261: } catch (NullPointerException ne){
262: if (debug) System.err.println("JarClassLoader loadClassFromJar Null Exception "+ne);
263: } catch (LinkageError le){
264: if (debug) System.err.println("JarClassLoader loadClassFromJar Linkage Error "+le);
265: }
266: return c;
267: }
268:
269:
270:
271: public Class getLoadedClass(String classname){
272: //return super.findLoadedClass(classname);
273: Class c = null;
274: try {
275: c = super.loadClass(classname);
276: } catch (ClassNotFoundException e){
277: if (debug) System.err.println("JarClassLoader getLoadedClass Exception "+e);
278: }
279: return c;
280: }
281:
282: public void resolvesClass(Class theClass){
283: try {
284: super.resolveClass(theClass);
285: } catch (Exception e){
286: if (debug) System.err.println("JarClassLoader resolvesClass Exception "+e);
287: }
288: }
289: */
290:
291: /*************************** CACHE ************************************/
292:
293: URL getCachedFile(URL jarURL) {
294: URL fileURL = jarURL;
295: if (jarURL.getProtocol().equals("file")) {
296: return jarURL;
297: }
298: //System.out.println("[PluginClassLoader->getCachedFile] for " +jarURL);
299: try {
300: File f = new File(jarURL.getFile());
301: String jarName = f.getName();
302:
303: //String urlRemote = "jar:" + jarURL.toString() + "!/";
304: File fileLocal = new File(tmpDir + fs + salome_cache + fs
305: + jarName);
306: if (needUpdate(jarURL, fileLocal, jarName)) {
307: fileURL = installFile(jarURL, jarName).toURL();
308:
309: } else {
310: Util
311: .log("[PluginClassLoader->getCachedFile] Use cache for "
312: + jarURL);
313: fileURL = fileLocal.toURL();
314: }
315: } catch (Exception e) {
316:
317: }
318: //System.out.println("[PluginClassLoader->getCachedFile] set url to use " +fileURL);
319: return fileURL;
320: }
321:
322: boolean needUpdate(URL pJarURL, File localFile, String name) {
323: boolean ret = false;
324: if (!localFile.exists()) {
325: // System.out.println("[PluginClassLoader->needUpdate] Need to Update (not exist) : " + localFile);
326: return true;
327: }
328: try {
329: JarInputStream jarInput = new JarInputStream(pJarURL
330: .openStream());
331: Manifest remoteManifest = jarInput.getManifest();
332:
333: JarFile localeJar = new JarFile(localFile);
334: Manifest localManifest = localeJar.getManifest();
335:
336: if (!localManifest.equals(remoteManifest)) {
337: //System.out.println("[PluginClassLoader->needUpdate] Need to Update : " + localFile);
338: ret = true;
339: } else {
340: // ZipEntry getEntry(String name) META-INF/SALOME_T.SF
341: if (localManifest.getEntries().size() == 0) {
342: // System.out.println("[PluginClassLoader->needUpdate] Need to Update " + localFile + " No attribute in manifest")
343: ret = true;
344: }
345: }
346:
347: //System.out.println("JarManifest = " + manifest + " for " + jar);
348: } catch (Exception e) {
349: e.printStackTrace();
350: ret = true;
351: }
352: return ret;
353: }
354:
355: boolean create_cache_dir() throws Exception {
356: boolean ret = false;
357: File file = new File(tmpDir + fs + salome_cache);
358: if (!file.exists()) {
359: file.mkdirs();
360: ret = true;
361: }
362: return ret;
363: }
364:
365: File installFile(URL pUrl, String name) throws Exception {
366: File file = null;
367: try {
368: URLConnection urlconn = pUrl.openConnection();
369: InputStream is = urlconn.getInputStream();
370: file = new File(tmpDir + fs + salome_cache + fs + name);
371: writeStream(is, file);
372:
373: } catch (Exception e) {
374: e.printStackTrace();
375: return null;
376: }
377: return file;
378: }
379:
380: void writeStream(InputStream is, File f) throws Exception {
381: byte[] buf = new byte[102400];
382: f.createNewFile();
383: FileOutputStream fos = new FileOutputStream(f);
384: int len = 0;
385: while ((len = is.read(buf)) != -1) {
386: fos.write(buf, 0, len);
387: }
388: fos.close();
389: is.close();
390: }
391:
392: }
|