diff --git a/app/src/processing/app/contrib/ModeContribution.java b/app/src/processing/app/contrib/ModeContribution.java index a65458b37..53385b118 100644 --- a/app/src/processing/app/contrib/ModeContribution.java +++ b/app/src/processing/app/contrib/ModeContribution.java @@ -24,11 +24,17 @@ package processing.app.contrib; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; +import java.net.URL; import java.net.URLClassLoader; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import processing.app.Base; import processing.app.Mode; +import processing.app.contrib.LocalContribution.IgnorableException; public class ModeContribution extends LocalContribution { @@ -77,8 +83,7 @@ public class ModeContribution extends LocalContribution { private ModeContribution(Base base, File folder, String className) throws Exception { super(folder); - - className = initLoader(className); + className = initLoader(base, className); if (className != null) { Class modeClass = loader.loadClass(className); Base.log("Got mode class " + modeClass); @@ -175,6 +180,88 @@ public class ModeContribution extends LocalContribution { ModeContribution other = (ModeContribution) o; return loader.equals(other.loader) && mode.equals(other.getMode()); } + + public String initLoader(Base base, String className) throws Exception { + + File modeDirectory = new File(folder, getTypeName()); + if (modeDirectory.exists()) { + Base.log("checking mode folder regarding " + className); + // If no class name specified, search the main .jar for the + // full name package and mode name. + if (className == null) { + String shortName = folder.getName(); + File mainJar = new File(modeDirectory, shortName + ".jar"); + if (mainJar.exists()) { + className = findClassInZipFile(shortName, mainJar); + } else { + throw new IgnorableException(mainJar.getAbsolutePath() + " does not exist."); + } + + if (className == null) { + throw new IgnorableException("Could not find " + shortName + + " class inside " + mainJar.getAbsolutePath()); + } + } + + ArrayList extraUrls = new ArrayList<>(); + if (imports != null && imports.size() > 0) { + // if the mode has any dependencies (defined as imports in mode.properties), + // add the dependencies to the classloader + + HashMap installedModes = new HashMap<>(); + for(Mode m: base.getModeList()){ + // Base.log("Mode contrib: " + m.getClass().getName() + " : "+ m.getFolder()); + installedModes.put(m.getClass().getName(), m); + } + + for(String modeImport: imports){ + if (installedModes.containsKey(modeImport)) { + Base.log("Found mode dependency " + modeImport); + File[] archives = Base.listJarFiles(new File(installedModes.get(modeImport). + getFolder().getAbsolutePath() + File.separator + "mode")); + if (archives != null && archives.length > 0) { + for (int i = 0; i < archives.length; i++) { + // Base.log("Adding jar dependency: " + archives[i].getAbsolutePath()); + extraUrls.add(archives[i].toURI().toURL()); + } + } + } else { + throw new IgnorableException("Dependency mode "+ modeImport + " could not be" + + " found. Can't load " + className); + } + } + } + + // Add .jar and .zip files from the "mode" folder into the classpath + File[] archives = Base.listJarFiles(modeDirectory); + if (archives != null && archives.length > 0) { + int arrLen = archives.length + extraUrls.size(); + URL[] urlList = new URL[arrLen]; + + int j = 0; + for (; j < extraUrls.size(); j++) { + //Base.log("Found archive " + archives[j] + " for " + getName()); + urlList[j] = extraUrls.get(j); + } + + for (int k = 0; k < archives.length; k++,j++) { + Base.log("Found archive " + archives[k] + " for " + getName()); + urlList[j] = archives[k].toURI().toURL(); + } + + loader = new URLClassLoader(urlList); + Base.log("loading above JARs with loader " + loader); +// System.out.println("listing classes for loader " + loader); +// listClasses(loader); + } + } + + // If no archives were found, just use the regular ClassLoader + if (loader == null) { + loader = Thread.currentThread().getContextClassLoader(); + } + return className; + } // static protected List discover(File folder) {