Returns java.lang.IllegalArgumentException in ProcessBuilder.start() - java

ProcessBuilder pb = new ProcessBuilder(commandInformation);
Process process = pb.start();
Above code is returning error:
java.lang.IllegalArgumentException
at java.lang.ProcessImpl.<init>(ProcessImpl.java:69)
at java.lang.ProcessImpl.start(ProcessImpl.java:30)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
at com.ConvertsImages.SystemCommandExecutor.executeCommand(SystemCommandExecutor.java:51)
at com.ConvertsImages.ImageConversion.runConvertCommand(ImageConversion.java:115)
at com.ConvertsImages.ImageConversion.runConvert(ImageConversion.java:80)
at com.ConvertsImages.ImageConversion.main(ImageConversion.java:26)
List commandInformation has only one entry as below:
["D:\Program Files\ImageMagick-6.8.6-Q16\convert.exe" "D:\ConvertFiles\ReImport_2507_1.jpg" -resize 40x40 "D:\ConvertFiles\proxy-40\ReImport_2507_1.jpg.jpg" ]
Please suggest.

Looking at the source code for ProcessBuilder, there is a method isQuoted that checks if a String argument is quoted and throws IllegalArgumentException if it is and a flag is checked.
private static boolean isQuoted(boolean noQuotesInside, String arg,
String errorMessage) {
int lastPos = arg.length() - 1;
if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') {
// The argument has already been quoted.
if (noQuotesInside) {
if (arg.indexOf('"', 1) != lastPos) {
// There is ["] inside.
throw new IllegalArgumentException(errorMessage);
}
}
return true;
}
if (noQuotesInside) {
if (arg.indexOf('"') >= 0) {
// There is ["] inside.
throw new IllegalArgumentException(errorMessage);
}
}
return false;
}
The above is called from getExecutablePath, note the true flag
boolean pathIsQuoted = isQuoted(true, path,
"Executable name has embedded quote, split the arguments");
which is called inside the ProcessImpl constructor
String executablePath = getExecutablePath(cmd[0]);
where cmd is the array created from your list. Index 0 matches the executable (in your case the whole String). In the String you showed us, your executable is quoted (or at least starts with one), so the method will throw an IllegalArgumentException.
This is confirmed by your stack trace
at java.lang.ProcessImpl.<init>(ProcessImpl.java:69)
That means inside your constructor.
Split each argument in your command list as a separate String element in the list. Don't put quotes around the executable.

I suspect you need a list of 'n' arguments.
It's currently interpreting your first list entry as the executable, and that's clearly not right since it incorporates your arguments too.

Please make sure, that the parameter passed in ProcessBuilder, commandInformation is a String array or a List<String>.
Parameters: command A string array containing the program and its
arguments
Parameters:
command The list containing the program and its arguments
Source
Oracle Docs. which states one of the reasons for IllegalArgumetnException.
Also I just noticed the file name that you have is included with .jpg.jpg .
Shouldn't it be fileName.jpg

Related

Only allow specified command name but still allow additional arguments

