Skip to content

Commit

Permalink
Finished refactor to pdex.util.runtime ahead of adding tests.
Browse files Browse the repository at this point in the history
As part of processing#5753 / processing#5750's support for jmod (Jigsaw) and new OpenJFX structure, finished the refactor to pdex.util.runtime which increases testability and (hopefully) readability of runtime formulation now that Java 11 has made it slightly more complex.
  • Loading branch information
sampottinger committed Jan 28, 2019
1 parent 7bd8e28 commit 7bb31cb
Show file tree
Hide file tree
Showing 18 changed files with 457 additions and 218 deletions.
1 change: 0 additions & 1 deletion java/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@
<junit haltonfailure="true">
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<test name="processing.mode.java.pdex.util.runtime.strategy.JavaRuntimeFactoryStrategyTest" />
</junit>
</target>

Expand Down
200 changes: 6 additions & 194 deletions java/src/processing/mode/java/pdex/PreprocessingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@

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.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
Expand All @@ -48,17 +42,16 @@
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;

Expand All @@ -72,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);

Expand Down Expand Up @@ -320,68 +311,27 @@ private PreprocessedSketch preprocessSketch(PreprocessedSketch prevResult) {
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 ||
prevResult.classLoader == null || prevResult.classPath == null ||
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;
Expand Down Expand Up @@ -487,136 +437,7 @@ private static boolean checkIfImportsChanged(List<ImportStatement> prevImports,

/// 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 (jmods in Java 9+)
StringJoiner jmodPathJoiner = new StringJoiner(File.separator);
jmodPathJoiner.add(System.getProperty("java.home"));
jmodPathJoiner.add("jmods");
jmodPathJoiner.add("java.base.jmod");
String jmodsPath = jmodPathJoiner.toString();
classPath.append(File.pathSeparator).append(jmodsPath);
}

{ // 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 +
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();

/// --------------------------------------------------------------------------

Expand Down Expand Up @@ -651,15 +472,6 @@ private static CompilationUnit makeASTWithBindings(ASTParser parser,
}


/**
* 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<>();
Expand Down
11 changes: 11 additions & 0 deletions java/src/processing/mode/java/pdex/util/runtime/RuntimeConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,15 @@ public class RuntimeConst {
"jdk.xml.dom.jmod",
"jdk.zipfs.jmod"
};

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"
};
}

This file was deleted.

Loading

0 comments on commit 7bb31cb

Please sign in to comment.