mirror of
https://github.com/processing/processing4.git
synced 2026-02-03 13:49:18 +01:00
Moves to Java11 and OpenJDK via AdoptOpenJDK within the processing4 train.
Moves to Java11 and OpenJDK via AdoptOpenJDK within the processing4 train using a squash of sampottinger processing fork's java11 branch. **Primary required changes:** Some changes directly support OpenJFX / OpenJDK 11: - Response to image loading changes caused by [JEP 320](https://openjdk.java.net/jeps/320) - Use of jmodules as necessitated by [JEP 261](https://openjdk.java.net/jeps/261) - Reponse to largely changed file paths caused by [JEP 220](https://openjdk.java.net/jeps/220). - Modifications in build system related to AdoptOpenJDK and Java 11 which have a different naming structure for downloads. - Allowing use of non-Oracle Java within internal Processing checks. **Secondary required changes:** There were some secondary required changes that impacted the usability of Processing after having moved to OpenJFX / OpenJDK 11: - Removal of com.apple.eawt calls related to [JEP 272](http://openjdk.java.net/jeps/272) - Response to HiDPI support on Windows and Linux in [JEP 263](https://openjdk.java.net/jeps/263) - Removal of `java.ext.dirs`. Would be forced by [JEP 220](http://openjdk.java.net/jeps/220). - Due to bugs on Windows, updated the JNA jars. - Changes in downloader build tasks to support AdoptOpenJDK and OpenJFX. - Updated org.eclipse.* / equinox jars. - Some optimization around size of distribution. - Update of AppBundler. - Some changes in formulation of classpath and modifications in PreprocessingService given [JEP 261](https://openjdk.java.net/jeps/261). **Incidental changes:** This was (ahem) a bit of a larger PR with the above modifications. So, I wanted to introduce automated tests when possible and convenient along with a few changes for platform sustainability in order to support development: - Addition of cross-building capability (!) made possible by AdoptOpenJDK. - Addition of mockito for testing. - Upgrade of junit. - Addition of ant-contrib. - Standardized nomenclature around JRE / JDK in `build/build.xml` - Deduplication of code in `jre/build.xml`. - Addition of JavaDoc in a few places. - Some refactoring of PImage / Shape to support increased testing and readability in image manipulation code.
This commit is contained in:
@@ -54,6 +54,8 @@ import processing.core.PConstants;
|
||||
import processing.data.StringList;
|
||||
import processing.data.XML;
|
||||
import processing.mode.java.pdex.SourceUtils;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimeConst;
|
||||
import processing.mode.java.pdex.util.runtime.strategy.JavaFxRuntimePathFactory;
|
||||
import processing.mode.java.preproc.PdePreprocessor;
|
||||
import processing.mode.java.preproc.PreprocessorResult;
|
||||
import processing.mode.java.preproc.SurfaceInfo;
|
||||
@@ -785,10 +787,10 @@ public class JavaBuild {
|
||||
if (exportPlatform == PConstants.MACOSX) {
|
||||
dotAppFolder = new File(destFolder, sketch.getName() + ".app");
|
||||
|
||||
File contentsOrig = new File(Platform.getJavaHome(), "../../../../..");
|
||||
File contentsOrig = new File(Platform.getJavaHome(), "../../../..");
|
||||
|
||||
if (embedJava) {
|
||||
File jdkFolder = new File(Platform.getJavaHome(), "../../..");
|
||||
File jdkFolder = new File(Platform.getJavaHome(), "../..");
|
||||
String jdkFolderName = jdkFolder.getCanonicalFile().getName();
|
||||
jvmRuntime = "<key>JVMRuntime</key>\n <string>" + jdkFolderName + "</string>";
|
||||
jdkPath = new File(dotAppFolder, "Contents/PlugIns/" + jdkFolderName).getAbsolutePath();
|
||||
@@ -920,7 +922,6 @@ public class JavaBuild {
|
||||
for (Library library : importedLibraries) {
|
||||
// add each item from the library folder / export list to the output
|
||||
for (File exportFile : library.getApplicationExports(exportPlatform, exportVariant)) {
|
||||
// System.out.println("export: " + exportFile);
|
||||
String exportName = exportFile.getName();
|
||||
if (!exportFile.exists()) {
|
||||
System.err.println(exportFile.getName() +
|
||||
@@ -943,7 +944,6 @@ public class JavaBuild {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// create platform-specific CLASSPATH based on included jars
|
||||
|
||||
String exportClassPath = null;
|
||||
@@ -972,23 +972,14 @@ public class JavaBuild {
|
||||
}
|
||||
// https://github.com/processing/processing/issues/2239
|
||||
runOptions.append("-Djna.nosys=true");
|
||||
// https://github.com/processing/processing/issues/4608
|
||||
if (embedJava) {
|
||||
// if people don't embed Java, it might be a mess, but what can we do?
|
||||
if (exportPlatform == PConstants.MACOSX) {
|
||||
runOptions.append("-Djava.ext.dirs=$APP_ROOT/Contents/PlugIns/jdk" +
|
||||
PApplet.javaVersionName +
|
||||
".jdk/Contents/Home/jre/lib/ext");
|
||||
} else if (exportPlatform == PConstants.WINDOWS) {
|
||||
runOptions.append("-Djava.ext.dirs=\"%EXEDIR%\\java\\lib\\ext\"");
|
||||
} else if (exportPlatform == PConstants.LINUX) {
|
||||
runOptions.append("-Djava.ext.dirs=\"$APPDIR/java/lib/ext\"");
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/processing/processing/issues/2559
|
||||
if (exportPlatform == PConstants.WINDOWS) {
|
||||
runOptions.append("-Djava.library.path=\"%EXEDIR%\\lib\"");
|
||||
|
||||
// No scaling of swing (see #5753) on zoomed displays until some issues regarding JEP 263
|
||||
// with rendering artifacts are sorted out.
|
||||
runOptions.append("-Dsun.java2d.uiScale=1");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ class ErrorChecker {
|
||||
|
||||
if (problems.isEmpty()) {
|
||||
AtomicReference<ClassPath> searchClassPath = new AtomicReference<>(null);
|
||||
|
||||
List<Problem> cuProblems = Arrays.stream(iproblems)
|
||||
// Filter Warnings if they are not enabled
|
||||
.filter(iproblem -> !(iproblem.isWarning() && !JavaMode.warningsEnabled))
|
||||
@@ -312,6 +313,7 @@ class ErrorChecker {
|
||||
// replace inner class separators with dots
|
||||
.map(res -> res.replace('$', '.'))
|
||||
// sort, prioritize clases from java. package
|
||||
.map(res -> res.startsWith("classes.") ? res.substring(8) : res)
|
||||
.sorted((o1, o2) -> {
|
||||
// put java.* first, should be prioritized more
|
||||
boolean o1StartsWithJava = o1.startsWith("java");
|
||||
@@ -324,4 +326,4 @@ class ErrorChecker {
|
||||
})
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-15 The Processing Foundation
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
@@ -20,20 +20,8 @@ along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
|
||||
package processing.mode.java.pdex;
|
||||
|
||||
import com.google.classpath.ClassPathFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -54,17 +42,16 @@ import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
|
||||
import processing.app.Library;
|
||||
import processing.app.Messages;
|
||||
import processing.app.Sketch;
|
||||
import processing.app.SketchCode;
|
||||
import processing.app.SketchException;
|
||||
import processing.app.Util;
|
||||
import processing.data.IntList;
|
||||
import processing.data.StringList;
|
||||
import processing.mode.java.JavaEditor;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.TextTransform.OffsetMapper;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathBuilder;
|
||||
import processing.mode.java.preproc.PdePreprocessor;
|
||||
import processing.mode.java.preproc.PdePreprocessor.Mode;
|
||||
|
||||
@@ -78,8 +65,6 @@ public class PreprocessingService {
|
||||
|
||||
protected final ASTParser parser = ASTParser.newParser(AST.JLS8);
|
||||
|
||||
private final ClassPathFactory classPathFactory = new ClassPathFactory();
|
||||
|
||||
private final Thread preprocessingThread;
|
||||
private final BlockingQueue<Boolean> requestQueue = new ArrayBlockingQueue<>(1);
|
||||
|
||||
@@ -326,22 +311,15 @@ public class PreprocessingService {
|
||||
toParsable.addAll(SourceUtils.wrapSketch(sketchMode, className, workBuffer.length()));
|
||||
|
||||
{ // Refresh sketch classloader and classpath if imports changed
|
||||
if (javaRuntimeClassPath == null) {
|
||||
javaRuntimeClassPath = buildJavaRuntimeClassPath();
|
||||
sketchModeClassPath = buildModeClassPath(javaMode, false);
|
||||
searchModeClassPath = buildModeClassPath(javaMode, true);
|
||||
}
|
||||
|
||||
if (reloadLibraries) {
|
||||
coreLibraryClassPath = buildCoreLibraryClassPath(javaMode);
|
||||
runtimePathBuilder.markLibrariesChanged();
|
||||
}
|
||||
|
||||
boolean rebuildLibraryClassPath = reloadLibraries ||
|
||||
checkIfImportsChanged(programImports, prevResult.programImports);
|
||||
|
||||
if (rebuildLibraryClassPath) {
|
||||
sketchLibraryClassPath = buildSketchLibraryClassPath(javaMode, programImports);
|
||||
searchLibraryClassPath = buildSearchLibraryClassPath(javaMode);
|
||||
runtimePathBuilder.markLibraryImportsChanged();
|
||||
}
|
||||
|
||||
boolean rebuildClassPath = reloadCodeFolder || rebuildLibraryClassPath ||
|
||||
@@ -349,45 +327,11 @@ public class PreprocessingService {
|
||||
prevResult.classPathArray == null || prevResult.searchClassPathArray == null;
|
||||
|
||||
if (reloadCodeFolder) {
|
||||
codeFolderClassPath = buildCodeFolderClassPath(sketch);
|
||||
runtimePathBuilder.markCodeFolderChanged();
|
||||
}
|
||||
|
||||
if (rebuildClassPath) {
|
||||
{ // Sketch class path
|
||||
List<String> sketchClassPath = new ArrayList<>();
|
||||
sketchClassPath.addAll(javaRuntimeClassPath);
|
||||
sketchClassPath.addAll(sketchModeClassPath);
|
||||
sketchClassPath.addAll(sketchLibraryClassPath);
|
||||
sketchClassPath.addAll(coreLibraryClassPath);
|
||||
sketchClassPath.addAll(codeFolderClassPath);
|
||||
|
||||
String[] classPathArray = sketchClassPath.stream().toArray(String[]::new);
|
||||
URL[] urlArray = Arrays.stream(classPathArray)
|
||||
.map(path -> {
|
||||
try {
|
||||
return Paths.get(path).toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
Messages.loge("malformed URL when preparing sketch classloader", e);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(url -> url != null)
|
||||
.toArray(URL[]::new);
|
||||
result.classLoader = new URLClassLoader(urlArray, null);
|
||||
result.classPath = classPathFactory.createFromPaths(classPathArray);
|
||||
result.classPathArray = classPathArray;
|
||||
}
|
||||
|
||||
{ // Search class path
|
||||
List<String> searchClassPath = new ArrayList<>();
|
||||
searchClassPath.addAll(javaRuntimeClassPath);
|
||||
searchClassPath.addAll(searchModeClassPath);
|
||||
searchClassPath.addAll(searchLibraryClassPath);
|
||||
searchClassPath.addAll(coreLibraryClassPath);
|
||||
searchClassPath.addAll(codeFolderClassPath);
|
||||
|
||||
result.searchClassPathArray = searchClassPath.stream().toArray(String[]::new);
|
||||
}
|
||||
runtimePathBuilder.prepareClassPath(result, javaMode);
|
||||
} else {
|
||||
result.classLoader = prevResult.classLoader;
|
||||
result.classPath = prevResult.classPath;
|
||||
@@ -493,141 +437,7 @@ public class PreprocessingService {
|
||||
|
||||
/// CLASSPATHS ---------------------------------------------------------------
|
||||
|
||||
|
||||
private List<String> javaRuntimeClassPath;
|
||||
|
||||
private List<String> sketchModeClassPath;
|
||||
private List<String> searchModeClassPath;
|
||||
|
||||
private List<String> coreLibraryClassPath;
|
||||
|
||||
private List<String> codeFolderClassPath;
|
||||
|
||||
private List<String> sketchLibraryClassPath;
|
||||
private List<String> searchLibraryClassPath;
|
||||
|
||||
|
||||
private static List<String> buildCodeFolderClassPath(Sketch sketch) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
// Code folder
|
||||
if (sketch.hasCodeFolder()) {
|
||||
File codeFolder = sketch.getCodeFolder();
|
||||
String codeFolderClassPath = Util.contentsToClassPath(codeFolder);
|
||||
classPath.append(codeFolderClassPath);
|
||||
}
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
private static List<String> buildModeClassPath(JavaMode mode, boolean search) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
if (search) {
|
||||
String searchClassPath = mode.getSearchPath();
|
||||
if (searchClassPath != null) {
|
||||
classPath.append(File.pathSeparator).append(searchClassPath);
|
||||
}
|
||||
} else {
|
||||
Library coreLibrary = mode.getCoreLibrary();
|
||||
String coreClassPath = coreLibrary != null ?
|
||||
coreLibrary.getClassPath() : mode.getSearchPath();
|
||||
if (coreClassPath != null) {
|
||||
classPath.append(File.pathSeparator).append(coreClassPath);
|
||||
}
|
||||
}
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
private static List<String> buildCoreLibraryClassPath(JavaMode mode) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
for (Library lib : mode.coreLibraries) {
|
||||
classPath.append(File.pathSeparator).append(lib.getClassPath());
|
||||
}
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
private static List<String> buildSearchLibraryClassPath(JavaMode mode) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
for (Library lib : mode.contribLibraries) {
|
||||
classPath.append(File.pathSeparator).append(lib.getClassPath());
|
||||
}
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
static private List<String> buildSketchLibraryClassPath(JavaMode mode,
|
||||
List<ImportStatement> programImports) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
programImports.stream()
|
||||
.map(ImportStatement::getPackageName)
|
||||
.filter(pckg -> !ignorableImport(pckg))
|
||||
.map(pckg -> {
|
||||
try {
|
||||
return mode.getLibrary(pckg);
|
||||
} catch (SketchException e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(lib -> lib != null)
|
||||
.map(Library::getClassPath)
|
||||
.forEach(cp -> classPath.append(File.pathSeparator).append(cp));
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
static private List<String> buildJavaRuntimeClassPath() {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
{ // Java runtime
|
||||
String rtPath = System.getProperty("java.home") +
|
||||
File.separator + "lib" + File.separator + "rt.jar";
|
||||
if (new File(rtPath).exists()) {
|
||||
classPath.append(File.pathSeparator).append(rtPath);
|
||||
} else {
|
||||
rtPath = System.getProperty("java.home") + File.separator + "jre" +
|
||||
File.separator + "lib" + File.separator + "rt.jar";
|
||||
if (new File(rtPath).exists()) {
|
||||
classPath.append(File.pathSeparator).append(rtPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // JavaFX runtime
|
||||
String jfxrtPath = System.getProperty("java.home") +
|
||||
File.separator + "lib" + File.separator + "ext" + File.separator + "jfxrt.jar";
|
||||
if (new File(jfxrtPath).exists()) {
|
||||
classPath.append(File.pathSeparator).append(jfxrtPath);
|
||||
} else {
|
||||
jfxrtPath = System.getProperty("java.home") + File.separator + "jre" +
|
||||
File.separator + "lib" + File.separator + "ext" + File.separator + "jfxrt.jar";
|
||||
if (new File(jfxrtPath).exists()) {
|
||||
classPath.append(File.pathSeparator).append(jfxrtPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
|
||||
private static List<String> sanitizeClassPath(String classPathString) {
|
||||
// Make sure class path does not contain empty string (home dir)
|
||||
return Arrays.stream(classPathString.split(File.pathSeparator))
|
||||
.filter(p -> p != null && !p.trim().isEmpty())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
private RuntimePathBuilder runtimePathBuilder = new RuntimePathBuilder();
|
||||
|
||||
/// --------------------------------------------------------------------------
|
||||
|
||||
@@ -662,20 +472,13 @@ public class PreprocessingService {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ignore processing packages, java.*.*. etc.
|
||||
*/
|
||||
static private boolean ignorableImport(String packageName) {
|
||||
return (packageName.startsWith("java.") ||
|
||||
packageName.startsWith("javax."));
|
||||
}
|
||||
|
||||
|
||||
static private final Map<String, String> COMPILER_OPTIONS;
|
||||
static {
|
||||
Map<String, String> compilerOptions = new HashMap<>();
|
||||
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, compilerOptions);
|
||||
compilerOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_11);
|
||||
compilerOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_11);
|
||||
compilerOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_11);
|
||||
|
||||
// See http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Fguide%2Fjdt_api_options.htm&anchor=compiler
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2019 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime;
|
||||
|
||||
|
||||
/**
|
||||
* Constants related to runtime component enumeration.
|
||||
*/
|
||||
public class RuntimeConst {
|
||||
|
||||
/**
|
||||
* The modules comprising the Java standard modules.
|
||||
*/
|
||||
public static final String[] STANDARD_MODULES = {
|
||||
"java.base.jmod",
|
||||
"java.compiler.jmod",
|
||||
"java.datatransfer.jmod",
|
||||
"java.desktop.jmod",
|
||||
"java.instrument.jmod",
|
||||
"java.logging.jmod",
|
||||
"java.management.jmod",
|
||||
"java.management.rmi.jmod",
|
||||
"java.naming.jmod",
|
||||
"java.net.http.jmod",
|
||||
"java.prefs.jmod",
|
||||
"java.rmi.jmod",
|
||||
"java.scripting.jmod",
|
||||
"java.se.jmod",
|
||||
"java.security.jgss.jmod",
|
||||
"java.security.sasl.jmod",
|
||||
"java.smartcardio.jmod",
|
||||
"java.sql.jmod",
|
||||
"java.sql.rowset.jmod",
|
||||
"java.transaction.xa.jmod",
|
||||
"java.xml.crypto.jmod",
|
||||
"java.xml.jmod",
|
||||
"jdk.accessibility.jmod",
|
||||
"jdk.aot.jmod",
|
||||
"jdk.attach.jmod",
|
||||
"jdk.charsets.jmod",
|
||||
"jdk.compiler.jmod",
|
||||
"jdk.crypto.cryptoki.jmod",
|
||||
"jdk.crypto.ec.jmod",
|
||||
"jdk.dynalink.jmod",
|
||||
"jdk.editpad.jmod",
|
||||
"jdk.hotspot.agent.jmod",
|
||||
"jdk.httpserver.jmod",
|
||||
"jdk.internal.ed.jmod",
|
||||
"jdk.internal.jvmstat.jmod",
|
||||
"jdk.internal.le.jmod",
|
||||
"jdk.internal.opt.jmod",
|
||||
"jdk.internal.vm.ci.jmod",
|
||||
"jdk.internal.vm.compiler.jmod",
|
||||
"jdk.internal.vm.compiler.management.jmod",
|
||||
"jdk.jartool.jmod",
|
||||
"jdk.javadoc.jmod",
|
||||
"jdk.jcmd.jmod",
|
||||
"jdk.jconsole.jmod",
|
||||
"jdk.jdeps.jmod",
|
||||
"jdk.jdi.jmod",
|
||||
"jdk.jdwp.agent.jmod",
|
||||
"jdk.jfr.jmod",
|
||||
"jdk.jlink.jmod",
|
||||
"jdk.jshell.jmod",
|
||||
"jdk.jsobject.jmod",
|
||||
"jdk.jstatd.jmod",
|
||||
"jdk.localedata.jmod",
|
||||
"jdk.management.agent.jmod",
|
||||
"jdk.management.jfr.jmod",
|
||||
"jdk.management.jmod",
|
||||
"jdk.naming.dns.jmod",
|
||||
"jdk.naming.rmi.jmod",
|
||||
"jdk.net.jmod",
|
||||
"jdk.pack.jmod",
|
||||
"jdk.rmic.jmod",
|
||||
"jdk.scripting.nashorn.jmod",
|
||||
"jdk.scripting.nashorn.shell.jmod",
|
||||
"jdk.sctp.jmod",
|
||||
"jdk.security.auth.jmod",
|
||||
"jdk.security.jgss.jmod",
|
||||
"jdk.unsupported.desktop.jmod",
|
||||
"jdk.unsupported.jmod",
|
||||
"jdk.xml.dom.jmod",
|
||||
"jdk.zipfs.jmod"
|
||||
};
|
||||
|
||||
/**
|
||||
* The jars required for OpenJFX.
|
||||
*/
|
||||
public static final String[] JAVA_FX_JARS = {
|
||||
"javafx-swt.jar",
|
||||
"javafx.base.jar",
|
||||
"javafx.controls.jar",
|
||||
"javafx.fxml.jar",
|
||||
"javafx.graphics.jar",
|
||||
"javafx.media.jar",
|
||||
"javafx.swing.jar",
|
||||
"javafx.web.jar"
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime;
|
||||
|
||||
import com.google.classpath.ClassPathFactory;
|
||||
import processing.app.Messages;
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.PreprocessedSketch;
|
||||
import processing.mode.java.pdex.util.runtime.strategy.*;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* Builder which generates runtime paths using a series of caches.
|
||||
*
|
||||
* <p>
|
||||
* Builder which helps generate classpath (and module path) entries for sketches using stateful
|
||||
* and individually invalidate-able caches to prevent duplicate work.
|
||||
* </p>
|
||||
*/
|
||||
public class RuntimePathBuilder {
|
||||
private final List<CachedRuntimePathFactory> libraryDependentCaches;
|
||||
private final List<CachedRuntimePathFactory> libraryImportsDependentCaches;
|
||||
private final List<CachedRuntimePathFactory> codeFolderDependentCaches;
|
||||
|
||||
private final List<RuntimePathFactoryStrategy> sketchClassPathStrategies;
|
||||
private final List<RuntimePathFactoryStrategy> searchClassPathStrategies;
|
||||
|
||||
private final ClassPathFactory classPathFactory;
|
||||
|
||||
/**
|
||||
* Create a new runtime path builder with empty caches.
|
||||
*/
|
||||
public RuntimePathBuilder() {
|
||||
classPathFactory = new ClassPathFactory();
|
||||
|
||||
// Declare caches to be built
|
||||
CachedRuntimePathFactory javaRuntimePathFactory;
|
||||
CachedRuntimePathFactory modeSketchPathFactory;
|
||||
CachedRuntimePathFactory modeSearchPathFactory;
|
||||
CachedRuntimePathFactory librarySketchPathFactory;
|
||||
CachedRuntimePathFactory librarySearchPathFactory;
|
||||
CachedRuntimePathFactory coreLibraryPathFactory;
|
||||
CachedRuntimePathFactory codeFolderPathFactory;
|
||||
|
||||
// Create collections
|
||||
sketchClassPathStrategies = new ArrayList<>();
|
||||
searchClassPathStrategies = new ArrayList<>();
|
||||
|
||||
libraryDependentCaches = new ArrayList<>();
|
||||
libraryImportsDependentCaches = new ArrayList<>();
|
||||
codeFolderDependentCaches = new ArrayList<>();
|
||||
|
||||
// Create strategies
|
||||
List<RuntimePathFactoryStrategy> runtimeStrategies = new ArrayList<>();
|
||||
runtimeStrategies.add(new JavaRuntimePathFactory());
|
||||
runtimeStrategies.add(new JavaFxRuntimePathFactory());
|
||||
javaRuntimePathFactory = new CachedRuntimePathFactory(
|
||||
new RuntimePathFactoryStrategyCollection(runtimeStrategies)
|
||||
);
|
||||
|
||||
modeSketchPathFactory = new CachedRuntimePathFactory(new ModeSketchRuntimePathFactory());
|
||||
modeSearchPathFactory = new CachedRuntimePathFactory(new ModeSearchRuntimePathFactory());
|
||||
|
||||
librarySketchPathFactory = new CachedRuntimePathFactory(new LibrarySketchRuntimePathFactory());
|
||||
librarySearchPathFactory = new CachedRuntimePathFactory(new LibrarySearchRuntimePathFactory());
|
||||
|
||||
coreLibraryPathFactory = new CachedRuntimePathFactory(new CoreLibraryRuntimePathFactory());
|
||||
codeFolderPathFactory = new CachedRuntimePathFactory(new CodeFolderRuntimePathFactory());
|
||||
|
||||
// Assign strategies to collections for producing paths
|
||||
sketchClassPathStrategies.add(javaRuntimePathFactory);
|
||||
sketchClassPathStrategies.add(modeSketchPathFactory);
|
||||
sketchClassPathStrategies.add(librarySketchPathFactory);
|
||||
sketchClassPathStrategies.add(coreLibraryPathFactory);
|
||||
sketchClassPathStrategies.add(codeFolderPathFactory);
|
||||
|
||||
searchClassPathStrategies.add(javaRuntimePathFactory);
|
||||
searchClassPathStrategies.add(modeSearchPathFactory);
|
||||
searchClassPathStrategies.add(librarySearchPathFactory);
|
||||
searchClassPathStrategies.add(coreLibraryPathFactory);
|
||||
searchClassPathStrategies.add(codeFolderPathFactory);
|
||||
|
||||
// Assign strategies to collections for cache invalidation
|
||||
libraryDependentCaches.add(coreLibraryPathFactory);
|
||||
|
||||
libraryImportsDependentCaches.add(librarySketchPathFactory);
|
||||
libraryImportsDependentCaches.add(librarySearchPathFactory);
|
||||
|
||||
codeFolderDependentCaches.add(codeFolderPathFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all of the runtime path caches associated with sketch libraries.
|
||||
*/
|
||||
public void markLibrariesChanged() {
|
||||
invalidateAll(libraryDependentCaches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all of the runtime path caches associated with sketch library imports.
|
||||
*/
|
||||
public void markLibraryImportsChanged() {
|
||||
invalidateAll(libraryImportsDependentCaches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all of the runtime path caches associated with the code folder having changed.
|
||||
*/
|
||||
public void markCodeFolderChanged() {
|
||||
invalidateAll(codeFolderDependentCaches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a classpath and inject it into a {PreprocessedSketch.Builder}.
|
||||
*
|
||||
* @param result The {PreprocessedSketch.Builder} into which the classpath should be inserted.
|
||||
* @param mode The {JavaMode} for which the classpath should be generated.
|
||||
*/
|
||||
public void prepareClassPath(PreprocessedSketch.Builder result, JavaMode mode) {
|
||||
List<ImportStatement> programImports = result.programImports;
|
||||
Sketch sketch = result.sketch;
|
||||
|
||||
prepareSketchClassPath(result, mode, programImports, sketch);
|
||||
prepareSearchClassPath(result, mode, programImports, sketch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all of the caches in a provided collection.
|
||||
*
|
||||
* @param caches The caches to invalidate so that, when their value is requested again, the value
|
||||
* is generated again.
|
||||
*/
|
||||
private void invalidateAll(List<CachedRuntimePathFactory> caches) {
|
||||
for (CachedRuntimePathFactory cache : caches) {
|
||||
cache.invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the classpath required for the sketch's execution.
|
||||
*
|
||||
* @param result The PreprocessedSketch builder into which the classpath and class loader should
|
||||
* be injected.
|
||||
* @param mode The JavaMode for which a sketch classpath should be generated.
|
||||
* @param programImports The imports listed by the sketch (user imports).
|
||||
* @param sketch The sketch for which the classpath is being generated.
|
||||
*/
|
||||
private void prepareSketchClassPath(PreprocessedSketch.Builder result, JavaMode mode,
|
||||
List<ImportStatement> programImports, Sketch sketch) {
|
||||
|
||||
Stream<String> sketchClassPath = sketchClassPathStrategies.stream()
|
||||
.flatMap((x) -> x.buildClasspath(mode, programImports, sketch).stream());
|
||||
|
||||
String[] classPathArray = sketchClassPath.toArray(String[]::new);
|
||||
URL[] urlArray = Arrays.stream(classPathArray)
|
||||
.map(path -> {
|
||||
try {
|
||||
return Paths.get(path).toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
Messages.loge("malformed URL when preparing sketch classloader", e);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(URL[]::new);
|
||||
|
||||
result.classLoader = new URLClassLoader(urlArray, null);
|
||||
result.classPath = classPathFactory.createFromPaths(classPathArray);
|
||||
result.classPathArray = classPathArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the classpath for searching in case of import suggestions.
|
||||
*
|
||||
* @param result The PreprocessedSketch builder into which the search classpath should be
|
||||
* injected.
|
||||
* @param mode The JavaMode for which a sketch classpath should be generated.
|
||||
* @param programImports The imports listed by the sketch (user imports).
|
||||
* @param sketch The sketch for which the classpath is being generated.
|
||||
*/
|
||||
private void prepareSearchClassPath(PreprocessedSketch.Builder result, JavaMode mode,
|
||||
List<ImportStatement> programImports, Sketch sketch) {
|
||||
|
||||
Stream<String> searchClassPath = searchClassPathStrategies.stream()
|
||||
.flatMap((x) -> x.buildClasspath(mode, programImports, sketch).stream());
|
||||
|
||||
result.searchClassPathArray = searchClassPath.toArray(String[]::new);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Common convenience functions for runtime path formulation.
|
||||
*/
|
||||
public class RuntimePathUtil {
|
||||
|
||||
/**
|
||||
* Remove invalid entries in a classpath string.
|
||||
*
|
||||
* @param classPathString The classpath to clean.
|
||||
* @return The cleaned classpath entries without invalid entries.
|
||||
*/
|
||||
public static List<String> sanitizeClassPath(String classPathString) {
|
||||
// Make sure class path does not contain empty string (home dir)
|
||||
return Arrays.stream(classPathString.split(File.pathSeparator))
|
||||
.filter(p -> p != null && !p.trim().isEmpty())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2019 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory which caches the results of another runtime path factory.
|
||||
*
|
||||
* <p>
|
||||
* Runtime path factory which decorates another {RuntimePathFactoryStrategy} that caches the
|
||||
* results of another runtime path factory. This is a lazy cached getter so the value will not be
|
||||
* resolved until it is requested.
|
||||
* </p>
|
||||
*/
|
||||
public class CachedRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
private AtomicReference<List<String>> cachedResult;
|
||||
private RuntimePathFactoryStrategy innerStrategy;
|
||||
|
||||
/**
|
||||
* Create a new cache around {RuntimePathFactoryStrategy}.
|
||||
*
|
||||
* @param newInnerStrategy The strategy to cache.
|
||||
*/
|
||||
public CachedRuntimePathFactory(RuntimePathFactoryStrategy newInnerStrategy) {
|
||||
cachedResult = new AtomicReference<>(null);
|
||||
innerStrategy = newInnerStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the cached path so that, when requested next time, it will be rebuilt from scratch.
|
||||
*/
|
||||
public void invalidateCache() {
|
||||
cachedResult.set(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached classpath or, if not cached, build a classpath using the inner strategy.
|
||||
*
|
||||
* <p>
|
||||
* Return the cached classpath or, if not cached, build a classpath using the inner strategy.
|
||||
* Note that this getter will not check to see if mode, imports, or sketch have changed. If a
|
||||
* cached value is available, it will be returned without examining the identity of the
|
||||
* parameters.
|
||||
* </p>
|
||||
*
|
||||
* @param mode The {JavaMode} for which the classpath should be built.
|
||||
* @param imports The sketch (user) imports.
|
||||
* @param sketch The sketch for which a classpath is to be returned.
|
||||
* @return Newly generated classpath.
|
||||
*/
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
return cachedResult.updateAndGet((cachedValue) ->
|
||||
cachedValue == null ? innerStrategy.buildClasspath(mode, imports, sketch) : cachedValue
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.app.Util;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Path factory which includes resources like jars within the sketch code folder.
|
||||
*/
|
||||
public class CodeFolderRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
// Code folder
|
||||
if (sketch.hasCodeFolder()) {
|
||||
File codeFolder = sketch.getCodeFolder();
|
||||
String codeFolderClassPath = Util.contentsToClassPath(codeFolder);
|
||||
classPath.append(codeFolderClassPath);
|
||||
}
|
||||
|
||||
return RuntimePathUtil.sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Library;
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory for libraries part of the processing mode (like {JavaMode}).
|
||||
*/
|
||||
public class CoreLibraryRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
||||
for (Library lib : mode.coreLibraries) {
|
||||
classPath.append(File.pathSeparator).append(lib.getClassPath());
|
||||
}
|
||||
|
||||
return RuntimePathUtil.sanitizeClassPath(classPath.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimeConst;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory which generates classpath entries for JavaFX / OpenFX.
|
||||
*/
|
||||
public class JavaFxRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
return Arrays.stream(RuntimeConst.JAVA_FX_JARS)
|
||||
.map(this::buildEntry)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a single classpath entry for OpenJFX.
|
||||
*
|
||||
* @param jarName The jar name like "javafx.base.jar" for which a fully qualified entry should be
|
||||
* created.
|
||||
* @return The fully qualified classpath entry like ".../Processing.app/Contents/PlugIns/
|
||||
* adoptopenjdk-11.0.1.jdk/Contents/Home/lib/javafx.base.jar"
|
||||
*/
|
||||
private String buildEntry(String jarName) {
|
||||
StringJoiner joiner = new StringJoiner(File.separator);
|
||||
joiner.add(System.getProperty("java.home"));
|
||||
joiner.add("lib");
|
||||
joiner.add(jarName);
|
||||
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimeConst;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory which enumerates the modules as part of the java runtime.
|
||||
*/
|
||||
public class JavaRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
return Arrays.stream(RuntimeConst.STANDARD_MODULES)
|
||||
.map(this::buildForModule)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a classpath entry for a module.
|
||||
*
|
||||
* @param moduleName The name of the module like "java.base.jmod".
|
||||
* @return The fully qualified classpath entry like ".../Processing.app/Contents/PlugIns/
|
||||
* * adoptopenjdk-11.0.1.jdk/Contents/Home/jmods/java.base.jmod"
|
||||
*/
|
||||
private String buildForModule(String moduleName) {
|
||||
StringJoiner jmodPathJoiner = new StringJoiner(File.separator);
|
||||
jmodPathJoiner.add(System.getProperty("java.home"));
|
||||
jmodPathJoiner.add("jmods");
|
||||
jmodPathJoiner.add(moduleName);
|
||||
return jmodPathJoiner.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Library;
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory to generate search classpath entries for third party libraries.
|
||||
*
|
||||
* <p>
|
||||
* Runtime path factory to generate classpath entries for third party libraries that are used when
|
||||
* generating import recommendations.
|
||||
* </p>
|
||||
*/
|
||||
public class LibrarySearchRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
StringJoiner classPathBuilder = new StringJoiner(File.pathSeparator);
|
||||
|
||||
for (Library lib : mode.contribLibraries) {
|
||||
classPathBuilder.add(lib.getClassPath());
|
||||
}
|
||||
|
||||
return RuntimePathUtil.sanitizeClassPath(classPathBuilder.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Library;
|
||||
import processing.app.Sketch;
|
||||
import processing.app.SketchException;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory to generate sketch classpath entries for third party libraries.
|
||||
*
|
||||
* <p>
|
||||
* Runtime path factory to generate classpath entries for third party libraries that are required
|
||||
* for running the sketch.
|
||||
* </p>
|
||||
*/
|
||||
public class LibrarySketchRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
StringJoiner classPathBuilder = new StringJoiner(File.pathSeparator);
|
||||
|
||||
imports.stream()
|
||||
.map(ImportStatement::getPackageName)
|
||||
.filter(pckg -> !isIgnorable(pckg))
|
||||
.map(pckg -> {
|
||||
try {
|
||||
return mode.getLibrary(pckg);
|
||||
} catch (SketchException e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(lib -> lib != null)
|
||||
.map(Library::getClassPath)
|
||||
.forEach(cp -> classPathBuilder.add(cp));
|
||||
|
||||
return RuntimePathUtil.sanitizeClassPath(classPathBuilder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a package is ignorable.
|
||||
*
|
||||
* @param packageName The name of the package to evaluate.
|
||||
* @return True if the package is part of standard Java (like java.lang.*). False otherwise.
|
||||
*/
|
||||
private boolean isIgnorable(String packageName) {
|
||||
return (packageName.startsWith("java.") || packageName.startsWith("javax."));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory to generate search classpath entries for the processing mode.
|
||||
*
|
||||
* <p>
|
||||
* Runtime path factory to generate classpath entries for the processing mode (like {JavaMode}) used
|
||||
* when generating import recommendations.
|
||||
* </p>
|
||||
*/
|
||||
public class ModeSearchRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
String searchClassPath = mode.getSearchPath();
|
||||
|
||||
if (searchClassPath != null) {
|
||||
return RuntimePathUtil.sanitizeClassPath(searchClassPath);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2012-19 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Library;
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.util.runtime.RuntimePathUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Runtime path factory for classpath entries required by the processing mode like {JavaMode}.
|
||||
*/
|
||||
public class ModeSketchRuntimePathFactory implements RuntimePathFactoryStrategy {
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
Library coreLibrary = mode.getCoreLibrary();
|
||||
String coreClassPath = coreLibrary != null ?
|
||||
coreLibrary.getClassPath() : mode.getSearchPath();
|
||||
if (coreClassPath != null) {
|
||||
return RuntimePathUtil.sanitizeClassPath(coreClassPath);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 2019 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Strategy which generates part of the classpath and/or module path.
|
||||
*
|
||||
* <p>
|
||||
* Strategy for factories each of which generate part of the classpath and/or module path required
|
||||
* by a sketch through user supplied requirements, mode (as in JavaMode) requirements, or transitive
|
||||
* requirements imposed by third party libraries.
|
||||
* </p>
|
||||
*/
|
||||
public interface RuntimePathFactoryStrategy {
|
||||
|
||||
/**
|
||||
* Create classpath and/or module path entries.
|
||||
*
|
||||
* @param mode The mode engaged by the user like JavaMode.
|
||||
* @param programImports The program imports imposed by the user within their sketch.
|
||||
* @param sketch The sketch provided by the user.
|
||||
* @return List of classpath and/or module path entries.
|
||||
*/
|
||||
List<String> buildClasspath(JavaMode mode, List<ImportStatement> programImports, Sketch sketch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
Copyright (c) 20119 The Processing Foundation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package processing.mode.java.pdex.util.runtime.strategy;
|
||||
|
||||
import processing.app.Sketch;
|
||||
import processing.mode.java.JavaMode;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Strategy which concatenates paths generated from a collection of RuntimePathFactoryStrategies.
|
||||
*/
|
||||
public class RuntimePathFactoryStrategyCollection implements RuntimePathFactoryStrategy {
|
||||
|
||||
private final List<RuntimePathFactoryStrategy> strategies;
|
||||
|
||||
/**
|
||||
* Create a new path concatenation operation.
|
||||
*
|
||||
* @param newStrategies
|
||||
*/
|
||||
public RuntimePathFactoryStrategyCollection(List<RuntimePathFactoryStrategy> newStrategies) {
|
||||
strategies = newStrategies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> buildClasspath(JavaMode mode, List<ImportStatement> imports, Sketch sketch) {
|
||||
return strategies.stream()
|
||||
.flatMap((strategy) -> strategy.buildClasspath(mode, imports, sketch).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -330,7 +330,8 @@ public class Runner implements MessageConsumer {
|
||||
params.append("-Djna.nosys=true");
|
||||
|
||||
// Added for 3.2.1, was still using the default ext.dirs in the PDE
|
||||
try {
|
||||
// java.ext.dirs no longer supported in Java 11
|
||||
/*try {
|
||||
String extPath =
|
||||
new File(Platform.getJavaHome(), "lib/ext").getCanonicalPath();
|
||||
// quoting this on OS X causes it to fail
|
||||
@@ -338,7 +339,7 @@ public class Runner implements MessageConsumer {
|
||||
params.append("-Djava.ext.dirs=" + extPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
|
||||
if (Platform.isMacOS()) {
|
||||
// This successfully sets the application menu name,
|
||||
@@ -347,13 +348,22 @@ public class Runner implements MessageConsumer {
|
||||
// No longer needed / doesn't seem to do anything differently
|
||||
//params.append("-Dcom.apple.mrj.application.apple.menu.about.name=" +
|
||||
// build.getSketchClassName());
|
||||
} else if (Platform.isWindows()) {
|
||||
// No scaling of swing (see #5753) on zoomed displays until some issues regarding JEP 263
|
||||
// with rendering artifacts are sorted out.
|
||||
params.append("-Dsun.java2d.uiScale=1");
|
||||
}
|
||||
|
||||
// sketch.libraryPath might be ""
|
||||
// librariesClassPath will always have sep char prepended
|
||||
params.append("-Djava.library.path=" +
|
||||
build.getJavaLibraryPath() +
|
||||
String javaLibraryPath = build.getJavaLibraryPath();
|
||||
|
||||
String javaLibraryPathParam = "-Djava.library.path=" +
|
||||
javaLibraryPath +
|
||||
File.pathSeparator +
|
||||
System.getProperty("java.library.path"));
|
||||
System.getProperty("java.library.path");
|
||||
|
||||
params.append(javaLibraryPathParam);
|
||||
|
||||
params.append("-cp");
|
||||
params.append(build.getClassPath());
|
||||
|
||||
Reference in New Issue
Block a user