New AAA CLI standalone JAR to create users and set passwords
[aaa.git] / aaa-cli-jar / src / main / java / org / opendaylight / aaa / cli / jar / AbstractMain.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.aaa.cli.jar;
9
10 import static java.util.Arrays.asList;
11
12 import java.io.File;
13 import java.io.IOException;
14 import java.util.List;
15 import joptsimple.OptionParser;
16 import joptsimple.OptionSet;
17 import org.opendaylight.aaa.api.IDMStoreException;
18
19 /**
20  * Class with main() method and argument parsing etc.
21  * This class ONLY deals with argument parsing etc. and doesn't "do" anything,
22  * yet; this is intentional, and best for true unit test-ability of this class.
23  *
24  * @author Michael Vorburger
25  */
26 @SuppressWarnings("checkstyle:RegexpSingleLineJava") // allow System.out / System.err here..
27 public abstract class AbstractMain {
28
29     private static final String OPTION_HELP = "h";
30     private static final String OPTION_DB_DIR = "dbd";
31     private static final String OPTION_LIST_USERS = "l";
32     private static final String OPTION_CHANGE_USER = "cu";
33     private static final String OPTION_NEW_USER = "nu";
34     private static final String OPTION_ADMINS = "a";
35     private static final String OPTION_PASS = "p";
36     private static final String OPTION_DEBUG = "X";
37
38     private static final int RETURN_NOT_ENOUGH_ARGS = -1;
39     private static final int RETURN_ABORT_DUE_TO_EXCEPTION = -2;
40     private static final int RETURN_ARGUMENTS_MISMATCHED = -3;
41     protected static final int RETURN_ILLEGAL_ARGUMENTS = -4;
42     private static final int RETURN_ARGUMENTS_INCOMPATIBLE = -5;
43     private static final int RETURN_ARGUMENTS_MISSING = -6;
44
45     @SuppressWarnings({ "unchecked", "checkstyle:IllegalThrows", "checkstyle:IllegalCatch" })
46     public int parseArguments(String[] args) throws Exception {
47         boolean isInDebugLogging = false;
48         try {
49             OptionParser optionParser = getOptionParser();
50             OptionSet optionSet = optionParser.parse(args);
51             if (optionSet.has(OPTION_DEBUG)) {
52                 isInDebugLogging = true;
53             }
54             if (!optionSet.nonOptionArguments().isEmpty()) {
55                 unrecognizedOptions(optionSet.nonOptionArguments());
56             }
57             if (args.length == 0 || optionSet.has(OPTION_HELP) || !optionSet.nonOptionArguments().isEmpty()) {
58                 printHelp(optionParser);
59                 return RETURN_NOT_ENOUGH_ARGS;
60             }
61
62             if (optionSet.has(OPTION_CHANGE_USER) && optionSet.has(OPTION_NEW_USER)) {
63                 System.err.println("Can't use these options together: -" + OPTION_CHANGE_USER
64                         + ", -" + OPTION_NEW_USER);
65                 return RETURN_ARGUMENTS_INCOMPATIBLE;
66             } else if (optionSet.has(OPTION_PASS) && !optionSet.has(OPTION_CHANGE_USER)
67                     && !optionSet.has(OPTION_NEW_USER)) {
68                 System.err.println("If passwords are specificied, then must use one or the other of these options: -"
69                         + OPTION_CHANGE_USER + ", -" + OPTION_NEW_USER);
70                 return RETURN_ARGUMENTS_MISSING;
71             }
72
73             List<String> userNames;
74             if (optionSet.has(OPTION_CHANGE_USER)) {
75                 userNames = (List<String>) optionSet.valuesOf(OPTION_CHANGE_USER);
76             } else { // optionSet.has(OPTION_NEW_USER))
77                 userNames = (List<String>) optionSet.valuesOf(OPTION_NEW_USER);
78             }
79             List<String> passwords = (List<String>) optionSet.valuesOf(OPTION_PASS);
80             if (passwords.size() != userNames.size()) {
81                 System.err.println("Must give as many user names as passwords");
82                 return RETURN_ARGUMENTS_MISMATCHED;
83             }
84
85             File dbDirectory = (File) optionSet.valueOf(OPTION_DB_DIR);
86             setDbDirectory(dbDirectory);
87
88             if (optionSet.has(OPTION_LIST_USERS)) {
89                 listUsers();
90             }
91
92             if (optionSet.has(OPTION_CHANGE_USER)) {
93                 return resetPasswords(userNames, passwords);
94             } else { // optionSet.has(OPTION_NEW_USER))
95                 boolean areAdmins = optionSet.has(OPTION_ADMINS);
96                 return addNewUsers(userNames, passwords, areAdmins);
97             }
98
99         } catch (Throwable t) {
100             if (!isInDebugLogging) {
101                 System.err.println("Aborting due to " + t.getClass().getSimpleName()
102                         + " (use -X to see full stack trace): " + t.getMessage());
103                 return RETURN_ABORT_DUE_TO_EXCEPTION;
104             } else {
105                 // Java will print the full stack trace if we rethrow it
106                 throw t;
107             }
108         }
109     }
110
111     private OptionParser getOptionParser() {
112         return new OptionParser() { {
113                 acceptsAll(asList(OPTION_HELP, "?" ), "Show help").forHelp();
114                 accepts(OPTION_DB_DIR, "databaseDirectory").withRequiredArg().ofType(File.class)
115                         .defaultsTo(new File(".")).describedAs("path");
116                 acceptsAll(asList(OPTION_LIST_USERS, "listUsers"), "List all existing users");
117                 acceptsAll(asList(OPTION_NEW_USER, "newUser"), "New user to create").withRequiredArg();
118                 acceptsAll(asList(OPTION_CHANGE_USER, "changeUser"), "Existing user name to change password")
119                         .withRequiredArg();
120                 acceptsAll(asList(OPTION_PASS, "passwd"), "New password").withRequiredArg();
121                 accepts(OPTION_ADMINS, "New User(s) added with 'admin' role");
122                 // TODO accepts("v", "Display version information").forHelp();
123                 acceptsAll(asList(OPTION_DEBUG, "debug"), "Produce execution debug output");
124
125                 allowsUnrecognizedOptions();
126             }
127         };
128     }
129
130     protected void unrecognizedOptions(List<?> unrecognizedOptions) {
131         System.err.println("Unrecognized options: " + unrecognizedOptions);
132     }
133
134     protected void printHelp(OptionParser optionParser) throws IOException {
135         optionParser.printHelpOn(System.out);
136     }
137
138     // ----
139
140     protected abstract void setDbDirectory(File dbDirectory) throws IOException, IDMStoreException;
141
142     protected abstract void listUsers() throws IDMStoreException;
143
144     protected abstract int resetPasswords(List<String> userNames, List<String> passwords) throws IDMStoreException;
145
146     protected abstract int addNewUsers(List<String> userNames, List<String> passwords, boolean areAdmins) throws IDMStoreException;
147
148 }