I am currently using this code to find a command that the user types in:
final Command command = commands.stream()
.filter(cmd -> input.startsWith(cmd.getName()))
.findAny()
.orElseThrow(() -> new InvalidInputException("unknown command"));
Every command class has its own getName() method. This is how the getName() method of ExitCommand() looks like:
#Override
public String getName() {
return "exit";
}
Unfortunately, with the current stream, "exittttttt" is also accepted. I can't use .equals(cmd.getName()) though, because there are commands that have subsequent arguments after the command name.
For example:
#Override
public String getName() {
return "delete track";
}
But the full command is delete track <id>.
Does anyone have an idea how to only allow the command name that is specified in each getName() method but also still allow further arguments?
EDIT:
Each command has its own getArguments() method. The method will return 0 for the exit command and 1 for the delete track command. Maybe this can be used to solve this problem?
If the space is what always separates commands from arguments, then you can use
.filter(cmd -> (cmd.getArguments() == 0 && input.equals(cmd.getName()))
|| input.startsWith(cmd.getName() + " "))
This checks that the input matches the command name exactly if the command supports no arguments, or the input has the command name followed by a space.
If commands supporting arguments may be called without arguments, then maybe this is the right predicate:
.filter(cmd -> (cmd.getArguments() == 0 && input.equals(cmd.getName()))
|| input.equals(cmd.getName()) //no args passed
|| input.startsWith(cmd.getName() + " "))
What about this line:
final Command command = commands.stream()
.filter(cmd -> (input.split(" +").length > 0 && input.split(" +")[0].equals(cmd.getName())))
.findAny()
.orElseThrow(() -> new InvalidInputException("unknown command"));
?
Your design need to be revisited. When we say a command, it will have options and arguments. In your case you are combining the command and option. Just seperate those out and use equals for command comparison.
delete -track <id>
delete- command
track- option can be identified with start of hyphen
optional arguments

Trouble finding solution to "variable might not have been initialized" error

