e33e54ac4486a5790ccc06897f47eb5f7550c3b7
[cli.git] / main / src / main / java / org / onap / cli / main / OnapCli.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.cli.main;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.List;
23
24 import org.apache.commons.io.IOUtils;
25 import org.onap.cli.fw.OnapCommand;
26 import org.onap.cli.fw.OnapCommandRegistrar;
27 import org.onap.cli.fw.conf.Constants;
28 import org.onap.cli.fw.error.OnapCommandException;
29 import org.onap.cli.fw.error.OnapCommandHelpFailed;
30 import org.onap.cli.fw.error.OnapCommandWarning;
31 import org.onap.cli.fw.input.OnapCommandParameter;
32 import org.onap.cli.fw.output.OnapCommandResult;
33 import org.onap.cli.fw.output.OnapCommandResultAttribute;
34 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
35 import org.onap.cli.fw.output.PrintDirection;
36 import org.onap.cli.fw.output.ResultType;
37 import org.onap.cli.main.conf.OnapCliConstants;
38 import org.onap.cli.main.interactive.StringCompleter;
39 import org.onap.cli.main.utils.OnapCliUtils;
40
41 import jline.TerminalFactory;
42 import jline.console.ConsoleReader;
43
44 /**
45  * Onap Command Line Interface (CLI).
46  *
47  */
48 public class OnapCli {
49
50     private List<String> args = new ArrayList<>();
51
52     private int exitCode = -1;
53
54     public OnapCli(String[] args) {
55         this.args = Arrays.asList(args);
56     }
57
58     private void exitSuccessfully() {
59         this.exitCode = OnapCliConstants.EXIT_SUCCESS;
60     }
61
62     private void exitFailure() {
63         this.exitCode = OnapCliConstants.EXIT_FAILURE;
64     }
65
66     private void print(String msg) {
67         System.out.println(msg);
68     }
69
70     private void print(Throwable throwable) {
71         System.out.println(throwable.getMessage());
72         try {
73             if (OnapCommandRegistrar.getRegistrar().isDevMode()) {
74                 throwable.printStackTrace();  // NOSONAR
75             }
76         } catch (OnapCommandException e) {
77             this.print(e.getCause());
78         }
79     }
80
81     private String getShortOption(String opt) {
82         return OnapCommandParameter.printShortOption(opt);
83     }
84
85     private String getLongOption(String opt) {
86         return OnapCommandParameter.printLongOption(opt);
87     }
88
89     public int getExitCode() {
90         return this.exitCode;
91     }
92
93     /**
94      * Handles help. --help or -h
95      */
96     public void handleHelp() {
97         try {
98             if ((args.size() == 1) && (this.getLongOption(OnapCliConstants.PARAM_HELP_LOGN).equals(args.get(0))
99                         || this.getShortOption(OnapCliConstants.PARAM_HELP_SHORT).equals(args.get(0)))) {
100                 this.print(IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("onap-readme.txt")));
101                 String help = OnapCommandRegistrar.getRegistrar().getHelp();
102                 this.print(help);
103                 this.exitSuccessfully();
104             }
105         } catch (Exception e) {
106             this.print(e);
107             this.exitFailure();
108         }
109     }
110
111     /**
112      * Handles version. --version or -v
113      */
114     public void handleVersion() {
115         try {
116             if ((args.size() == 1) && (this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG).equals(args.get(0))
117                     || this.getShortOption(OnapCliConstants.PARAM_VERSION_SHORT).equals(args.get(0)))) {
118                 String version = OnapCommandRegistrar.getRegistrar().getVersion();
119                 this.print(version);
120                 this.exitSuccessfully();
121             }
122         } catch (Exception e) {
123             this.print(e);
124             this.exitFailure();
125         }
126     }
127
128
129     /**
130      * Handles profile. --profile or -c
131      */
132     public void handleProfile() {
133         try {
134             if ((args.size() == 2) && (this.getLongOption(OnapCliConstants.PARAM_PROFILE_LONG).equals(args.get(0))
135                         || this.getShortOption(OnapCliConstants.PARAM_PROFILE_SHORT).equals(args.get(0)))) {
136
137                 OnapCommandRegistrar.getRegistrar().setProfile(args.get(1));
138                 //Make space of interactive mode
139                 this.args = new ArrayList<>();
140             }
141         } catch (Exception e) {
142             this.print(e);
143             this.exitFailure();
144         }
145     }
146
147     public static String getDirectiveHelp() throws OnapCommandHelpFailed {
148         OnapCommandResult help = new OnapCommandResult();
149         help.setType(ResultType.TABLE);
150         help.setPrintDirection(PrintDirection.LANDSCAPE);
151
152         OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
153         attr.setName(Constants.NAME.toUpperCase());
154         attr.setDescription(Constants.DESCRIPTION);
155         attr.setScope(OnapCommandResultAttributeScope.SHORT);
156         help.getRecords().add(attr);
157
158         OnapCommandResultAttribute attrDesc = new OnapCommandResultAttribute();
159         attrDesc.setName(Constants.DESCRIPTION.toUpperCase());
160         attrDesc.setDescription(Constants.DESCRIPTION);
161         attrDesc.setScope(OnapCommandResultAttributeScope.SHORT);
162         help.getRecords().add(attrDesc);
163
164         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_CLEAR);
165         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_CLEAR_MSG);
166
167         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_EXIT);
168         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_EXIT_MSG);
169
170         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_VERSION);
171         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_VERSION_MSG);
172
173         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_USE);
174         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_USE_MSG);
175
176         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_SET);
177         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_SET_MSG);
178
179         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_UNSET);
180         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_UNSET_MSG);
181
182         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_HELP);
183         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_HELP_MSG);
184
185         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_PROFILE);
186         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_PROFILE_MSG);
187         try {
188             return "\n\nDirectives:\n" + help.print();
189         } catch (OnapCommandException e) {
190             throw new OnapCommandHelpFailed(e);
191         }
192     }
193     /**
194      * Handles Interactive Mode.
195      */
196     public void handleInteractive() { // NOSONAR
197         if (args.isEmpty()) {
198             ConsoleReader console = null;
199             try {
200                 OnapCommandRegistrar.getRegistrar().setInteractiveMode(true);
201                 console = createConsoleReader();
202                 String line = null;
203
204                 while ((line = console.readLine()) != null) {
205                     if (OnapCliConstants.PARAM_INTERACTIVE_EXIT.equalsIgnoreCase(line)) {
206                         break;
207                     } else if (OnapCliConstants.PARAM_INTERACTIVE_CLEAR.equalsIgnoreCase(line)) {
208                         console.clearScreen();
209                         continue;
210                     }
211                     this.args = Arrays.asList(line.split(OnapCliConstants.PARAM_INTERACTIVE_ARG_SPLIT_PATTERN));
212
213                     if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_USE)) {
214                         if (args.size() == 1) {
215                             this.print("Please input the product version to use, supported versions: " +
216                                     OnapCommandRegistrar.getRegistrar().getAvailableProductVersions());
217                         } else {
218                             try {
219                                 OnapCommandRegistrar.getRegistrar().setEnabledProductVersion(args.get(1));
220                                 console.close();
221                                 console = createConsoleReader();
222                             } catch (OnapCommandException e) {
223                                 this.print(e);
224                             }
225                         }
226                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_HELP)) {
227                         try {
228                             this.print(OnapCommandRegistrar.getRegistrar().getHelpForEnabledProductVersion());
229                             this.print(this.getDirectiveHelp());
230                         } catch (OnapCommandException e) {
231                             this.print(e);
232                         }
233                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_VERSION)) {
234                         this.args = Arrays.asList(new String [] {this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG)});
235                         handleVersion();
236                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_PROFILE)) {
237                         if (args.size() == 1) {
238                             this.print("Please use it in the form of 'profile <profile-name>'");
239                         } else {
240                             this.args = Arrays.asList(new String [] {
241                                     this.getLongOption(OnapCliConstants.PARAM_PROFILE_LONG),
242                                     this.args.get(1)});
243                             handleProfile();
244                         }
245                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_SET)) {
246                         if (args.size() > 1) {
247                             String [] paramEntry = args.get(1).trim().split("=");
248                             if (paramEntry.length >= 2) {
249                                 OnapCommandRegistrar.getRegistrar().addParamCache(paramEntry[0].trim(), paramEntry[1].trim());
250                             } else {
251                                 this.print("Please use it in the form of 'set param-name=param-value'");
252                             }
253                         } else {
254                             this.print(OnapCommandRegistrar.getRegistrar().getParamCache().toString());
255                         }
256                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_UNSET)) {
257                         if (args.size() > 1) {
258                             for (int i = 1; i <args.size(); i++) {
259                                 OnapCommandRegistrar.getRegistrar().removeParamCache(args.get(i));
260                             }
261                         }
262                     } else {
263                         if (args.size() == 1 && args.get(0).trim().isEmpty()) {
264                             //Ignore blanks // NOSONAR
265                             continue;
266                         }
267
268                         handleCommand();
269                     }
270                 }
271             } catch (IOException e) { // NOSONAR
272                 this.print("Failed to read console, " + e.getMessage());
273             } catch (OnapCommandException e) {
274                 this.print(e);
275                 this.exitFailure();
276             } finally {
277                 try {
278                     TerminalFactory.get().restore();
279                 } catch (Exception e) { // NOSONAR
280                 }
281                 if (console != null) {
282                     console.close();
283                 }
284                 this.exitSuccessfully();
285             }
286         }
287     }
288
289     /**
290      * Creates console reader object.
291      *
292      * @return ConsoleReader
293      * @throws IOException
294      *             exception
295      */
296     private ConsoleReader createConsoleReader() throws IOException {
297         ConsoleReader console = new ConsoleReader();
298         try {
299             StringCompleter strCompleter = new StringCompleter(OnapCommandRegistrar.getRegistrar().listCommandsForEnabledProductVersion());
300             strCompleter.add(OnapCliConstants.PARAM_INTERACTIVE_EXIT,
301                     OnapCliConstants.PARAM_INTERACTIVE_CLEAR,
302                     OnapCliConstants.PARAM_INTERACTIVE_USE,
303                     OnapCliConstants.PARAM_INTERACTIVE_HELP,
304                     OnapCliConstants.PARAM_INTERACTIVE_VERSION,
305                     OnapCliConstants.PARAM_INTERACTIVE_SET,
306                     OnapCliConstants.PARAM_INTERACTIVE_UNSET,
307                     OnapCliConstants.PARAM_INTERACTIVE_PROFILE);
308             console.addCompleter(strCompleter);
309             console.setPrompt(OnapCliConstants.PARAM_INTERACTIVE_PROMPT);
310         } catch (OnapCommandException e) { // NOSONAR
311             this.print("Failed to load onap commands," + e.getMessage());
312         }
313
314         return console;
315     }
316
317     /**
318      * Handles command.
319      */
320     public void handleCommand() {
321         OnapCommand cmd;
322         if (!args.isEmpty()) {
323             try {
324                 cmd = OnapCommandRegistrar.getRegistrar().get(args.get(0));
325             } catch (Exception e) {
326                 this.print(e);
327                 this.exitFailure();
328                 return;
329             }
330             try {
331                 // check for help or version
332                 if (args.size() == 2) {
333                     if (this.getLongOption(OnapCliConstants.PARAM_HELP_LOGN).equals(args.get(1))
334                             || this.getShortOption(OnapCliConstants.PARAM_HELP_SHORT).equals(args.get(1))) {
335                         String help = cmd.printHelp();
336                         this.print(help);
337                         this.exitSuccessfully();
338                         return;
339                     } else if (this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG).equals(args.get(1))
340                             || this.getShortOption(OnapCliConstants.PARAM_VERSION_SHORT).equals(args.get(1))) {
341                         String version = cmd.printVersion();
342                         this.print(version);
343                         this.exitSuccessfully();
344                         return;
345                     }
346                 }
347
348                 for (OnapCommandParameter param: cmd.getParameters()) {
349                     if (OnapCommandRegistrar.getRegistrar().getParamCache().containsKey(
350                             cmd.getService().getName() + ":" + param.getLongOption())) {
351                         param.setValue(OnapCommandRegistrar.getRegistrar().getParamCache().get(
352                                 cmd.getService().getName() + ":" + param.getLongOption()));
353                     } else if (OnapCommandRegistrar.getRegistrar().getParamCache().containsKey(param.getLongOption())) {
354                         param.setValue(OnapCommandRegistrar.getRegistrar().getParamCache().get(param.getLongOption()));
355                     }
356                 }
357
358                 OnapCliUtils.populateParams(cmd.getParameters(), args);
359                 OnapCommandResult result = cmd.execute();
360                 this.print(result.getDebugInfo());
361                 this.print(result.print());
362                 this.exitSuccessfully();
363             } catch (Exception e) {
364                 this.print(cmd.getResult().getDebugInfo());
365                 if (e instanceof OnapCommandWarning) {
366                     this.exitSuccessfully();
367                 } else {
368                     this.print(e);
369                     this.exitFailure();
370                 }
371             }
372         }
373     }
374
375     /**
376      * Handles all client input.
377      */
378     public void handle() {
379         this.handleHelp();
380
381         if (this.exitCode == -1) {
382             this.handleVersion();
383         }
384
385         if (this.exitCode == -1) {
386             this.handleProfile();
387         }
388
389         if (this.exitCode == -1) {
390             this.handleInteractive();
391         }
392
393         if (this.exitCode == -1) {
394             this.handleCommand();
395         }
396     }
397
398     /**
399      * Main method.
400      *
401      * @param args
402      *            array
403      */
404     public static void main(String[] args) {
405         OnapCli cli = new OnapCli(args);
406         cli.handle();
407         System.exit(cli.getExitCode());
408     }
409
410 }