/*
* Scriptographer
*
* This file is part of Scriptographer, a Scripting Plugin for Adobe Illustrator
* http://scriptographer.org/
*
* Copyright (c) 2002-2010, Juerg Lehni
* http://scratchdisk.com/
*
* All rights reserved. See LICENSE file for details.
*
* File created on 05.01.2005.
*/
package com.scriptographer.loader;
import java.net.URLClassLoader;
import java.net.URL;
import java.net.MalformedURLException;
import java.lang.reflect.Method;
import java.io.*;
/**
* @author lehni
*/
public class Loader {
static URLClassLoader loader = null;
static String pluginPath;
public static void init(String path) throws MalformedURLException {
pluginPath = path;
File javaDir = new File(new File(pluginPath, "Core"), "Java");
// Filter out all the files in lib that are not jar or zip files and
// create a URL array of it:
File libDir = new File(javaDir, "lib");
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".jar") || name.endsWith(".zip");
}
};
File[] libs = libDir.listFiles(filter);
// Add two more, for the classes and rhino directories:
URL[] urls = new URL[libs.length + 2];
// And classes and rhino first, libraries after, to get the
// priorities right:
urls[0] = new File(javaDir, "classes").toURI().toURL();
// Rhino is usually loaded from lib, but during development
// it can also be live compiled into the rhino folder, which
// makes debugging easier:
urls[1] = new File(javaDir, "rhino").toURI().toURL();
// Now add the urls from above
for (int i = 0; i < libs.length; i++)
urls[i + 2] = libs[i].toURI().toURL();
loader = new URLClassLoader(urls);
// Set the new class loader as context class loader
Thread.currentThread().setContextClassLoader(loader);
}
/**
* Reloads the Scriptographer Engine from a new class loader
*
* @return a string, representing any errors that happened during reload, or
* null if all went well
*/
public static String reload() {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
try {
// First call destroy in the currently loaded ScriptographerEngine class:
Class<?> cls = loader.loadClass("com.scriptographer.ScriptographerEngine");
Method destroy = cls.getDeclaredMethod("destroy", new Class[] {});
destroy.invoke(null, new Object[] {});
} catch(Exception e) {
e.printStackTrace(writer);
}
try {
// Now (re)load all:
init(pluginPath);
} catch (Exception e) {
e.printStackTrace(writer);
}
String errors = stringWriter.toString();
return errors.length() == 0 ? null : errors;
}
/**
* To be called from the native environment. This replaces the static
* JNI_LoadClass, that always depends on the initial loader. This one
* allows reloading classes from a reloaded classpath for reflection.
*
* @param name in the slash-format (e.g. "java/lang/Object")
* @return the loaded class
* @throws ClassNotFoundException
*/
protected static Class loadClass(String name) throws ClassNotFoundException {
return loader.loadClass(name.replace('/', '.'));
}
}