Consolidate logic for runtime path generation into a single class.

In response to @benfry feedback within https://github.com/processing/processing4/pull/1, consolidated all of the runtime path calculation into a single class while still maintaining all of the tests and caching logic. This reduces the class count but still adapts to jmod and javafx path calculation requirements for java 11.
This commit is contained in:
A Pottinger
2019-10-06 21:10:16 -07:00
parent 2b05da132a
commit a265b1ed14
28 changed files with 57 additions and 1352 deletions

View File

@@ -49,7 +49,7 @@ import processing.mode.java.JavaEditor;
import processing.mode.java.JavaMode;
import processing.mode.java.pdex.TextTransform.OffsetMapper;
import processing.mode.java.pdex.util.ProblemFactory;
import processing.mode.java.pdex.util.runtime.RuntimePathBuilder;
import processing.mode.java.pdex.util.RuntimePathBuilder;
import processing.mode.java.preproc.PdePreprocessor;
import processing.mode.java.preproc.PreprocessorResult;
import processing.mode.java.preproc.code.ImportUtil;

View File

@@ -1,118 +0,0 @@
/*
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"
};
}

View File

@@ -1,220 +0,0 @@
/* -*- 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);
}
}

View File

@@ -1,48 +0,0 @@
/* -*- 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());
}
}

View File

@@ -1,84 +0,0 @@
/* -*- 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
);
}
}

View File

@@ -1,52 +0,0 @@
/* -*- 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());
}
}

View File

@@ -1,49 +0,0 @@
/* -*- 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());
}
}

View File

@@ -1,64 +0,0 @@
/* -*- 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();
}
}

View File

@@ -1,62 +0,0 @@
/* -*- 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();
}
}

View File

@@ -1,55 +0,0 @@
/* -*- 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());
}
}

View File

@@ -1,76 +0,0 @@
/* -*- 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."));
}
}

View File

@@ -1,53 +0,0 @@
/* -*- 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<>();
}
}
}

View File

@@ -1,50 +0,0 @@
/* -*- 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<>();
}
}
}

View File

@@ -1,51 +0,0 @@
/* -*- 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);
}

View File

@@ -1,54 +0,0 @@
/* -*- 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());
}
}