Create String list in Groovy
Asked Answered
C

3

9

The following code in Groovy adds GStrings to the list:

List<String> args = [ 'cmd', "-Dopt=${value}" ]

When I create a ProcessBuilder with this list, I get a ClassCastException. What's a groovy way to coerce the list elements to the correct type?

Crossness answered 6/7, 2011 at 7:6 Comment(2)
I added a comment about avoiding ProcessBuilder altogether to my answer (I am posting this incase you missed it)... It might save you some work :-)Melanous
One of my biggest peeves with Groovy is that it doesn't convert the type for you in this specific situation. The compiler knows the types, so it should be able to deal with this just as easily as if you'd assigned it to a String. :(Baguette
M
19

Or, you can do:

List<String> args = [ 'cmd', "-Dopt=${value}"] as String[]

or

List<String> args = [ 'cmd', "-Dopt=${value}"]*.toString()

actually, why are you using ProcessBuilder out of interest? Groovy adds ways to do process management, and even adds three execute methods to List

You can do (this is on OS X or Linux):

def opt = '-a'

println( [ 'ls', "$opt" ].execute( null, new File( '/tmp' ) ).text )

which prints out the files in my /tmp folder

Melanous answered 6/7, 2011 at 7:23 Comment(7)
Note that both do a bit too much work: The first one converts the initial List to a String[] and that back to a List, the second one creates a copy of the List as well and calls toString() on every element.Hewlett
@Joachim Yeah, but they both look cleaner (IMHO) than embedding toString inside the list on specific elements (and it makes it less likely that you missed an element)Melanous
very true. Also this is highly unlikely to be the critical element on any code-path.Hewlett
ProcessBuilder also accepts a String[] - so the first alternative can be replaced to be: String[] args = [ 'cmd', "-Dopt=${value}"] as String[]Longwood
Re execute: I need to call redirectErrorStream() but thanks for the suggestion. I could use it in a different place.Crossness
@Aaron you can call consumeProcessOutput(OutputStream output, OutputStream error) on the Process object returned by execute()Melanous
tim_yates: +1 but it's not 100% the same. For example, output and error are no longer in sync when I do it this way.Crossness
N
2

Try

List<String> args = [ 'cmd', "-Dopt=${value}".toString() ]

because the later is a GString.

Neutrality answered 6/7, 2011 at 7:20 Comment(0)
L
1

I did a test:

def value = "abc"
List<String> args = [ 'cmd', "-Dopt=${value}"];

System.out.println (args.getClass());

System.out.println (args.get(0).getClass());
System.out.println (args.get(1).getClass());

The output was:

class java.util.ArrayList
class java.lang.String
class org.codehaus.groovy.runtime.GStringImpl

Changing the code a bit to be:

def value = "abc"
List<String> args = [ 'cmd', "-Dopt=${value}".toString()];

System.out.println (args.getClass());

System.out.println (args.get(0).getClass());
System.out.println (args.get(1).getClass());

produced this:

class java.util.ArrayList
class java.lang.String
class java.lang.String

Should do the trick, but I'm not 100% sure this is the best way to do it.

Longwood answered 6/7, 2011 at 7:21 Comment(2)
Minor hint: I find System.out.println(args*.getClass()) to be easier to write and produce nicer output ;-)Hewlett
@Joachim, Cool! (or should I say, Groovy!)Longwood

© 2022 - 2024 — McMap. All rights reserved.