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