Scala - Fails to execute a process through terminal in a particular scenario - java

I'm using graphviz to generate graphs based on the messages passed in a scala program.
To invoke the graphviz application from inside the scala program, I'm using the exec() method (similar to Java). It successfully executed the command and created the graph when I used the below code snippet:
var cmd: String = "dot -Tpng Graph.dot -o Graph.png"
var run: Runtime = Runtime.getRuntime() ;
var pr: Process = run.exec(cmd) ;
However It fails to execute after changing the path of the input and output files (I just included a directory inside which the input file and output file resides as shown below)
def main(args: Array[String]): Unit = {
var DirectoryName: String = "Logs"
var GraphFileName: String = DirectoryName + File.separator + "Graph.dot"
val GraphFileObj: File = new File(GraphFileName)
// var cmd: String = "dot -Tpng Graph.dot -o Graph.png"
var cmd: String = "dot -Tpng \"" + GraphFileObj.getAbsolutePath + "\" -o \"" + DirectoryName + File.separator + "Graph.png\"" ;
println(cmd)
var run: Runtime = Runtime.getRuntime() ;
var pr: Process = run.exec(cmd) ;
}
The same command when executed through terminal gives proper output. Can you please help me to find what I'm missing?

exec is not a shell...e.g. quoting won't work as you expect, and thus your path (which may contain spaces, etc) will not be processed as you expect. The command will be broken apart using StringTokenizer, and your literal quotes will be...well..literal.
Use the form of exec that takes an array instead, so you can tokenize the command correctly.
val args = Array[String]("dot", "-Tpng", GraphFileObj.getAbsolutePath, ...);
run.exec(args)

Related

Using common methods for Jenkins builds

I have multiple Jenkins jobs using pipeline scripts and i use the same method for at least 4 of them
def createJiraLinks(def ticketNumbers) {
ArrayList<String> jiraLinks = new ArrayList<String>();
for(int i =0; i < ticketNumbers.size(); i++) {
def jira_json = sh script: """/usr/local/bin/curl -X GET -H "Content-Type: application/json" --cert-type PEM --key-type PEM -E /Users/Jenkins/.jenkins/workspace/certificates/cert.pem --key /Users/Jenkins/.jenkins/workspace/certificates/cert.pem https://jira.dev.org.co.uk:443/rest/api/2/issue/${ticketNumbers[i]}""", returnStdout: true
def json = jsonParse(jira_json);
def summary = json['fields']['summary'].toString();
jiraLinks.add("[" + ticketNumbers[i] + "](https://jira.dev.org.co.uk/browse/" + ticketNumbers[i] + ")" + " - " + summary);
}
return jiraLinks;
}
How can i have each pipeline job import this method so that if i ever need to update it i can just do it once, the key part here is having the ability to use sh script: as if i run the the curl command using "String.execute()" the command fails as i cannot correctly format it
Any advice/tips appreaciated
Thanks
See the detailed description at Extending with Shared Libraries.

Run a jar for specific emails in Outlook

