APEX standalone support for ToscaPolicy format
[policy/apex-pdp.git] / services / services-engine / src / main / java / org / onap / policy / apex / service / engine / main / ApexCommandLineArguments.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modification Copyright (C) 2020 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.service.engine.main;
23
24 import java.io.File;
25 import java.io.PrintWriter;
26 import java.io.StringWriter;
27 import java.net.URL;
28 import java.util.Arrays;
29 import lombok.Getter;
30 import lombok.Setter;
31 import org.apache.commons.cli.CommandLine;
32 import org.apache.commons.cli.DefaultParser;
33 import org.apache.commons.cli.HelpFormatter;
34 import org.apache.commons.cli.Option;
35 import org.apache.commons.cli.Options;
36 import org.apache.commons.cli.ParseException;
37 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
38 import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
39 import org.onap.policy.common.utils.resources.ResourceUtils;
40 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
41
42 /**
43  * This class reads and handles command line parameters for the Apex main
44  * program.
45  *
46  * @author Liam Fallon (liam.fallon@ericsson.com)
47  */
48 public class ApexCommandLineArguments {
49     // A system property holding the root directory for relative paths in the
50     // configuration file
51     public static final String APEX_RELATIVE_FILE_ROOT = "APEX_RELATIVE_FILE_ROOT";
52
53     // Recurring string constants
54     private static final String FILE_PREAMBLE = " file \"";
55     private static final String RELATIVE_FILE_ROOT = "relative file root \"";
56     private static final int HELP_LINE_LENGTH = 120;
57
58     // Apache Commons CLI options
59     private final Options options;
60
61     @Getter
62     @Setter
63     private String toscaPolicyFilePath = null;
64     private String relativeFileRoot = null;
65
66     /**
67      * Construct the options for the CLI editor.
68      */
69     public ApexCommandLineArguments() {
70         //@formatter:off
71         options = new Options();
72         options.addOption(Option.builder("h")
73                 .longOpt("help")
74                 .desc("outputs the usage of this command")
75                 .required(false)
76                 .type(Boolean.class)
77                 .build());
78         options.addOption(Option.builder("v")
79                         .longOpt("version")
80                         .desc("outputs the version of Apex")
81                         .required(false)
82                         .type(Boolean.class)
83                         .build());
84         options.addOption(Option.builder("rfr")
85                         .longOpt("relative-file-root")
86                         .desc("the root file path for relative file paths specified in the Apex configuration file, "
87                                         + "defaults to the current directory from where Apex is executed")
88                         .hasArg()
89                         .argName(APEX_RELATIVE_FILE_ROOT)
90                         .required(false)
91                         .type(String.class)
92                         .build());
93         options.addOption(Option.builder("p").longOpt("tosca-policy-file")
94             .desc("the full path to the ToscaPolicy file to use.").hasArg().argName("TOSCA_POLICY_FILE")
95             .required(false)
96             .type(String.class).build());
97         //@formatter:on
98     }
99
100     /**
101      * Construct the options for the CLI editor and parse in the given arguments.
102      *
103      * @param args The command line arguments
104      */
105     public ApexCommandLineArguments(final String[] args) {
106         // Set up the options with the default constructor
107         this();
108
109         // Parse the arguments
110         try {
111             parse(args);
112         } catch (final ApexException e) {
113             throw new ApexRuntimeException("parse error on Apex parameters", e);
114         }
115     }
116
117     /**
118      * Parse the command line options.
119      *
120      * @param args The command line arguments
121      * @return a string with a message for help and version, or null if there is no
122      *         message
123      * @throws ApexException on command argument errors
124      */
125     public String parse(final String[] args) throws ApexException {
126         // Clear all our arguments
127         setToscaPolicyFilePath(null);
128         CommandLine commandLine = null;
129         try {
130             commandLine = new DefaultParser().parse(options, args);
131         } catch (final ParseException e) {
132             throw new ApexException("invalid command line arguments specified : " + e.getMessage());
133         }
134
135         // Arguments left over after Commons CLI does its stuff
136         final String[] remainingArgs = commandLine.getArgs();
137
138         if (remainingArgs.length > 0 && commandLine.hasOption('p') || remainingArgs.length > 1) {
139             throw new ApexException("too many command line arguments specified : " + Arrays.toString(args));
140         }
141
142         if (remainingArgs.length == 1) {
143             toscaPolicyFilePath = remainingArgs[0];
144         }
145
146         if (commandLine.hasOption('h')) {
147             return help(ApexMain.class.getName());
148         }
149
150         if (commandLine.hasOption('v')) {
151             return version();
152         }
153
154         if (commandLine.hasOption("rfr")) {
155             setRelativeFileRoot(commandLine.getOptionValue("rfr"));
156         } else {
157             setRelativeFileRoot(null);
158         }
159
160         if (commandLine.hasOption('p')) {
161             toscaPolicyFilePath = commandLine.getOptionValue('p');
162         }
163         return null;
164     }
165
166     /**
167      * Validate the command line options.
168      *
169      * @throws ApexException on command argument validation errors
170      */
171     public void validate() throws ApexException {
172         validateReadableFile("Tosca Policy", toscaPolicyFilePath);
173         validateRelativeFileRoot();
174     }
175
176     /**
177      * Print version information for Apex.
178      *
179      * @return the version string
180      */
181     public String version() {
182         return ResourceUtils.getResourceAsString("version.txt");
183     }
184
185     /**
186      * Print help information for Apex.
187      *
188      * @param mainClassName the main class name
189      * @return the help string
190      */
191     public String help(final String mainClassName) {
192         final StringWriter stringWriter = new StringWriter();
193         final PrintWriter stringPrintWriter = new PrintWriter(stringWriter);
194
195         new HelpFormatter().printHelp(stringPrintWriter, HELP_LINE_LENGTH, mainClassName + " [options...]", "options",
196             options, 0, 0, "");
197
198         return stringWriter.toString();
199     }
200
201     /**
202      * Gets the root file path for relative file paths in the configuration file.
203      *
204      * @return the root file path
205      */
206     public String getRelativeFileRoot() {
207         return relativeFileRoot;
208     }
209
210
211     /**
212      * Sets the root file path for relative file paths in the configuration file.
213      *
214      * @param relativeFileRoot the configuration file path
215      */
216     public void setRelativeFileRoot(final String relativeFileRoot) {
217         String relativeFileRootValue = relativeFileRoot;
218
219         if (!ParameterValidationUtils.validateStringParameter(relativeFileRoot)) {
220             relativeFileRootValue = System.getProperty(APEX_RELATIVE_FILE_ROOT);
221         }
222
223         if (!ParameterValidationUtils.validateStringParameter(relativeFileRootValue)) {
224             relativeFileRootValue = System.getProperty("user.dir");
225         } else if (!(new File(relativeFileRootValue).isAbsolute())) {
226             relativeFileRootValue = System.getProperty("user.dir") + File.separator + relativeFileRootValue;
227         }
228
229         this.relativeFileRoot = relativeFileRootValue;
230         System.setProperty(APEX_RELATIVE_FILE_ROOT, relativeFileRootValue);
231     }
232
233     /**
234      * Validate readable file.
235      *
236      * @param fileTag  the file tag
237      * @param fileName the file name
238      * @throws ApexException the apex exception
239      */
240     private void validateReadableFile(final String fileTag, final String fileName) throws ApexException {
241         if (fileName == null || fileName.length() == 0) {
242             throw new ApexException(fileTag + " file was not specified as an argument");
243         }
244
245         // The file name can refer to a resource on the local file system or on the
246         // class path
247         final URL fileUrl = ResourceUtils.getUrl4Resource(fileName);
248         if (fileUrl == null) {
249             throw new ApexException(fileTag + FILE_PREAMBLE + fileName + "\" does not exist");
250         }
251
252         final File theFile = new File(fileUrl.getPath());
253         if (!theFile.exists()) {
254             throw new ApexException(fileTag + FILE_PREAMBLE + fileName + "\" does not exist");
255         }
256         if (!theFile.isFile()) {
257             throw new ApexException(fileTag + FILE_PREAMBLE + fileName + "\" is not a normal file");
258         }
259         if (!theFile.canRead()) {
260             throw new ApexException(fileTag + FILE_PREAMBLE + fileName + "\" is ureadable");
261         }
262     }
263
264     /**
265      * Validate the relative file root.
266      */
267     private void validateRelativeFileRoot() throws ApexException {
268         File relativeFileRootPath = new File(relativeFileRoot);
269         if (!relativeFileRootPath.isDirectory()) {
270             throw new ApexException(RELATIVE_FILE_ROOT + relativeFileRoot + "\" does not exist or is not a directory");
271         }
272
273         if (!relativeFileRootPath.canRead()) {
274             throw new ApexException(RELATIVE_FILE_ROOT + relativeFileRoot + "\" is not a readable directory");
275         }
276
277         if (!relativeFileRootPath.canExecute()) {
278             throw new ApexException(RELATIVE_FILE_ROOT + relativeFileRoot + "\" is not an executable directory");
279         }
280     }
281
282 }