My java program takes input from the user on the command line. The user has a choice: he may either specify a plain-text file as input with the -inputfile option, or he may leave this option unspecified, in which case the program takes input from System.in. (I've observed this behavior in some programs that come pre-installed with my Ubuntu distro, so I infer that it is acceptable practice.)
So I make a BufferedReader (inBR)that reads from the file, if provided, and a Scanner (inScanner) that reads from System.in otherwise. Only one of these objects is actually instantiated, the other is left as null. Later on, when the program reads a line from input, I have the following code:
String line;
if (inBR != null) {
line = inBR.readLine(); (1)
} else {
line = inScanner.nextLine(); (2)
}
Which gives me the compile time errors variable inBR might not have been initialized and variable inScanner might not have been initialized at lines (1) and (2), respectively.
What is the acceptable solution here? I've considered, "initialize the variable that's supposed to be null as an Object to shut up the compiler." But this is just a hack; surely there's a better way.
Also, why isn't this a runtime exception, as a NullPointerException?
EDIT: inScanner.readLine() => inScanner.nextLine()
Declaring them this way would avoid the compilation error :
BufferedReader inBR = null;
Scanner inScanner = null;
Of course you still have to give them actual values before accessing them, or you'll get NullPointerException.
In java all variables that are used must be initialized at some point.
public void example(){
String name;
if(name == null) return null;
}
In the above example the variable name has not been initialized. There are several ways to solve this problem:
public void example1(){
String name = null;
if(name == null) return null;
}
This would solve the problem.
This would also solve the problem
public void exapmle2(){
String name = "";
if(name == null) return null;
}
Make the condition whether or not a file is provided. For example, if a file is provided, create the buffered reader and set line immediately. Otherwise, create a scanner and set the line.

What would be a safe way to split a string into multiple parts in Java?

Let me clarify the question I am asking. I have a java program I am working on that takes input from the keyboard via a readline library called JLine2. The library takes the entire line types as a command instead on breaking it up into space separated commands and arguments. What I am looking for is a safe way to break up the string that is passed as input.
I have tried using an array but since I am in the early stages of concept I don't yet know how many arguments my largest command will have so using a pre-initialized array I don't think will work. The problem I have ran into is when I check for null values in the array or when I check to see if a particular command or argument is present. Java keeps throwing an exception about the array index being out of scope or something. Because the array does not actually have a value for say array index 1 which is an argument to command in array index 0.
So what I am looking for is a way to take a string and safely split it into parts without having Java yelling at me when and array exception has occurred.
Here is the very slim code I can provide...
ConfigShell.class
package shell;
import java.io.IOException;
import configFS.ConfigFS;
import jline.console.ConsoleReader;
public class ConfigShell {
private ConfigFS config;
public ConfigShell() throws IOException {
config = new ConfigFS();
}
public void init() throws IOException {
ConsoleReader console = new ConsoleReader();
// When the program starts we want to be placed at / (root).
console.setPrompt(">> ");
// In this case an infinite loop is better than a loop based on whether line is equal to null.
// This allows line to be equal to null and still stay inside the shell.
while (true) {
String line = console.readLine();
if (line != null) {
// If pre-initialize the array I can check for null as a value for an array index.
// If I did this at time I needed the array and there were not enough index occupied the system would return an exception.
String[] cmdArgs = new String[4];
// We need to split up the incoming line because JLine2 does not do it for me.
// This allows me to evaluate the entire command piece by piece rather all at once.
cmdArgs = line.split("\\s+");
if (cmdArgs[0] != null && cmdArgs[0].equals("add")) {
if (cmdArgs[1] != null && cmdArgs[1].equals("server")) {
if (cmdArgs[2] != null) {
config.addServer(cmdArgs[2]);
System.out.println("Added server " + cmdArgs[2] + " to the configuration successfully.");
}
}
}
if (cmdArgs[0].equals("exit")) {
System.exit(0);
}
}
}
}
}
Note for testing: My Start.class main method makes a call to the init method in the above file.
You can do:
String cmdArgs = line.split("\\s+");
and then, before accessing any particular index, check the size of the array so that you do not get ArrayIndexOutOfBoundException
Something like this:
if(cmdArgs.length>=2){
//It means you have at least 2 elements
//Now its safe to access cmdArgs[0] and cmdArgs[1]
}
If all your problem is to have a storage for a variable number of strings you can use ArrayList<String> object.
You declare it like ArrayList<String> as = new ArrayList<String>();
Then when you split something from your command string you will simply use add method:
as.add(yourString);
If you need to retrieve a particular element of the ArrayList you can use its get method:
as.get(0);
You can process all elements with for each loop:
for(String str: as) {
println(str):
}
Have a look here for info and here for an example.
As I think you can use StringTokenizer class and its methods for your requirement.
see the sample code below:
if(line!=null)
{
StringTokenizer st=new StringTokenizer(line);// by default it takes space as delimiter....you can use as required as second argument in constructor...
while(st.hasMoreTokens())
{
String token1=st.nextToken();
// do your stuffs here..........
// I don't know exactly about your required logic here......
/* if(token1.equals("add"))
{
String token2=st.nextToken();
if(token2.equals("server"))
{
String token3=st.nextToken();
config.addServer(token3);
System.out.println("Added server " + token3 + " to the configuration successfully.");
}
}
*/
}// while closing...
}// outer if closing...
Or as PM 77-1 told you can use ArrayList. But as my opinion LinkedList should be a better option here.

Switch or if statements in writing an interpreter in java

Current assignment needs me to write a program to read a file with instructions in a very tiny and basic programming language (behaves a little like FORTRAN) and execute those instructions. Basically it's a simple interpreter for the language I guess. It's completely linear, with statements all being defined in sequence and it only has String and integer variables. There are 8 keywords and 4 arithmetic operators I would need to find and define if they exist within the source file, and each line must start off with one of the reserved words.
A program in this language might look something like this:
#COMMENTS
LET.... (declares variables with values)
INTEGER myINT
STRING myString
CALCULATE...
PRINT
PRINTLN
END
Can I use a switch block instead of if-loops to find and then execute all these? My concern is that switches don't work with Strings in Java 6, which is what I'm supposed to be using, but I don't see how to easily assign various int values so the switch block would work. Thanks in advance for any suggestions and advice!
If your language is so simple that every statement begins in its own line and is identified by one word only, then (as Gray pointed out in another comment) you can split the words in each line, then compare the first word against a map. However, I would suggest, instead of mapping the words to ints and then doing one big switch, to map them into objects instead, like this (suggested by Dave Newton):
interface Directive {
public void execute(String line);
}
class LetDirective implements Directive {
public void execute(String line) { ...handle LET directive here... }
}
...define other directives in the same way...
Then define the map:
private Map<String, Directive> directives = new HashMap<String, Directive>();
directives.put("LET", new LetDirective());
...
Then in your parsing method:
int firstSpace = line.indexOf(' ');
String command = line;
if (firstSpace > 0)
command = line.substring(0, firstSpace);
Directive directive = directives.get(command.toUpperCase());
if (directive != null)
directive.execute(line);
else
...show some error...
Each directive would have to parse the rest of the line on its own and handle it correctly inside its execute() method.
The benefit of this over a switch is that you can handle a larger amount of commands without ending up with one gigantic method, but instead with one smaller method per each command.
If you are talking about converting strings to integers then you could do it with an Java enumerated type:
private enum ReservedWord {
LET,
...
}
// skip blank lines and comments
String[] tokens = codeLine.split(" ");
ReservedWord keyword;
try {
keyword = ReservedWord.valueOf(tokens[0]);
} catch (IllegalArgumentException e) {
// spit out nice syntax error message
}
You could also put the processing of the line inside of the enum as a method if you'd like. You could also do it with a Map:
private final Map<String, Integer> reservedWords = new HashMap<String, Integer>();
private final int RESERVED_WORD_LET 1
...
{
reservedWords.put("LET", RESERVED_WORD_LET);
...
}
// skip blank lines and comments
String[] tokens = codeLine.split(" ");
Integer value = reservedWords.get(tokens[0]);
if (value == null) // handle error... ;
switch (value) {
case 1:
// LET
...
}

Java: Check if command line arguments are null

I am looking to do some error checking for my command line arguments
public static void main(String[] args)
{
if(args[0] == null)
{
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}
However, this returns an array out of bounds exception, which makes sense. I am just looking for the proper usage.
The arguments can never be null. They just won't exist.
In other words, what you need to do is check the length of your arguments.
public static void main(String[] args) {
// Check how many arguments were passed in
if (args.length == 0) {
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}
#jjnguy's answer is correct in most circumstances. You won't ever see a null String in the argument array (or a null array) if main is called by running the application is run from the command line in the normal way.
However, if some other part of the application calls a main method, it is conceivable that it might pass a null argument or null argument array.
However(2), this is clearly a highly unusual use-case, and it is an egregious violation of the implied contract for a main entry-point method. Therefore, I don't think you should bother checking for null argument values in main. In the unlikely event that they do occur, it is acceptable for the calling code to get a NullPointerException. After all, it is a bug in the caller to violate the contract.
To expand upon this point:
It is possible that the args variable itself will be null, but not via normal execution. Normal execution will use java.exe as the entry point from the command line. However, I have seen some programs that use compiled C++ code with JNI to use the jvm.dll, bypassing the java.exe entirely. In this case, it is possible to pass NULL to the main method, in which case args will be null.
I recommend always checking if ((args == null) || (args.length == 0)), or if ((args != null) && (args.length > 0)) depending on your need.
You should check for (args == null || args.length == 0). Although the null check isn't really needed, it is a good practice.
if i want to check if any speicfic position of command line arguement is passed or not then how to check?
like for example
in some scenarios 2 command line args will be passed and in some only one will be passed then how do it check wheather the specfic commnad line is passed or not?
public class check {
public static void main(String[] args) {
if(args[0].length()!=0)
{
System.out.println("entered first if");
}
if(args[0].length()!=0 && args[1].length()!=0)
{
System.out.println("entered second if");
}
}
}
So in the above code if args[1] is not passed then i get java.lang.ArrayIndexOutOfBoundsException:
so how do i tackle this where i can check if second arguement is passed or not and if passed then enter it.
need assistance asap.
If you don't pass any argument then even in that case args gets initialized but without any item/element.
Try the following one, you will get the same effect:
public static void main(String[] args) throws InterruptedException {
String [] dummy= new String [] {};
if(dummy[0] == null)
{
System.out.println("Proper Usage is: java program filename");
System.exit(0);
}
}

Categories

Resources