33using System . IO ;
44using System . IO . Compression ;
55using System . Reflection ;
6+ using System . Runtime . InteropServices ;
7+ using System . Threading . Tasks ;
68using System . Xml . Serialization ;
79
810// TODOS:
911// Performance - now every call causes verapdf to be unpacked
10- // Inportability - Make verapdf working on linux
1112// Codestyle - make this code great again
1213// Fix the generated casing in report.cs
1314
@@ -17,7 +18,7 @@ public class PdfAValidator : IDisposable
1718 {
1819 public void Dispose ( )
1920 {
20- Directory . Delete ( _pathVeraPdf , true ) ;
21+ Directory . Delete ( _pathVeraPdfDirectory , true ) ;
2122 }
2223
2324 /// <summary>
@@ -26,8 +27,9 @@ public void Dispose()
2627 /// <param name="pathToVeraPdfBin"></param>
2728 public PdfAValidator ( string pathToVeraPdfBin , string pathToJava )
2829 {
29- _pathVeraPdfBat = pathToVeraPdfBin ;
30- _pathJava = pathToJava ;
30+ // TODO Test
31+ VeraPdfStarterScript = pathToVeraPdfBin ;
32+ PathJava = pathToJava ;
3133 }
3234
3335 /// <summary>
@@ -36,10 +38,10 @@ public PdfAValidator(string pathToVeraPdfBin, string pathToJava)
3638 public PdfAValidator ( )
3739 { intiPathToVeraPdfBinAndJava ( ) ; }
3840
39- private string _pathVeraPdf ;
40- private string _pathJava ;
41+ private string _pathVeraPdfDirectory ;
42+ public string PathJava { private set ; get ; }
4143 private string _pathZipVeraPdf ;
42- private string _pathVeraPdfBat ;
44+ public string VeraPdfStarterScript { private set ; get ; }
4345
4446 public bool Validate ( string pathToPdfFile )
4547 {
@@ -59,52 +61,110 @@ public report ValidateWithDetailedReport(string pathToPdfFile)
5961 {
6062 string concatedVeraPdfOutput = string . Empty ;
6163
62- process . StartInfo . FileName = _pathVeraPdfBat ;
64+ process . StartInfo . FileName = VeraPdfStarterScript ;
6365 process . StartInfo . RedirectStandardOutput = true ;
64- process . StartInfo . RedirectStandardError = false ;
66+ process . StartInfo . RedirectStandardError = true ;
6567 process . StartInfo . UseShellExecute = false ;
6668 process . StartInfo . CreateNoWindow = true ;
67- process . StartInfo . EnvironmentVariables [ "JAVACMD" ] = _pathJava ;
69+ if ( ! String . IsNullOrEmpty ( PathJava ) )
70+ process . StartInfo . EnvironmentVariables [ "JAVACMD" ] = PathJava ;
6871 ProcessStartInfo startInfo = process . StartInfo ;
6972 string [ ] arguments = new string [ ] { "\" " , pathToPdfFile , "\" " } ;
7073 startInfo . Arguments = string . Concat ( arguments ) ;
7174 process . Start ( ) ;
7275
73- while ( true )
76+ var outputResult = GetStreamOutput ( process . StandardOutput ) ;
77+ var errorResult = GetStreamOutput ( process . StandardError ) ;
78+
79+ process . WaitForExit ( ) ;
80+
81+ if ( string . IsNullOrEmpty ( errorResult ) )
7482 {
75- string standardOutputLine = process . StandardOutput . ReadLine ( ) ;
76- if ( standardOutputLine == null )
77- {
78- using ( var sr = new StringReader ( concatedVeraPdfOutput ) )
79- {
80- var veraPdfReport = ( report ) new XmlSerializer ( typeof ( report ) ) . Deserialize ( sr ) ;
81- return veraPdfReport ;
82- }
83- }
84-
85- concatedVeraPdfOutput += standardOutputLine ;
83+ var veraPdfReport = DeserializeXml < report > ( outputResult ) ;
84+ return veraPdfReport ;
8685 }
86+
87+ throw new VeraPdfException ( "Calling VearPdf caused an error: " + errorResult ) ;
8788 }
8889 }
8990
91+ private string GetStreamOutput ( StreamReader stream )
92+ {
93+ //Read output in separate task to avoid deadlocks
94+ var outputReadTask = Task . Run ( ( ) => stream . ReadToEnd ( ) ) ;
95+
96+ return outputReadTask . Result ;
97+ }
98+
99+ static T DeserializeXml < T > ( string sourceXML ) where T : class
100+ {
101+ var serializer = new XmlSerializer ( typeof ( T ) ) ;
102+ T result = null ;
103+
104+ using ( TextReader reader = new StringReader ( sourceXML ) )
105+ result = ( T ) serializer . Deserialize ( reader ) ;
106+ return result ;
107+ }
108+
109+ public void SetLinuxFileExecuteable ( string filePath )
110+ {
111+ var chmodCmd = "chmod 700 " + filePath ;
112+ var escapedArgs = chmodCmd . Replace ( "\" " , "\\ \" " ) ;
113+
114+ var process = new Process
115+ {
116+ StartInfo = new ProcessStartInfo
117+ {
118+ RedirectStandardOutput = true ,
119+ UseShellExecute = false ,
120+ CreateNoWindow = true ,
121+ WindowStyle = ProcessWindowStyle . Hidden ,
122+ FileName = "/bin/bash" ,
123+ Arguments = $ "-c \" { escapedArgs } \" "
124+ }
125+ } ;
126+ process . Start ( ) ;
127+ process . WaitForExit ( ) ;
128+ }
129+
90130 private void intiPathToVeraPdfBinAndJava ( )
91131 {
92- _pathVeraPdf = Path . Combine ( Path . GetTempPath ( ) , "VeraPdf" + Guid . NewGuid ( ) ) ;
93- Directory . CreateDirectory ( _pathVeraPdf ) ;
94- _pathZipVeraPdf = Path . Combine ( _pathVeraPdf , "VeraPdf.zip" ) ;
132+ _pathVeraPdfDirectory = Path . Combine ( Path . GetTempPath ( ) , "VeraPdf" + Guid . NewGuid ( ) ) ;
133+ Directory . CreateDirectory ( _pathVeraPdfDirectory ) ;
134+ _pathZipVeraPdf = Path . Combine ( _pathVeraPdfDirectory , "VeraPdf.zip" ) ;
95135
96136 var assembly = Assembly . GetExecutingAssembly ( ) ;
97- using ( var stream = assembly . GetManifestResourceStream ( "PdfAValidator.VeraPdf.zip" ) )
98- using ( var fileStream = File . Create ( _pathZipVeraPdf ) )
137+
138+ if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
99139 {
100- stream . Seek ( 0 , SeekOrigin . Begin ) ;
101- stream . CopyTo ( fileStream ) ;
140+ using ( var stream = assembly . GetManifestResourceStream ( "PdfAValidator.VeraPdf.Windows.zip" ) )
141+ using ( var fileStream = File . Create ( _pathZipVeraPdf ) )
142+ {
143+ stream . Seek ( 0 , SeekOrigin . Begin ) ;
144+ stream . CopyTo ( fileStream ) ;
145+ }
146+ ZipFile . ExtractToDirectory ( _pathZipVeraPdf , _pathVeraPdfDirectory ) ;
147+ VeraPdfStarterScript = Path . Combine ( _pathVeraPdfDirectory , "verapdf" , "verapdf.bat" ) ;
148+ // took from https://adoptopenjdk.net/releases.html?variant=openjdk8&jvmVariant=hotspot#x64_win
149+ PathJava = Path . Combine ( _pathVeraPdfDirectory , "verapdf" , "jdk8u202-b08-jre" , "bin" , "java" ) ;
102150 }
151+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
152+ {
153+ var names = assembly . GetManifestResourceNames ( ) ;
154+
155+ using ( var stream = assembly . GetManifestResourceStream ( "PdfAValidator.VeraPdf.Linux.zip" ) )
156+ using ( var fileStream = File . Create ( _pathZipVeraPdf ) )
157+ {
158+ stream . Seek ( 0 , SeekOrigin . Begin ) ;
159+ stream . CopyTo ( fileStream ) ;
160+ }
161+ ZipFile . ExtractToDirectory ( _pathZipVeraPdf , _pathVeraPdfDirectory ) ;
103162
104- ZipFile . ExtractToDirectory ( _pathZipVeraPdf , _pathVeraPdf ) ;
105- _pathVeraPdfBat = Path . Combine ( _pathVeraPdf , "VeraPdf" , "verapdf.bat" ) ;
106- // took from https://adoptopenjdk.net/releases.html?variant=openjdk8&jvmVariant=hotspot#x64_win
107- _pathJava = Path . Combine ( _pathVeraPdf , "VeraPdf" , "jdk8u202-b08-jre" , "bin" , "java" ) ;
163+ VeraPdfStarterScript = Path . Combine ( _pathVeraPdfDirectory , "verapdf" , "verapdf" ) ;
164+ SetLinuxFileExecuteable ( VeraPdfStarterScript ) ;
165+ }
166+ else
167+ throw new NotImplementedException ( "Sorry, only supporting linux and windows." ) ;
108168 }
109169 }
110170}
0 commit comments