Skip to content

Commit 248b85f

Browse files
committed
check needed classpath for engines
1 parent 2892ae7 commit 248b85f

File tree

7 files changed

+109
-8
lines changed

7 files changed

+109
-8
lines changed

graphviz-java/src/main/java/guru/nidi/graphviz/engine/AbstractJsGraphvizEngine.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,24 @@
2727
import java.util.regex.Matcher;
2828
import java.util.regex.Pattern;
2929

30+
import static guru.nidi.graphviz.engine.IoUtils.isOnClasspath;
3031
import static guru.nidi.graphviz.engine.IoUtils.readStream;
3132
import static java.util.stream.Collectors.joining;
3233

3334
public abstract class AbstractJsGraphvizEngine extends AbstractGraphvizEngine {
35+
private static final String VIZ_BASE = "META-INF/resources/webjars/viz.js-for-graphviz-java/2.1.2/";
36+
static boolean AVAILABLE = isOnClasspath(VIZ_BASE + "viz.js");
3437
private static final Pattern FONT_NAME_PATTERN = Pattern.compile("\"?fontname\"?\\s*=\\s*\"?(.*?)[\",;\\]]");
3538
private static final Map<Class<?>, ThreadLocal<JavascriptEngine>> ENGINES = new HashMap<>();
3639
private final Supplier<JavascriptEngine> engineSupplier;
3740
private final FontMeasurer fontMeasurer = new FontMeasurer();
3841

3942
protected AbstractJsGraphvizEngine(boolean sync, Supplier<JavascriptEngine> engineSupplier) {
4043
super(sync);
44+
if (!AVAILABLE) {
45+
throw new MissingDependencyException("Javascript engines are not available.",
46+
"org.webjars.npm:viz.js-for-graphviz-java");
47+
}
4148
this.engineSupplier = engineSupplier;
4249
}
4350

@@ -119,9 +126,8 @@ protected Entry<String, Options> preprocessCode(String src, Options options) {
119126
}
120127

121128
private String vizJsCode() {
122-
final String path = "/META-INF/resources/webjars/viz.js-for-graphviz-java/2.1.2/";
123-
try (final InputStream api = getClass().getResourceAsStream(path + "viz.js");
124-
final InputStream engine = getClass().getResourceAsStream(path + "full.render.js")) {
129+
try (final InputStream api = getClass().getResourceAsStream("/" + VIZ_BASE + "viz.js");
130+
final InputStream engine = getClass().getResourceAsStream("/" + VIZ_BASE + "full.render.js")) {
125131
return readStream(api) + readStream(engine);
126132
} catch (IOException e) {
127133
throw new AssertionError("Could not load internal javascript resources, is the jar file corrupt?", e);

graphviz-java/src/main/java/guru/nidi/graphviz/engine/Graphviz.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import guru.nidi.graphviz.model.Graph;
1919
import guru.nidi.graphviz.model.MutableGraph;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
2022

2123
import javax.annotation.Nullable;
2224
import java.io.*;
@@ -32,8 +34,11 @@
3234
import static java.util.Arrays.asList;
3335

3436
public final class Graphviz {
37+
private static final Logger LOG = LoggerFactory.getLogger(Graphviz.class);
38+
3539
private static final Pattern DPI_PATTERN = Pattern.compile("\"?dpi\"?\\s*=\\s*\"?([0-9.]+)\"?",
3640
Pattern.CASE_INSENSITIVE);
41+
private static final List<GraphvizEngine> AVAILABLE_ENGINES = availableEngines();
3742

3843
@Nullable
3944
private static volatile BlockingQueue<GraphvizEngine> engineQueue;
@@ -64,9 +69,27 @@ private Graphviz(@Nullable MutableGraph graph, String src, @Nullable Rasterizer
6469
this.filters = filters;
6570
}
6671

72+
private static List<GraphvizEngine> availableEngines() {
73+
final List<GraphvizEngine> engines = new ArrayList<>();
74+
if (GraphvizCmdLineEngine.AVAILABLE) {
75+
engines.add(new GraphvizCmdLineEngine());
76+
}
77+
if (GraphvizV8Engine.AVAILABLE) {
78+
engines.add(new GraphvizV8Engine());
79+
}
80+
engines.add(new GraphvizServerEngine());
81+
if (GraphvizJdkEngine.AVAILABLE) {
82+
engines.add(new GraphvizJdkEngine());
83+
}
84+
if (engines.size() == 1) {
85+
LOG.warn("Only GraphvizServerEngine is available." +
86+
" If you want to use other engines, please put the needed dependencies on the classpath.");
87+
}
88+
return engines;
89+
}
90+
6791
public static void useDefaultEngines() {
68-
useEngine(new GraphvizCmdLineEngine(), new GraphvizV8Engine(),
69-
new GraphvizServerEngine(), new GraphvizJdkEngine());
92+
useEngine(AVAILABLE_ENGINES);
7093
}
7194

7295
public static void useEngine(GraphvizEngine first, GraphvizEngine... rest) {

graphviz-java/src/main/java/guru/nidi/graphviz/engine/GraphvizCmdLineEngine.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Optional;
2828
import java.util.concurrent.TimeUnit;
2929

30+
import static guru.nidi.graphviz.engine.IoUtils.isOnClasspath;
3031
import static java.util.Locale.ENGLISH;
3132

3233
/**
@@ -36,6 +37,7 @@
3637
*/
3738
public class GraphvizCmdLineEngine extends AbstractGraphvizEngine {
3839
private static final Logger LOG = LoggerFactory.getLogger(AbstractGraphvizEngine.class);
40+
static boolean AVAILABLE = isOnClasspath("org.apache.commons.exec.CommandLine");
3941

4042
private final String envPath;
4143
private final CommandRunner cmdRunner;
@@ -51,6 +53,10 @@ public GraphvizCmdLineEngine() {
5153

5254
public GraphvizCmdLineEngine(String envPath, CommandLineExecutor executor) {
5355
super(true);
56+
if (!AVAILABLE) {
57+
throw new MissingDependencyException("Command line engine is not available.",
58+
"org.apache.commons:commons-exec");
59+
}
5460
this.envPath = envPath;
5561
cmdRunner = new CommandBuilder()
5662
.withShellWrapper(true)

graphviz-java/src/main/java/guru/nidi/graphviz/engine/GraphvizJdkEngine.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,41 @@
1515
*/
1616
package guru.nidi.graphviz.engine;
1717

18+
import javax.annotation.Nullable;
19+
20+
import static guru.nidi.graphviz.engine.IoUtils.isOnClasspath;
21+
1822
public class GraphvizJdkEngine extends AbstractJsGraphvizEngine {
23+
static boolean AVAILABLE = AbstractJsGraphvizEngine.AVAILABLE &&
24+
(tryGraal() != null || isOnClasspath("net.arnx.nashorn.lib.PromiseException"));
25+
1926
public GraphvizJdkEngine() {
2027
super(false, GraphvizJdkEngine::newEngine);
28+
if (!AVAILABLE) {
29+
throw new MissingDependencyException("JDK engine is not available", "net.arnx:nashorn-promise");
30+
}
2131
}
2232

2333
private static JavascriptEngine newEngine() {
34+
final GraalJavascriptEngine graal = tryGraal();
35+
return graal != null ? graal : new NashornJavascriptEngine();
36+
}
37+
38+
@Nullable
39+
private static GraalJavascriptEngine tryGraal() {
2440
try {
2541
return new GraalJavascriptEngine();
2642
} catch (ExceptionInInitializerError | NoClassDefFoundError | IllegalStateException e) {
27-
return new NashornJavascriptEngine();
43+
return null;
2844
}
2945
}
3046

3147
@Override
3248
protected void doInit() {
33-
engine().executeJavascript(promiseJsCode());
49+
final JavascriptEngine engine = engine();
50+
if (engine instanceof NashornJavascriptEngine) {
51+
engine.executeJavascript(promiseJsCode());
52+
}
3453
super.doInit();
3554
}
3655
}

graphviz-java/src/main/java/guru/nidi/graphviz/engine/GraphvizV8Engine.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@
1717

1818
import javax.annotation.Nullable;
1919

20+
import static guru.nidi.graphviz.engine.IoUtils.isOnClasspath;
21+
2022
public class GraphvizV8Engine extends AbstractJsGraphvizEngine {
23+
static boolean AVAILABLE = AbstractJsGraphvizEngine.AVAILABLE && isOnClasspath("com.eclipsesource.v8.V8");
24+
2125
public GraphvizV8Engine() {
2226
this(null);
2327
}
2428

2529
public GraphvizV8Engine(@Nullable String extractionPath) {
2630
super(true, () -> new V8JavascriptEngine(extractionPath));
31+
if (!AVAILABLE) {
32+
throw new MissingDependencyException("V8 engine is not available.", "com.eclipsesource.j2v8:j2v8_*");
33+
}
2734
}
2835
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright © 2015 Stefan Niederhauser ([email protected])
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package guru.nidi.graphviz.engine;
17+
18+
public class MissingDependencyException extends GraphvizException {
19+
private final String dependency;
20+
21+
public MissingDependencyException(String message, String dependency) {
22+
super(message + " Missing '" + dependency + "' dependency.");
23+
this.dependency = dependency;
24+
}
25+
26+
public String getDependency() {
27+
return dependency;
28+
}
29+
}

graphviz-java/src/main/java/guru/nidi/graphviz/engine/Rasterizer.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package guru.nidi.graphviz.engine;
1717

18+
import org.slf4j.LoggerFactory;
19+
1820
import javax.annotation.Nullable;
1921
import java.awt.*;
2022
import java.awt.image.BufferedImage;
@@ -28,7 +30,16 @@ public interface Rasterizer {
2830
@Nullable
2931
Rasterizer SALAMANDER = isOnClasspath("com.kitfox.svg.SVGDiagram") ? new SalamanderRasterizer() : null;
3032
@Nullable
31-
Rasterizer DEFAULT = BATIK != null ? BATIK : SALAMANDER;
33+
Rasterizer DEFAULT = getDefault();
34+
35+
@Nullable
36+
static Rasterizer getDefault() {
37+
final Rasterizer r = BATIK != null ? BATIK : SALAMANDER;
38+
if (r == null) {
39+
LoggerFactory.getLogger(Rasterizer.class).warn("Neither Batik nor Salamander found on classpath");
40+
}
41+
return r;
42+
}
3243

3344
static Rasterizer builtIn(String format) {
3445
return new BuiltInRasterizer(format, null, null);

0 commit comments

Comments
 (0)