2929import java .util .concurrent .TimeUnit ;
3030
3131import static guru .nidi .graphviz .engine .GraphvizLoader .isOnClasspath ;
32+ import static guru .nidi .graphviz .service .CommandRunner .isExecutableFile ;
33+ import static guru .nidi .graphviz .service .CommandRunner .isExecutableFound ;
34+ import static guru .nidi .graphviz .service .SystemUtils .pathOf ;
3235import static java .util .Locale .ENGLISH ;
3336
3437/**
@@ -40,6 +43,8 @@ public class GraphvizCmdLineEngine extends AbstractGraphvizEngine {
4043 private static final Logger LOG = LoggerFactory .getLogger (AbstractGraphvizEngine .class );
4144 static final boolean AVAILABLE = isOnClasspath ("org/apache/commons/exec/CommandLine.class" );
4245
46+ @ Nullable
47+ private final String executable ;
4348 private final String envPath ;
4449 private final CommandRunner cmdRunner ;
4550
@@ -49,13 +54,30 @@ public class GraphvizCmdLineEngine extends AbstractGraphvizEngine {
4954 private String outputFileName ;
5055
5156 public GraphvizCmdLineEngine () {
52- this (Optional .ofNullable (System .getenv ("PATH" )).orElse ("" ), defaultExecutor ());
57+ this (null , Optional .ofNullable (System .getenv ("PATH" )).orElse ("" ), runner (defaultExecutor ()));
58+ }
59+
60+ public GraphvizCmdLineEngine (String executable ) {
61+ this (executable , Optional .ofNullable (System .getenv ("PATH" )).orElse ("" ), runner (defaultExecutor ()));
5362 }
5463
55- public GraphvizCmdLineEngine (String envPath , CommandLineExecutor executor ) {
64+ private GraphvizCmdLineEngine (@ Nullable String executable , String envPath , CommandRunner cmdRunner ) {
5665 super (true );
66+ this .executable = executable ;
5767 this .envPath = envPath ;
58- cmdRunner = new CommandBuilder ()
68+ this .cmdRunner = cmdRunner ;
69+ }
70+
71+ public GraphvizCmdLineEngine searchPath (String path ) {
72+ return new GraphvizCmdLineEngine (executable , path , cmdRunner );
73+ }
74+
75+ public GraphvizCmdLineEngine executor (CommandLineExecutor executor ) {
76+ return new GraphvizCmdLineEngine (executable , envPath , runner (executor ));
77+ }
78+
79+ private static CommandRunner runner (CommandLineExecutor executor ) {
80+ return new CommandBuilder ()
5981 .withShellWrapper (true )
6082 .withCommandExecutor (executor )
6183 .build ();
@@ -76,7 +98,7 @@ public GraphvizCmdLineEngine timeout(int amount, TimeUnit unit) {
7698
7799 @ Override
78100 protected void doInit () {
79- getEngineExecutable (Engine . DOT );
101+ getEngineExecutable ();
80102 }
81103
82104 @ Override
@@ -96,10 +118,10 @@ public EngineResult execute(String src, Options options, Rasterizer rasterizer)
96118
97119 private EngineResult doExecute (Path path , File dotFile , Options options , Rasterizer rasterizer )
98120 throws IOException , InterruptedException {
99- final String engine = getEngineExecutable (options .engine );
100121 final String format = getFormatName (options .format , rasterizer );
101- final String command = engine
122+ final String command = getEngineExecutable ()
102123 + (options .yInvert != null && options .yInvert ? " -y" : "" )
124+ + " -K" + options .engine .toString ().toLowerCase (ENGLISH )
103125 + " -T" + format
104126 + " " + dotFile .getAbsolutePath () + " -ooutfile." + format ;
105127 cmdRunner .exec (command , path .toFile (), timeout );
@@ -116,11 +138,16 @@ protected String preprocessCode(String src, Options options) {
116138 return replacePaths (imgReplaced , IMAGE_ATTR , path -> replacePath (path , options .basedir ));
117139 }
118140
119- private String getEngineExecutable (@ Nullable Engine engine ) {
120- final String cmd = engine == null ? "dot" : engine .toString ().toLowerCase (ENGLISH );
121- final List <String > exes = SystemUtils .executableNames (cmd );
141+ private String getEngineExecutable () {
142+ if (executable != null ) {
143+ if (isExecutableFile (pathOf (executable )) || isExecutableFound (executable , envPath )) {
144+ return executable ;
145+ }
146+ LOG .warn ("Executable '" + executable + "' not found directly and not on PATH. Trying with 'dot'." );
147+ }
148+ final List <String > exes = SystemUtils .executableNames ("dot" );
122149 for (final String exe : exes ) {
123- if (CommandRunner . isExecutableFound (exe , envPath )) {
150+ if (isExecutableFound (exe , envPath )) {
124151 return exe ;
125152 }
126153 }
0 commit comments