443b86f240daa886bb2e4dbc98d3a6634090ed62
[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.cmd.OnapCommand;
26 import org.onap.cli.fw.conf.OnapCommandConfig;
27 import org.onap.cli.fw.conf.OnapCommandConstants;
28 import org.onap.cli.fw.error.OnapCommandException;
29 import org.onap.cli.fw.error.OnapCommandHelpFailed;
30 import org.onap.cli.fw.error.OnapCommandInvalidSample;
31 import org.onap.cli.fw.error.OnapCommandWarning;
32 import org.onap.cli.fw.input.OnapCommandParameter;
33 import org.onap.cli.fw.output.OnapCommandPrintDirection;
34 import org.onap.cli.fw.output.OnapCommandResult;
35 import org.onap.cli.fw.output.OnapCommandResultAttribute;
36 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
37 import org.onap.cli.fw.output.OnapCommandResultType;
38 import org.onap.cli.fw.registrar.OnapCommandRegistrar;
39 import org.onap.cli.main.conf.OnapCliConstants;
40 import org.onap.cli.main.interactive.StringCompleter;
41 import org.onap.cli.main.utils.OnapCliArgsParser;
42 import org.onap.cli.sample.yaml.SampleYamlGenerator;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import jline.TerminalFactory;
47 import jline.console.ConsoleReader;
48
49 /**
50  * Oclip Command Line Interface (CLI).
51  *
52  */
53 public class OnapCli {
54
55     private static Logger LOG = LoggerFactory.getLogger(OnapCli.class);
56
57     private List<String> args = new ArrayList<>();
58
59     private String product = null;
60
61     private int exitCode = -1;
62
63     public OnapCli(String[] args) {
64         this.args = Arrays.asList(args);
65     }
66
67     public OnapCli(String product, String[] args) {
68         this(args);
69         this.product = product;
70     }
71
72     private void exitSuccessfully() {
73         this.exitCode = OnapCliConstants.EXIT_SUCCESS;
74     }
75
76     private void exitFailure() {
77         this.exitCode = OnapCliConstants.EXIT_FAILURE;
78     }
79
80     protected void print(String msg) {
81         System.out.println(msg);
82     }
83
84     private void print(Throwable throwable) {
85         this.print(throwable.getMessage());
86         LOG.error(throwable.getMessage(), throwable);
87     }
88
89     private String getShortOption(String opt) {
90         return OnapCommandParameter.printShortOption(opt);
91     }
92
93     private String getLongOption(String opt) {
94         return OnapCommandParameter.printLongOption(opt);
95     }
96
97     public int getExitCode() {
98         return this.exitCode;
99     }
100
101     /**
102      * Handles help. --help or -h
103      */
104     public void handleHelp() {
105         try {
106             if ((args.size() == 1) && (this.getLongOption(OnapCliConstants.PARAM_HELP_LOGN).equals(args.get(0))
107                         || this.getShortOption(OnapCliConstants.PARAM_HELP_SHORT).equals(args.get(0)))) {
108                 this.print(IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("oclip-readme.txt")));
109                 String help = OnapCommandRegistrar.getRegistrar().getHelp();
110                 this.print(help);
111                 this.exitSuccessfully();
112             }
113         } catch (Exception e) {
114             this.print(e);
115             this.exitFailure();
116         }
117     }
118
119     /**
120      * Handles version. --version or -v
121      */
122     public void handleVersion() {
123         try {
124             if ((args.size() == 1) && (this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG).equals(args.get(0))
125                     || this.getShortOption(OnapCliConstants.PARAM_VERSION_SHORT).equals(args.get(0)))) {
126                 String version = OnapCommandRegistrar.getRegistrar().getVersion();
127                 this.print(version);
128                 this.exitSuccessfully();
129             }
130         } catch (Exception e) {
131             this.print(e);
132             this.exitFailure();
133         }
134     }
135
136
137     /**
138      * Handles profile. --profile or -c
139      */
140     public void handleProfile() {
141         try {
142             if ((args.size() == 2) && (this.getLongOption(OnapCliConstants.PARAM_PROFILE_LONG).equals(args.get(0))
143                         || this.getShortOption(OnapCliConstants.PARAM_PROFILE_SHORT).equals(args.get(0)))) {
144
145                 OnapCommandRegistrar.getRegistrar().setProfile(args.get(1));
146                 //Make space of interactive mode
147                 this.args = new ArrayList<>();
148             }
149         } catch (Exception e) {
150             this.print(e);
151             this.exitFailure();
152         }
153     }
154
155     public static String getDirectiveHelp() throws OnapCommandHelpFailed {
156         OnapCommandResult help = new OnapCommandResult();
157         help.setType(OnapCommandResultType.TABLE);
158         help.setPrintDirection(OnapCommandPrintDirection.LANDSCAPE);
159
160         OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
161         attr.setName(OnapCommandConstants.NAME.toUpperCase());
162         attr.setDescription(OnapCommandConstants.DESCRIPTION);
163         attr.setScope(OnapCommandResultAttributeScope.SHORT);
164         help.getRecords().add(attr);
165
166         OnapCommandResultAttribute attrDesc = new OnapCommandResultAttribute();
167         attrDesc.setName(OnapCommandConstants.DESCRIPTION.toUpperCase());
168         attrDesc.setDescription(OnapCommandConstants.DESCRIPTION);
169         attrDesc.setScope(OnapCommandResultAttributeScope.SHORT);
170         help.getRecords().add(attrDesc);
171
172         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_CLEAR);
173         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_CLEAR_MSG);
174
175         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_EXIT);
176         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_EXIT_MSG);
177
178         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_VERSION);
179         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_VERSION_MSG);
180
181         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_USE);
182         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_USE_MSG);
183
184         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_SET);
185         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_SET_MSG);
186
187         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_UNSET);
188         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_UNSET_MSG);
189
190         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_HELP);
191         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_HELP_MSG);
192
193         attr.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_PROFILE);
194         attrDesc.getValues().add(OnapCliConstants.PARAM_INTERACTIVE_PROFILE_MSG);
195         try {
196             return "\n\nDirectives:\n" + help.print();
197         } catch (OnapCommandException e) {
198             throw new OnapCommandHelpFailed(e);
199         }
200     }
201     /**
202      * Handles Interactive Mode.
203      */
204     public void handleInteractive() { // NOSONAR
205         if (args.isEmpty()) {
206             ConsoleReader console = null;
207             try {
208                 OnapCommandRegistrar.getRegistrar().setInteractiveMode(true);
209                 console = createConsoleReader();
210                 String line = null;
211
212                 while ((line = console.readLine()) != null) {
213                     line = line.trim();
214                     if (OnapCliConstants.PARAM_INTERACTIVE_EXIT.equalsIgnoreCase(line)) {
215                         break;
216                     } else if (OnapCliConstants.PARAM_INTERACTIVE_CLEAR.equalsIgnoreCase(line)) {
217                         console.clearScreen();
218                         continue;
219                     }
220                     this.args = Arrays.asList(line.split(OnapCliConstants.PARAM_INTERACTIVE_ARG_SPLIT_PATTERN));
221
222                     if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_USE)) {
223                         if (args.size() == 1) {
224                             this.print("Please input the product version to use, supported versions: " +
225                                     OnapCommandRegistrar.getRegistrar().getAvailableProductVersions());
226                         } else {
227                             try {
228                                 OnapCommandRegistrar.getRegistrar().setEnabledProductVersion(args.get(1));
229                                 console.close();
230                                 console = createConsoleReader();
231                             } catch (OnapCommandException e) {
232                                 this.print(e);
233                             }
234                         }
235                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_HELP)) {
236                         try {
237                             this.print(OnapCommandRegistrar.getRegistrar().getHelpForEnabledProductVersion());
238                             this.print(this.getDirectiveHelp());
239                         } catch (OnapCommandException e) {
240                             this.print(e);
241                         }
242                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_VERSION)) {
243                         this.args = Arrays.asList(new String [] {this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG)});
244                         handleVersion();
245                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_PROFILE)) {
246                         if (args.size() == 1) {
247                             this.print("Please use it in the form of 'profile <profile-name>'");
248                         } else {
249                             this.args = Arrays.asList(new String [] {
250                                     this.getLongOption(OnapCliConstants.PARAM_PROFILE_LONG),
251                                     this.args.get(1)});
252                             handleProfile();
253                         }
254                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_SET)) {
255                         if (args.size() > 1) {
256                             String [] paramEntry = args.get(1).trim().split("=");
257                             if (paramEntry.length >= 2) {
258                                 OnapCommandRegistrar.getRegistrar().addParamCache(paramEntry[0].trim(), paramEntry[1].trim());
259                             } else {
260                                 this.print("Please use it in the form of 'set param-name=param-value'");
261                             }
262                         } else {
263                             this.print(OnapCommandRegistrar.getRegistrar().getParamCache().toString());
264                         }
265                     } else if (!args.isEmpty() && this.args.get(0).equals(OnapCliConstants.PARAM_INTERACTIVE_UNSET)) {
266                         if (args.size() > 1) {
267                             for (int i = 1; i <args.size(); i++) {
268                                 OnapCommandRegistrar.getRegistrar().removeParamCache(args.get(i));
269                             }
270                         }
271                     } else {
272                         if (args.size() == 1 && args.get(0).trim().isEmpty()) {
273                             //Ignore blanks // NOSONAR
274                             continue;
275                         }
276
277                         handleCommand();
278                     }
279                 }
280             } catch (IOException e) { // NOSONAR
281                 this.print("Failed to read console, " + e.getMessage());
282             } catch (OnapCommandException e) {
283                 this.print(e);
284                 this.exitFailure();
285             } finally {
286                 try {
287                     TerminalFactory.get().restore();
288                 } catch (Exception e) { // NOSONAR
289                 }
290                 if (console != null) {
291                     console.close();
292                 }
293                 this.exitSuccessfully();
294             }
295         }
296     }
297
298     /**
299      * Creates console reader object.
300      *
301      * @return ConsoleReader
302      * @throws IOException
303      *             exception
304      */
305     private ConsoleReader createConsoleReader() throws IOException {
306         try(ConsoleReader console = new ConsoleReader()){
307             try {
308                 StringCompleter strCompleter = new StringCompleter(OnapCommandRegistrar.getRegistrar().listCommandsForEnabledProductVersion());
309                 strCompleter.add(OnapCliConstants.PARAM_INTERACTIVE_EXIT,
310                         OnapCliConstants.PARAM_INTERACTIVE_CLEAR,
311                         OnapCliConstants.PARAM_INTERACTIVE_USE,
312                         OnapCliConstants.PARAM_INTERACTIVE_HELP,
313                         OnapCliConstants.PARAM_INTERACTIVE_VERSION,
314                         OnapCliConstants.PARAM_INTERACTIVE_SET,
315                         OnapCliConstants.PARAM_INTERACTIVE_UNSET,
316                         OnapCliConstants.PARAM_INTERACTIVE_PROFILE);
317                 console.addCompleter(strCompleter);
318                 console.setPrompt(OnapCliConstants.PARAM_INTERACTIVE_PROMPT + ":" + OnapCommandRegistrar.getRegistrar().getEnabledProductVersion() + ">");
319             } catch (OnapCommandException e) { // NOSONAR
320                 this.print("Failed to load oclip commands," + e.getMessage());
321             }
322             return console;
323         }
324     }
325
326     /**
327      * Handles command.
328      */
329     public void handleCommand() {
330         OnapCommand cmd;
331         if (!args.isEmpty()) {
332             try {
333                 if (this.product != null) {
334                     cmd = OnapCommandRegistrar.getRegistrar().get(args.get(0), this.product);
335                 } else {
336                     cmd = OnapCommandRegistrar.getRegistrar().get(args.get(0));
337                 }
338             } catch (Exception e) {
339                 this.print(e);
340                 this.exitFailure();
341                 return;
342             }
343             try {
344                 // check for help or version
345                 if (args.size() == 2) {
346                     if (this.getLongOption(OnapCliConstants.PARAM_HELP_LOGN).equals(args.get(1))
347                             || this.getShortOption(OnapCliConstants.PARAM_HELP_SHORT).equals(args.get(1))) {
348                         String help = cmd.printHelp();
349                         this.print(help);
350                         this.exitSuccessfully();
351                         return;
352                     } else if (this.getLongOption(OnapCliConstants.PARAM_VERSION_LONG).equals(args.get(1))
353                             || this.getShortOption(OnapCliConstants.PARAM_VERSION_SHORT).equals(args.get(1))) {
354                         String version = cmd.printVersion();
355                         this.print(version);
356                         this.exitSuccessfully();
357                         return;
358                     }
359                 }
360
361                 for (OnapCommandParameter param: cmd.getParameters()) {
362                     if (OnapCommandRegistrar.getRegistrar().getParamCache().containsKey(
363                             cmd.getInfo().getService() + ":" + param.getLongOption())) {
364                         param.setValue(OnapCommandRegistrar.getRegistrar().getParamCache().get(
365                                 cmd.getInfo().getService() + ":" + param.getLongOption()));
366                     } else if (OnapCommandRegistrar.getRegistrar().getParamCache().containsKey(param.getLongOption())) {
367                         param.setValue(OnapCommandRegistrar.getRegistrar().getParamCache().get(param.getLongOption()));
368                     }
369                 }
370
371                 OnapCliArgsParser.populateParams(cmd.getParameters(), args);
372                 OnapCommandResult result = cmd.execute();
373
374                 this.print(result.getDebugInfo());
375                 this.print(result.print());
376                 this.exitSuccessfully();
377
378                 generateSmapleYaml(cmd);
379             } catch (OnapCommandWarning w) {
380                 this.print(w);
381                 this.print(cmd.getResult().getDebugInfo());
382                 this.exitSuccessfully();
383             } catch (Exception e) {
384                 this.print(e);
385                 this.print(cmd.getResult().getDebugInfo());
386                 this.exitFailure();
387             }
388         }
389     }
390
391     private void generateSmapleYaml(OnapCommand cmd) throws OnapCommandException {
392         if (Boolean.parseBoolean(OnapCommandConfig.getPropertyValue(OnapCommandConstants.SAMPLE_GEN_ENABLED)) && this.getExitCode() == OnapCliConstants.EXIT_SUCCESS) {
393             try {
394                 SampleYamlGenerator.generateSampleYaml(args, cmd.getResult().print(),
395                         OnapCommandRegistrar.getRegistrar().getEnabledProductVersion(),
396                         OnapCommandConfig.getPropertyValue(OnapCommandConstants.SAMPLE_GEN_TARGET_FOLDER) + "/" + cmd.getSchemaName().replaceAll(".yaml", "") + "-sample.yaml",
397                         cmd.getResult().isDebug());
398             } catch (IOException error) {
399                 throw new OnapCommandInvalidSample(args.get(0), error);
400             }
401         }
402     }
403
404     /**
405      * Handles all client input.
406      */
407     public void handle() {
408         this.handleHelp();
409
410         if (this.exitCode == -1) {
411             this.handleVersion();
412         }
413
414         if (this.exitCode == -1) {
415             this.handleProfile();
416         }
417
418         if (this.exitCode == -1) {
419             this.handleInteractive();
420         }
421
422         if (this.exitCode == -1) {
423             this.handleCommand();
424         }
425     }
426
427     /**
428      * Main method.
429      *
430      * @param args
431      *            array
432      */
433     public static void main(String[] args) {
434         OnapCli cli = new OnapCli(args);
435         cli.handle();
436         System.exit(cli.getExitCode());
437     }
438
439 }