I built a random password generator in Java which is meant to be run from the command line. It accepts options for:
- Length
- Upper case letters
- Lower case letters
- Special characters
- Numbers
The project is on BitBucket.
Example program execution :
java -jar program.jar -length 12 -number -upper -lower -special
This generates a 12 character long password with upper and lower case letters, numbers, and special characters.
What I think :
- I find my Parser class to be quite messy. It would be hard to add a new parameter with different properties. How would you do it?
Parser.java
package passManager;
import java.util.ArrayList;
import java.util.Arrays;
public class Parser {
public static ArrayList<String> makeArgList(String args[]) {
ArrayList<String> argList = new ArrayList<String>();
boolean allArgsValid = true;
// Checks if each arg is valid
for (int i = 0; i < args.length && allArgsValid; i++) {
// If it starts with - and is not in the list of parameters, bad
if (args[i].startsWith("-") && !isInArgumentsList(args[i], Constants.VALID_ARGS)) {
System.out.println("Invalid parameter: " + args[i] + ". Exiting.");
allArgsValid = false;
// If it's not a parameter and it isn't a number, bad
} else if (!isInArgumentsList(args[i], Constants.VALID_ARGS) && !args[i].matches("^\\d+$")) {
System.out.println("Invalid parameter: " + args[i] + ". Exiting.");
allArgsValid = false;
// Verify the length parameter
} else if (args[i].equals("-length")) {
// If length is the only parameter (-length or -length 5 only is
// bad)
if (i == 0 && (i + 1 == args.length || i + 2 == args.length)) {
System.out.println("Length cannot be the only parameter. Exiting.");
allArgsValid = false;
// If what comes after -length is 0 or not a number
} else if (!args[i + 1].matches("^\\d+$")) {
System.out.println("Length must be a number. Exiting.");
allArgsValid = false;
}
// If it starts with a number
} else if (args[0].matches("^\\d+$")) {
System.out.println("First argument cannot be number: " + args[i] + ". Exiting.");
allArgsValid = false;
// If it's a lone number
} else if (args[i].matches("^\\d+$") && !args[i - 1].equals("-length")) {
System.out.println("Invalid parameter: " + args[i] + ". Exiting.");
allArgsValid = false;
}
}
// Check that there must be a length argument, and at least another
// arg.
if (!Arrays.asList(args).contains("-length")) {
if (args.length == 0) {
System.out.println("Length and one other parameter are needed. Exiting.");
allArgsValid = false;
} else {
System.out.println("Length is needed. Exiting.");
allArgsValid = false;
}
}
// If every arg was valid, then we can add all of them to the final list
if (allArgsValid) {
for (int i = 0; i < args.length; i++) {
String cleanedElement = args[i].toString().replace("-", "");
argList.add(cleanedElement);
}
return argList;
}
return null; // All args were not valid
}
private static boolean isInArgumentsList(String letter, String valid_args[]) {
boolean valid = false;
for (int i = 0; i < valid_args.length; i++) {
if (letter.equals(valid_args[i])) {
valid = true;
}
}
return valid;
}
}
Main.java
public class Main {
public static void main(String args[]) {
ArrayList<String> argList = new ArrayList<String>();
argList = Parser.makeArgList(args);
if (!(argList == null)) {
System.out.println("\n+ Password Generated with the Following Attributes : ");
for (int i = 0; i < argList.size(); i++) {
System.out.println(". " + argList.get(i));
}
System.out.println("\n+ Your Generated Password is : ");
System.out.println(Generator.generatePassword(argList));
}
}
Generator.java
package passManager;
import java.util.ArrayList;
import java.util.Random;
public class Generator {
private static int length = 0;
private static StringBuilder WORKING_SET = new StringBuilder();
private static Random random = new Random();
public static String generatePassword(ArrayList<String> argList) {
StringBuilder tempPassword = new StringBuilder();
String finalStringPassword;
makeWorkingSet(argList);
// TODO bug when only arg is length
for (int i = 0; i < length; i++) {
int randomPosition = random.nextInt(WORKING_SET.length());
tempPassword.append(WORKING_SET.charAt(randomPosition));
}
finalStringPassword = tempPassword.toString();
return finalStringPassword;
}
private static void makeWorkingSet(ArrayList<String> argList) {
for (int i = 0; i < argList.size(); i++) {
switch (argList.get(i)) {
case "length":
length = Integer.parseInt(argList.get(i + 1));
break;
case "upper":
WORKING_SET.append(Constants.UPPERLETTERS);
break;
case "lower":
WORKING_SET.append(Constants.LOWERLETTERS);
break;
case "special":
WORKING_SET.append(Constants.SPECIAL);
break;
case "number":
WORKING_SET.append(Constants.DIGITS);
break;
}
}
}
}
Constants.java
package passManager;
public interface Constants {
final String[] VALID_ARGS = { "-length", "-special", "-lower", "-upper", "-number" };
final String LOWERLETTERS = "abcdefghijklmnopqrstuvwxyz";
final String UPPERLETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final String DIGITS = "0123456789";
final String SPECIAL = "!@#@$%^&*()";
}