diff --git a/src/Java/JarRunner.cs b/src/Java/JarRunner.cs index 09497d3..6af76a8 100644 --- a/src/Java/JarRunner.cs +++ b/src/Java/JarRunner.cs @@ -22,12 +22,12 @@ public JarRunner(string javaPath, string jarPath) this.jarPath = jarPath; } - public async Task RunJarWithInputAsync(string input, CancellationToken cancellationToken, - params string[] arguments) + public async Task RunJarWithInputAsync(string input, string workingDirectory, + CancellationToken cancellationToken, params string[] arguments) { var argumentString = $"-Dfile.encoding=UTF-8 -jar \"{jarPath}\" {string.Join(" ", arguments)}"; - return await new ProcessHelper().RunProcessWithInputAsync(javaPath, argumentString, input, cancellationToken) - .ConfigureAwait(false); + return await new ProcessHelper().RunProcessWithInputAsync(javaPath, argumentString, + input, workingDirectory, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Local/LocalCommandProvider.cs b/src/Local/LocalCommandProvider.cs index b268dd9..17528da 100644 --- a/src/Local/LocalCommandProvider.cs +++ b/src/Local/LocalCommandProvider.cs @@ -6,7 +6,9 @@ internal class LocalCommandProvider { private readonly ErrorReportMode errorReportMode; private readonly string localGraphvizDotPath; + private readonly string include; private readonly string delimitor; + private readonly int imageIndex; private string ErrorReportModeCommand { @@ -26,19 +28,27 @@ private string ErrorReportModeCommand } } - private string GraphvizDotCommand => string.IsNullOrEmpty(localGraphvizDotPath) + private string GraphvizDotCommand => string.IsNullOrEmpty(localGraphvizDotPath) ? string.Empty : $" -graphvizdot \"{localGraphvizDotPath}\""; + private string IncludeCommand => string.IsNullOrEmpty(include) + ? string.Empty + : $" \"-I{include}\""; + private string DelimitorCommand => string.IsNullOrEmpty(delimitor) ? string.Empty : $" -pipedelimitor \"{delimitor}\""; + private string ImageIndexCommand => $" -pipeimageindex {imageIndex}"; + public LocalCommandProvider(PlantUmlSettings settings) { errorReportMode = settings.ErrorReportMode; localGraphvizDotPath = settings.LocalGraphvizDotPath; + include = settings.Include; delimitor = settings.Delimitor; + imageIndex = settings.ImageIndex; } public string GetCommand(OutputFormat outputFormat) @@ -46,7 +56,9 @@ public string GetCommand(OutputFormat outputFormat) string outputFormatCommand = GetOuputFormatCommand(outputFormat); outputFormatCommand += ErrorReportModeCommand; outputFormatCommand += GraphvizDotCommand; + outputFormatCommand += IncludeCommand; outputFormatCommand += DelimitorCommand; + outputFormatCommand += ImageIndexCommand; return outputFormatCommand; } diff --git a/src/Local/LocalPlantUmlRenderer.cs b/src/Local/LocalPlantUmlRenderer.cs index 2ea907c..d6248d0 100644 --- a/src/Local/LocalPlantUmlRenderer.cs +++ b/src/Local/LocalPlantUmlRenderer.cs @@ -4,27 +4,32 @@ using System.Threading.Tasks; using PlantUml.Net.Java; using PlantUml.Net.Remote; +using PlantUml.Net.Tools; namespace PlantUml.Net.Local { internal class LocalPlantUmlRenderer : IPlantUmlRenderer { private readonly JarRunner jarRunner; + private readonly string workingDirectory; private readonly LocalCommandProvider commandProvider; private readonly RenderUrlCalculator renderUrlCalculator; - public LocalPlantUmlRenderer(JarRunner jarRunner, LocalCommandProvider commandProvider, RenderUrlCalculator renderUrlCalculator) + public LocalPlantUmlRenderer(JarRunner jarRunner, string workingDirectory, + LocalCommandProvider commandProvider, RenderUrlCalculator renderUrlCalculator) { this.jarRunner = jarRunner; + this.workingDirectory = workingDirectory; this.commandProvider = commandProvider; this.renderUrlCalculator = renderUrlCalculator; } - public async Task RenderAsync(string code, OutputFormat outputFormat, CancellationToken cancellationToken = default) + public async Task RenderAsync(string code, OutputFormat outputFormat, + CancellationToken cancellationToken = default(CancellationToken)) { string command = commandProvider.GetCommand(outputFormat); - var processResult = await jarRunner.RunJarWithInputAsync(code, cancellationToken, command, "-pipe", "-charset UTF-8") - .ConfigureAwait(false); + IProcessResult processResult = await jarRunner.RunJarWithInputAsync(workingDirectory, code, + cancellationToken, command, "-pipe", "-charset UTF-8").ConfigureAwait(false); if (processResult.ExitCode != 0) { string message = Encoding.UTF8.GetString(processResult.Error); diff --git a/src/PlantUmlSettings.cs b/src/PlantUmlSettings.cs index 61babe4..9fd9296 100644 --- a/src/PlantUmlSettings.cs +++ b/src/PlantUmlSettings.cs @@ -37,12 +37,28 @@ public class PlantUmlSettings /// public RenderingMode RenderingMode { get; set; } + /// + /// Include a file as if '!include file' were used, also allowing pattern like '*.puml' + /// + public string Include { get; set; } + + /// + /// The working directory to use which may is needed for relative includes. + /// Defaults to null to use the applications executable directory. + /// + public string WorkingDirectory { get; set; } + /// /// Separators between diagrams if multiple diagrams are generated. /// This way it can be determined can determine where one image ends and another starts. /// public string Delimitor { get; set; } + /// + /// To generate the Nth image + /// + public int ImageIndex { get; set; } + public PlantUmlSettings() { RenderingMode = RenderingMode.Remote; diff --git a/src/RendererFactory.cs b/src/RendererFactory.cs index fdbfe0e..ba9c671 100644 --- a/src/RendererFactory.cs +++ b/src/RendererFactory.cs @@ -27,7 +27,7 @@ public IPlantUmlRenderer CreateRenderer(PlantUmlSettings settings) JarRunner jarRunner = CreateJarRunner(settings); LocalCommandProvider commandProvider = new LocalCommandProvider(settings); - return new LocalPlantUmlRenderer(jarRunner, commandProvider, renderUrlCalculator); + return new LocalPlantUmlRenderer(jarRunner, settings.WorkingDirectory, commandProvider, renderUrlCalculator); default: throw new ArgumentException("Invalid rendering mode", nameof(settings.RenderingMode)); diff --git a/src/Tools/ProcessHelper.cs b/src/Tools/ProcessHelper.cs index c9b12b8..7004cb2 100644 --- a/src/Tools/ProcessHelper.cs +++ b/src/Tools/ProcessHelper.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -6,11 +7,12 @@ namespace PlantUml.Net.Tools { internal class ProcessHelper { - public async Task RunProcessWithInputAsync(string fileName, string arguments, string input, CancellationToken cancellationToken) + public async Task RunProcessWithInputAsync(string fileName, string arguments, string workingDirectory, + string input, CancellationToken cancellationToken) { using (Process process = new Process() { - StartInfo = GetProcessStartInfo(fileName, arguments), + StartInfo = GetProcessStartInfo(fileName, arguments, workingDirectory), EnableRaisingEvents = true }) { @@ -21,7 +23,14 @@ public async Task RunProcessWithInputAsync(string fileName, stri { if (tcs.TrySetCanceled()) { - process.Kill(); + try + { + process.Kill(); + } + catch (ArgumentNullException) + { + //Catch potential ArgumentNullException: SafeHandle cannot be null + } } }); } @@ -29,7 +38,7 @@ public async Task RunProcessWithInputAsync(string fileName, stri process.Start(); process.WriteInput(input); - Task.Run(() => + _ = Task.Run(() => { ProcessResult result = new ProcessResult { @@ -44,7 +53,7 @@ public async Task RunProcessWithInputAsync(string fileName, stri } } - private static ProcessStartInfo GetProcessStartInfo(string command, string arguments) + private static ProcessStartInfo GetProcessStartInfo(string command, string arguments, string workingDirectory) { return new ProcessStartInfo(command) { @@ -56,7 +65,8 @@ private static ProcessStartInfo GetProcessStartInfo(string command, string argum CreateNoWindow = true, Arguments = arguments, StandardErrorEncoding = System.Text.Encoding.UTF8, - StandardOutputEncoding = System.Text.Encoding.UTF8 + StandardOutputEncoding = System.Text.Encoding.UTF8, + WorkingDirectory = workingDirectory }; } }