I have to run some java code every time I receive a specific email.
I just download the attachment in the email, run the jar and reply with the response from executing that jar with the attachment.
Is it possible to somehow automate this ?
I have checked out VBA routines that can be called using outlook rules but I am not sure whether I can execute my jar file with this.
Any ideas ?
Here is the structure, I'll let you tune it!
You can set a rule to use SaveToDiskAndReply which is the main program.
Paste this at the start of your Outlook module :
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub RunSleep( _
exec As WshExec, _
Optional timeSegment As Long = 800 _
)
Do While exec.Status = WshRunning
Sleep timeSegment
Loop
End Sub
Private Function RunProgram( _
program As String, _
Optional command As String = "" _
) As WshExec
Dim wsh As New WshShell
Dim exec As WshExec
Set exec = wsh.exec(program)
Call exec.StdIn.WriteLine(command)
Call RunSleep(exec)
Set RunProgram = exec
End Function
Public Function Run_Jar() As String
Dim program As WshExec
Dim value As String
'''Set the path (jar and log)
Set program = RunProgram("java -jar ""D:\\Demo.jar"" 8861ccd621")
DoEvents
Run_Jar = program.StdOut.ReadAll
End Function
And use that as the script launched by the rule :
Public Sub SaveToDiskAndReply(ItM As Outlook.MailItem)
Dim oAttS As Outlook.Attachments
Dim objAtt As Outlook.Attachment
Dim oItM As Outlook.MailItem
Dim saveFolder As String
Dim dateFormat As String
Dim JarReturn As String
dateFormat = Format(Now, "yyyy-mm-dd")
saveFolder = "c:\temp\"
Set oAttS = ItM.Attachments
'''Save the attachements
For Each objAtt In oAttS
objAtt.SaveAsFile saveFolder & objAtt.FileName
Next objAtt
'''Run your jar
JarReturn = Run_Jar
'''Fill the email
Set oItM = OutApp.CreateItem(0)
'''Decomment the next line when you're done testing
'On Error Resume Next
With oItM
.To = ItM.SenderEmailAddress
.CC = ""
.BCC = ""
.Subject = ItM.Subject
.Body = JarReturn
For Each objAtt In oAttS
.Attachments.Add saveFolder & objAtt.FileName
Next objAtt
.Send 'or use .Display
End With
On Error GoTo 0
Set oAttS = Nothing
Set objAtt = Nothing
End Sub

Java runtime exec not handling string array well

I have a tomcat servlet which calls a jar function with parameters. The first parameter sometimes contains space. So I tried to use a String array, but it doesn't work at all.
What am I doing wrong?
requestParm = "java -classpath c:\\j\\test.jar test.connect " + fileName + " new";
requestParmarray =new String[]{"java -classpath c:\\j\\test.jar test.connect ",fileName , " new"};
requestParmarrayNew =new String[]{"java -classpath c:\\j\\test.jar test.connect "+fileName+" new"};
// This line works.but can not handle space well
Process ls_proc = Runtime.getRuntime().exec(requestPar);
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarray );
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarrayNew );
// Does not call the function at all
Process ls_proc = new ProcessBuilder("java -classpath c:\\j\\test.jar test.connect ",fileName, "new" ).start();
You're creating the array incorrectly: Each individual argument must be in its own entry:
String[] requestParmArray = new String[] {
"java",
"-classpath",
"c:\\j\\test.jar",
"test.connect",
fileName,
"new"
};
Process ls_proc = Runtime.getRuntime().exec(requestParmArray);
Also note that I removed the space you had after test.connect; the spaces you put on the command line are just to separate arguments, but in the above, they're separated by being separate entries in the array.
You should make the array in exec() have each parameter as a separate array entry like:
String[] requestPar = new String[]{"java", "-classpath", "c:\\j\\test.jar", "test.connect ", fileName, "new"};
And use it:
Process ls_proc = Runtime.getRuntime().exec(requestPar);

how to use property=value in CLI commons Library

I am trying to use the OptionBuilder.withArgName( "property=value" )
If my Option is called status and my command line was:
--status p=11 s=22
It only succeeds to identify the first argument which is 11 and it fails to identify the second argument...
Option status = OptionBuilder.withLongOpt("status")
.withArgName( "property=value" )
.hasArgs(2)
.withValueSeparator()
.withDescription("Get the status")
.create('s');
options.addOption(status);
Thanks for help in advance
You can access to passed properties using simple modification of passed command line options
--status p=11 --status s=22
or with your short syntax
-s p=11 -s s=22
In this case you can access to your properties simply with code
if (cmd.hasOption("status")) {
Properties props = cmd.getOptionProperties("status");
System.out.println(props.getProperty("p"));
System.out.println(props.getProperty("t"));
}
If you need to use your syntax strictly, you can manually parse your property=value pairs.
In this case you should remove .withValueSeparator() call, and then use
String [] propvalues = cmd.getOptionValues("status");
for (String propvalue : propvalues) {
String [] values = propvalue.split("=");
System.out.println(values[0] + " : " + values[1]);
}

Passing arguments to a lua function with luaj

I'm trying to call a lua function in a Java program using LuaJ. It works fine when I'm not passing any arguments to the closure:
String script = "print 'Hello World!'";
InputStream input = new ByteArrayInputStream(script.getBytes());
Prototype prototype = LuaC.compile(input, "script");
LuaValue globals = JsePlatform.standardGlobals();
LuaClosure closure = new LuaClosure(prototype, globals);
closure.call();
But now I'm trying a lua script with a top-level function that takes an argument and I just can't figure out how to pass in the argument from Java. Here's what I got so far:
String script = "function something(argument)\n"+
"test_string = 'Hello World!'\n"+
"print(test_string)\n"+
"print(argument)\n"+
"end";
InputStream input = new ByteArrayInputStream(script.getBytes());
Prototype prototype = LuaC.compile(input, "script");
LuaValue globals = JsePlatform.standardGlobals();
LuaClosure closure = new LuaClosure(prototype, globals);
closure.invokemethod("something", CoerceJavaToLua.coerce("Foo"));
This results in an Exception on the invokemethod line:
org.luaj.vm2.LuaError: attempt to index ? (a function value)
Thanks for your help!
In lua, the top-level scope is an anonymous function with variable arguments. These are accessed using ... In your example, you don't need the function named something, the chunk itself can be used as an unnamed function.
For example, this code in luaj-3.0-beta1
String script = "argument = ...\n"+
"test_string = 'Hello World!'\n"+
"print(test_string)\n"+
"print(argument)\n";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.loadString(script, "myscript");
chunk.call( LuaValue.valueOf("some-arg-value") );
Produced this result for me:
Hello World!
some-arg-value
You can pass in any number of arguments this way.
Since you receive
org.luaj.vm2.LuaError: attempt to index ? (a function value)
as your error; this means that your function is not being created at all.
Try it without \n and give spaces in the variable script. Like this:
String script = "function something(argument) " +
" test_string = 'Hello World!'; " +
" print( test_string ); " +
" print( argument ); " +
" end";

Categories