diff options
author | Kanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com> | 2017-07-19 15:14:29 +0530 |
---|---|---|
committer | Kanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com> | 2017-07-19 15:31:19 +0530 |
commit | b610d2dbfa445e2ed8fd7f9976ae7a776666d630 (patch) | |
tree | 6d58385dc197aada4c6a832c922f04d0f4da61ad /framework/src/main/java/org/onap | |
parent | 20173579de1cd7d8f70fc2cdf17a4f9c0fc6e946 (diff) |
Add seed code from Open-Orelease-1.0.0
It migrated the code from Open-O into
onap namespace and adds the required
framework, main, deployment and some
sample plugins for msb.
CLI-7
CLI-8
CLI-11
Change-Id: I499e34237daccb971ef74bd10e50f50707baa4d3
Signed-off-by: Kanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com>
Diffstat (limited to 'framework/src/main/java/org/onap')
64 files changed, 7063 insertions, 0 deletions
diff --git a/framework/src/main/java/org/onap/cli/fw/OnapCommand.java b/framework/src/main/java/org/onap/cli/fw/OnapCommand.java new file mode 100644 index 00000000..d67538cc --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/OnapCommand.java @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw; + +import org.onap.cli.fw.ad.OnapAuthClient; +import org.onap.cli.fw.ad.OnapCredentials; +import org.onap.cli.fw.ad.OnapService; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandHelpFailed; +import org.onap.cli.fw.error.OnapCommandInvalidParameterType; +import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection; +import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope; +import org.onap.cli.fw.error.OnapCommandInvalidSchema; +import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion; +import org.onap.cli.fw.error.OnapCommandNotInitialized; +import org.onap.cli.fw.error.OnapCommandParameterNameConflict; +import org.onap.cli.fw.error.OnapCommandParameterOptionConflict; +import org.onap.cli.fw.error.OnapCommandRegistrationFailed; +import org.onap.cli.fw.error.OnapCommandSchemaNotFound; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.output.OnapCommandResult; +import org.onap.cli.fw.output.OnapCommandResultAttributeScope; +import org.onap.cli.fw.output.ResultType; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Onap Command. + * + */ +public abstract class OnapCommand { + + private String cmdDescription; + + private String cmdName; + + private String cmdSchemaName; + + private OnapService onapService = new OnapService(); + + private List<OnapCommandParameter> cmdParameters = new ArrayList<>(); + + private OnapCommandResult cmdResult = new OnapCommandResult(); + + protected OnapAuthClient authClient; + + protected boolean isInitialzied = false; + + public String getSchemaVersion() { + return Constants.ONAP_CMD_SCHEMA_VERSION_VALUE; + } + + /** + * Onap command description, defined by derived command. + */ + public String getDescription() { + return this.cmdDescription; + } + + public void setDescription(String description) { + this.cmdDescription = description; + } + + /* + * Onap command name like user-create, ns-list, etc , defined by derived command + */ + public String getName() { + return this.cmdName; + } + + public void setName(String name) { + this.cmdName = name; + } + + /* + * Onap service, this command uses to execute it. , defined by derived command + */ + public OnapService getService() { + return this.onapService; + } + + public void setService(OnapService service) { + this.onapService = service; + } + + public void setParameters(List<OnapCommandParameter> parameters) { + this.cmdParameters = parameters; + } + + /* + * Onap command input parameters, defined by derived command + */ + public List<OnapCommandParameter> getParameters() { + return this.cmdParameters; + } + + /* + * Onap command input parameters, defined by derived command + */ + public Map<String, OnapCommandParameter> getParametersMap() { + return OnapCommandUtils.getInputMap(this.getParameters()); + } + + /* + * Onap command output results, defined by derived command + */ + public OnapCommandResult getResult() { + return this.cmdResult; + } + + public void setResult(OnapCommandResult result) { + this.cmdResult = result; + } + + public String getSchemaName() { + return cmdSchemaName; + } + + protected void setSchemaName(String schemaName) { + this.cmdSchemaName = schemaName; + } + + /** + * Initialize this command from command schema. + * + * @throws OnapCommandRegistrationFailed + * Command Registration Exception + * @throws OnapCommandInvalidResultAttributeScope + * InvalidResultAttribute Exception + * @throws OnapCommandInvalidPrintDirection + * InvalidPrintDirection Exception + * @throws OnapCommandInvalidParameterType + * InvalidParameterType Exception + * @throws OnapCommandSchemaNotFound + * SchemaNotFound Exception + * @throws OnapCommandInvalidSchema + * InvalidSchema Exception + * @throws OnapCommandParameterOptionConflict + * ParameterOptionConflict Exception + * @throws OnapCommandParameterNameConflict + * ParameterNameConflict Exception + * @throws OnapCommandInvalidSchemaVersion + * InvalidSchemaVersion Exception + */ + public void initializeSchema(String schema) throws OnapCommandException { + this.setSchemaName(schema); + OnapCommandUtils.loadSchema(this, schema, true); + this.initializeProfileSchema(); + this.isInitialzied = true; + } + + /** + * Any additional profile based such as http/swagger schema could be initialized. + */ + protected void initializeProfileSchema() throws OnapCommandException { + + } + + /* + * Validate input parameters. This can be overridden in derived commands + */ + protected void validate() throws OnapCommandException { + for (OnapCommandParameter param : this.getParameters()) { + param.validate(); + } + } + + /** + * Onap command execute with given parameters on service. Before calling this method, its mandatory to set all + * parameters value. + * + * @throws OnapCommandException + * : General Command Exception + */ + public OnapCommandResult execute() throws OnapCommandException { + if (!this.isInitialzied) { + throw new OnapCommandNotInitialized(this.getClass().getName()); + } + + Map<String, OnapCommandParameter> paramMap = this.getParametersMap(); + + // -h or --help is always higher precedence !, user can set this value to get help message + if ("true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_HELP).getValue())) { + OnapCommandResult result = new OnapCommandResult(); + result.setType(ResultType.TEXT); + result.setOutput(this.printHelp()); + return result; + } + + // -v or --version is next higher precedence !, user can set this value to get help message + if ("true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_VERSION).getValue())) { + OnapCommandResult result = new OnapCommandResult(); + result.setType(ResultType.TEXT); + result.setOutput(this.printVersion()); + return result; + } + + // validate + this.validate(); + + // -f or --format + this.cmdResult.setType( + ResultType.get(paramMap.get(Constants.DEFAULT_PARAMETER_OUTPUT_FORMAT).getValue().toString())); + if ("true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_OUTPUT_ATTR_LONG).getValue())) { + this.cmdResult.setScope(OnapCommandResultAttributeScope.LONG); + } + // --no-title + if ("true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_OUTPUT_NO_TITLE).getValue())) { + this.cmdResult.setIncludeTitle(false); + } + + // --debug + if ("true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_DEBUG).getValue())) { + this.cmdResult.setDebug(true); + } + + try { + // login + OnapCredentials creds = OnapCommandUtils.fromParameters(this.getParameters()); + this.authClient = new OnapAuthClient(creds, this.getResult().isDebug()); + + if (!this.onapService.isNoAuth() + && !"true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_OUTPUT_NO_AUTH).getValue())) { + this.authClient.login(); + } + + // execute + this.run(); + + // logout + if (!this.onapService.isNoAuth() + && !"true".equals(paramMap.get(Constants.DEFAULT_PARAMETER_OUTPUT_NO_AUTH).getValue())) { + this.authClient.logout(); + } + + if (this.cmdResult.isDebug()) { + this.cmdResult.setDebugInfo(this.authClient.getDebugInfo()); + } + } catch (OnapCommandException e) { + if (this.cmdResult.isDebug()) { + this.cmdResult.setDebugInfo(this.authClient.getDebugInfo()); + } + throw e; + } + + return this.cmdResult; + } + + /* + * Each command implements run method to executing the command. + * + */ + protected abstract void run() throws OnapCommandException; + + /* + * Get my service base path (endpoint). + */ + protected String getBasePath() throws OnapCommandException { + return this.authClient.getServiceBasePath(this.getService()); + } + + protected String getAuthToken() { + return this.authClient.getAuthToken(); + } + + /** + * Returns the service service version it supports. + * + * @return version + */ + public String printVersion() { + return this.getService().toString(); + } + + /** + * Provides help message for this command. + * + * @return help message + * @throws OnapCommandHelpFailed + * Failed to execute Help command. + */ + public String printHelp() throws OnapCommandHelpFailed { + return OnapCommandUtils.help(this); + } + // (mrkanag) Add toString for all command, parameter, result, etc objects in JSON format +} diff --git a/framework/src/main/java/org/onap/cli/fw/OnapCommandRegistrar.java b/framework/src/main/java/org/onap/cli/fw/OnapCommandRegistrar.java new file mode 100644 index 00000000..567e0381 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/OnapCommandRegistrar.java @@ -0,0 +1,243 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw; + +import org.onap.cli.fw.cmd.OnapHttpCommand; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.conf.OnapCommandConfg; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandHelpFailed; +import org.onap.cli.fw.error.OnapCommandInvalidRegistration; +import org.onap.cli.fw.error.OnapCommandNotFound; +import org.onap.cli.fw.error.OnapCommandRegistrationFailed; +import org.onap.cli.fw.output.OnapCommandResult; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.output.OnapCommandResultAttributeScope; +import org.onap.cli.fw.output.PrintDirection; +import org.onap.cli.fw.output.ResultType; +import org.onap.cli.fw.utils.ExternalSchema; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Onap Command registrar provides a common place, where every command would get registered automatically when its + * loaded into JVM. + * + */ +public class OnapCommandRegistrar { + /* + * static { //Start the AOP for logging new OnapCommandLogger(); } + */ + private Map<String, Class<? extends OnapCommand>> registry = new HashMap<>(); + + private static OnapCommandRegistrar registrar = null; + + /** + * Register the command into registrar and throws OnapInvalidCommandRegistration for invalid command. + * + * @param name + * Command Name + * @param cmd + * Command Class + * @throws OnapCommandInvalidRegistration + * Invalid registration exception + */ + public void register(String name, Class<? extends OnapCommand> cmd) throws OnapCommandInvalidRegistration { + this.registry.put(name, cmd); + } + + /** + * Get global registrar. + * + * @throws OnapCommandException + * exception + */ + public static OnapCommandRegistrar getRegistrar() throws OnapCommandException { + if (registrar == null) { + registrar = new OnapCommandRegistrar(); + registrar.autoDiscover(); + registrar.autoDiscoverHttpSchemas(); + } + + return registrar; + } + + /** + * Get the list of discovered commands by registrar. + * + * @return set + */ + public Set<String> listCommands() { + return this.registry.keySet(); + } + + /** + * Returns map of command to schema. + * + * @return map + * @throws OnapCommandException + * exception + */ + public Map<String, String> getAllCommandToSchemaMap() throws OnapCommandException { + Map<String, String> map = new HashMap<>(); + List<ExternalSchema> schemas = OnapCommandUtils.findAllExternalSchemas(); + if (schemas != null) { + for (ExternalSchema schema : schemas) { + map.put(schema.getCmdName(), schema.getSchemaName()); + } + } + if (this.registry != null) { + for (String cmd : this.registry.keySet()) { + if (!map.containsKey(cmd) && registry.get(cmd) != null) { + map.put(cmd, this.getSchemaFileName(registry.get(cmd))); + } + } + } + + return map; + } + + /** + * Get the OnapCommand, which CLI main would use to find the command based on the command name. + * + * @param cmdName + * Name of command + * @return OnapCommand + * @throws OnapCommandException + * Exception + */ + public OnapCommand get(String cmdName) throws OnapCommandException { + OnapCommand cmd; + Class<? extends OnapCommand> cls = registry.get(cmdName); + if (cls == null) { + throw new OnapCommandNotFound(cmdName); + } + + try { + Constructor<?> constr = cls.getConstructor(); + cmd = (OnapCommand) constr.newInstance(); + + String schemaName; + if (cmd.getClass().equals(OnapHttpCommand.class)) { // NOSONAR + schemaName = OnapCommandUtils.loadExternalSchemaFromJson(cmdName).getSchemaName(); + } else { + schemaName = this.getSchemaFileName(cls); + } + cmd.initializeSchema(schemaName); + } catch (OnapCommandException | NoSuchMethodException | SecurityException | InstantiationException + | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new OnapCommandRegistrationFailed(cmdName, e); + } + + return cmd; + } + + private void autoDiscover() throws OnapCommandInvalidRegistration { + List<Class<OnapCommand>> cmds = OnapCommandUtils.findOnapCommands(); + + for (Class<OnapCommand> cmd : cmds) { + if (cmd.isAnnotationPresent(OnapCommandSchema.class)) { + OnapCommandSchema ano = cmd.getAnnotation(OnapCommandSchema.class); + this.register(ano.name(), cmd); + } + } + } + + private void autoDiscoverHttpSchemas() throws OnapCommandException { + List<ExternalSchema> schemas = OnapCommandUtils.loadExternalSchemasFromJson(); + for (ExternalSchema schema : schemas) { + this.register(schema.getCmdName(), OnapHttpCommand.class); + } + } + + private String getSchemaFileName(Class<? extends OnapCommand> cmd) { + OnapCommandSchema ano = (OnapCommandSchema) cmd.getAnnotation(OnapCommandSchema.class); + if (ano.schema().isEmpty()) { + return "onap-" + ano.name() + "-schema.yaml"; + } + return ano.schema(); + } + + /** + * Helps to find the Onap CLI version, could be used with --version or -v option. + * + * @return string + */ + public String getVersion() { + String version = this.getClass().getPackage().getImplementationVersion(); + if (version == null) { + version = OnapCommandConfg.getVersion(); + } + return version; + } + + /** + * Provides the help message in tabular format for all commands registered in this registrar. + * + * @return string + * @throws OnapCommandHelpFailed + * Help cmd failed + */ + public String getHelp() throws OnapCommandHelpFailed { + OnapCommandResult help = new OnapCommandResult(); + help.setType(ResultType.TABLE); + help.setPrintDirection(PrintDirection.LANDSCAPE); + + OnapCommandResultAttribute attr = new OnapCommandResultAttribute(); + attr.setName(Constants.NAME.toUpperCase()); + attr.setDescription(Constants.DESCRIPTION); + attr.setScope(OnapCommandResultAttributeScope.SHORT); + help.getRecords().add(attr); + + OnapCommandResultAttribute attrSrv = new OnapCommandResultAttribute(); + attrSrv.setName(Constants.SERVICE.toUpperCase()); + attrSrv.setDescription(Constants.SERVICE); + attrSrv.setScope(OnapCommandResultAttributeScope.SHORT); + help.getRecords().add(attrSrv); + + OnapCommandResultAttribute attrDesc = new OnapCommandResultAttribute(); + attrDesc.setName(Constants.DESCRIPTION.toUpperCase()); + attrDesc.setDescription(Constants.DESCRIPTION); + attrDesc.setScope(OnapCommandResultAttributeScope.SHORT); + help.getRecords().add(attrDesc); + + for (String cmdName : OnapCommandUtils.sort(this.listCommands())) { + OnapCommand cmd; + try { + cmd = this.get(cmdName); + } catch (OnapCommandException e) { + throw new OnapCommandHelpFailed(e); + } + + attr.getValues().add(cmd.getName()); + attrSrv.getValues().add(cmd.printVersion()); + attrDesc.getValues().add(cmd.getDescription()); + } + + try { + return "\n\nOnap sub-commands:\n" + help.print(); + } catch (OnapCommandException e) { + throw new OnapCommandHelpFailed(e); + } + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/OnapCommandSchema.java b/framework/src/main/java/org/onap/cli/fw/OnapCommandSchema.java new file mode 100644 index 00000000..853d3583 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/OnapCommandSchema.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Provide command name and schema file location, which is placed in the main resources folder (in classpath). It is + * recommended to keep the name for schema, in the form of onap-[command-name]-schema.yaml, considered this format as + * default if the schema declaration is missing for a command abc-create, schema file name could be + * abc-create-schema.yaml, corresponding command would like as below + * + * @OnapCommandSchema(name="abc-create", schema="onap-abc-create-schema.yaml") public class AbcCreate extends + * OnapCommand { ... } + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OnapCommandSchema { + /** + * Command name + * + * @return + */ + String name(); + + /** + * Schema file name placed under class path + * + * @return + */ + String schema() default ""; +} diff --git a/framework/src/main/java/org/onap/cli/fw/ad/OnapAuthClient.java b/framework/src/main/java/org/onap/cli/fw/ad/OnapAuthClient.java new file mode 100644 index 00000000..0150ee98 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/ad/OnapAuthClient.java @@ -0,0 +1,194 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.ad; + +import com.jayway.jsonpath.JsonPath; +import org.apache.http.HttpStatus; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.conf.OnapCommandConfg; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandExecutionFailed; +import org.onap.cli.fw.error.OnapCommandHttpFailure; +import org.onap.cli.fw.error.OnapCommandLoginFailed; +import org.onap.cli.fw.error.OnapCommandLogoutFailed; +import org.onap.cli.fw.error.OnapCommandServiceNotFound; +import org.onap.cli.fw.http.HttpInput; +import org.onap.cli.fw.http.HttpResult; +import org.onap.cli.fw.http.OnapHttpConnection; + +/** + * Onap Auth client helps to do login and logout. + * + */ +public class OnapAuthClient { + + /* + * Onap credentials + */ + private OnapHttpConnection http = null; + + private OnapCredentials creds = null; + + public OnapAuthClient(OnapCredentials creds, boolean debug) throws OnapCommandHttpFailure { + this.creds = creds; + this.http = new OnapHttpConnection(creds.getMsbUrl().startsWith("https"), debug); + } + + /** + * Login. + * + * @throws OnapCommandLoginFailed + * LoginFailed Exception + * @throws OnapCommandHttpFailure + * Http request failed + * @throws OnapCommandExecutionFailed + * cmd exec failed + * @throws OnapCommandServiceNotFound + * service not found + */ + public void login() throws OnapCommandException { + + // For development purpose, its introduced and is not supported for production + if (OnapCommandConfg.isAuthIgnored()) { + return; + } + + HttpInput input = new HttpInput().setUri(this.getAuthUrl() + "/tokens") + .setBody(String.format(Constants.TOKEN, creds.getUsername(), creds.getPassword())) + .setMethod("post"); + + HttpResult result; + try { + result = this.run(input); + } catch (OnapCommandHttpFailure e) { + throw new OnapCommandLoginFailed(e); + } + if (result.getStatus() != HttpStatus.SC_OK && result.getStatus() != HttpStatus.SC_CREATED) { + throw new OnapCommandLoginFailed(result.getBody(), result.getStatus()); + } + + if (OnapCommandConfg.isCookiesBasedAuth()) { + this.http.setAuthToken(result.getRespCookies().get(Constants.X_AUTH_TOKEN)); + } else { + this.http.setAuthToken(result.getRespHeaders().get(Constants.X_AUTH_TOKEN)); + } + } + + /** + * Logout. + * + * @throws OnapCommandExecutionFailed + * cmd exec failed + * @throws OnapCommandServiceNotFound + * service not found + * @throws OnapCommandLogoutFailed + * logout failed + * @throws OnapCommandHttpFailure + * exception + */ + public void logout() throws OnapCommandException { + // For development purpose, its introduced and is not supported for production + if (OnapCommandConfg.isAuthIgnored()) { + return; + } + + HttpInput input = new HttpInput().setUri(this.getAuthUrl() + "/tokens").setMethod("delete"); + + HttpResult result; + try { + result = this.run(input); + } catch (OnapCommandHttpFailure e) { + throw new OnapCommandLogoutFailed(e); + } + if (result.getStatus() != HttpStatus.SC_NO_CONTENT) { + throw new OnapCommandLogoutFailed(result.getStatus()); + } + + this.http.close(); + } + + /** + * Find given service base path. + * + * @param srv + * onap service + * @return string + * @throws OnapCommandExecutionFailed + * Cmd execution failed exception + * @throws OnapCommandServiceNotFound + * Service not found + * @throws OnapCommandHttpFailure + * http request failed + */ + public String getServiceBasePath(OnapService srv) throws OnapCommandException { + if (srv.getName().equals(Constants.MSB)) { + return this.getMsbUrl(); + } + + HttpInput input = new HttpInput().setUri(this.creds.getMsbUrl() + + String.format(Constants.MSB_SERVICE_URI, srv.getName(), srv.getVersion())); + HttpResult result = this.http.get(input); + + if (result.getStatus() == HttpStatus.SC_NOT_FOUND) { + throw new OnapCommandServiceNotFound(srv.toString()); + } + if (!result.isSuccess()) { + throw new OnapCommandExecutionFailed("Failed to retrive service " + srv.toString()); + } + + try { + return this.creds.getMsbUrl() + JsonPath.read(result.getBody(), "url"); + } catch (Exception e) { + throw new OnapCommandExecutionFailed(e, srv.toString()); + } + } + + private String getAuthUrl() throws OnapCommandException { + OnapService srv = new OnapService(); + srv.setName(Constants.AUTH_SERVICE); + srv.setVersion(Constants.AUTH_SERVICE_VERSION); + return this.getServiceBasePath(srv); + } + + private String getMsbUrl() { + return this.creds.getMsbUrl() + Constants.MSB_URI; + } + + public String getAuthToken() { + return this.http.getAuthToken(); + } + + public String getDebugInfo() { + return this.http.getDebugInfo(); + } + + /** + * Http call to auth service. + * + * @param input + * http input + * @return http result + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult run(HttpInput input) throws OnapCommandHttpFailure { + if (OnapCommandConfg.isCookiesBasedAuth()) { + input.getReqCookies().put(Constants.X_AUTH_TOKEN, http.getAuthToken()); + } + return this.http.request(input); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/ad/OnapCredentials.java b/framework/src/main/java/org/onap/cli/fw/ad/OnapCredentials.java new file mode 100644 index 00000000..7c3c3ac0 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/ad/OnapCredentials.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.ad; + +/** + * Onap Service credentials. + */ +public class OnapCredentials { + + /* + * Onap Service username. + */ + private String username; + + /* + * Onap Service password + */ + private String password; + + /* + * Onap Service msb-url + */ + private String msbUrl; + + /** + * Onap credentials with username and password. + * + * @param username + * user name + * @param password + * password + * @param msbUrl + * msb url + */ + public OnapCredentials(String username, String password, String msbUrl) { + super(); + this.username = username; + this.password = password; + this.msbUrl = msbUrl; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getMsbUrl() { + return msbUrl; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/ad/OnapService.java b/framework/src/main/java/org/onap/cli/fw/ad/OnapService.java new file mode 100644 index 00000000..16752f25 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/ad/OnapService.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.ad; + +/** + * Onap Service as reported in Onap MSB like msb v1 or /api/microservice/v1. + */ +public class OnapService { + /* + * Onap Service name like gso. + */ + private String serviceName; + + /* + * Onap Service API version like v1, v2, etc + */ + private String serviceVersion; + + private String basePath; + + private boolean noAuth = false; + + public boolean isNoAuth() { + return noAuth; + } + + public void setNoAuth(boolean noAuth) { + this.noAuth = noAuth; + } + + public String getName() { + return serviceName; + } + + public void setName(String name) { + this.serviceName = name; + } + + public String getVersion() { + return serviceVersion; + } + + public void setVersion(String version) { + this.serviceVersion = version; + } + + public String getBasePath() { + return basePath; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + @Override + public String toString() { + return this.getName() + " " + this.getVersion(); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/cmd/OnapHttpCommand.java b/framework/src/main/java/org/onap/cli/fw/cmd/OnapHttpCommand.java new file mode 100644 index 00000000..d5f51f00 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/cmd/OnapHttpCommand.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.cmd; + +import org.onap.cli.fw.OnapCommand; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandExecutionFailed; +import org.onap.cli.fw.http.HttpInput; +import org.onap.cli.fw.http.HttpResult; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Onap Command. + * + */ +public class OnapHttpCommand extends OnapCommand { + + private HttpInput input = new HttpInput(); + + private List<Integer> successStatusCodes = new ArrayList<>(); + + private Map<String, String> resultMap = new HashMap<>(); + + public void setInput(HttpInput input) { + this.input = input; + } + + @Override + public String getSchemaVersion() { + return Constants.ONAP_CMD_SCHEMA_VERSION_VALUE; + } + + public void setSuccessStatusCodes(List<Integer> successStatusCodes) { + this.successStatusCodes = successStatusCodes; + } + + public void setResultMap(Map<String, String> resultMap) { + this.resultMap = resultMap; + } + + public HttpInput getInput() { + return input; + } + + public List<Integer> getSuccessStatusCodes() { + return successStatusCodes; + } + + public Map<String, String> getResultMap() { + return resultMap; + } + + @Override + protected void initializeProfileSchema() throws OnapCommandException { + OnapCommandUtils.loadSchema(this, this.getSchemaName()); + } + + @Override + protected void run() throws OnapCommandException { + HttpInput httpInput = OnapCommandUtils.populateParameters(this.getParametersMap(), this.getInput()); + httpInput.setUri(this.authClient.getServiceBasePath(this.getService()) + httpInput.getUri()); + + HttpResult output = this.authClient.run(httpInput); + + this.getResult().setOutput(output); + if (!this.getSuccessStatusCodes().contains(output.getStatus())) { + throw new OnapCommandExecutionFailed(this.getName(), output.getBody(), output.getStatus()); + } + + Map<String, ArrayList<String>> results = OnapCommandUtils.populateOutputs(this.getResultMap(), output); + + for (OnapCommandResultAttribute attr : this.getResult().getRecords()) { + attr.setValues(results.get(attr.getName())); + } + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaRefreshCommand.java b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaRefreshCommand.java new file mode 100644 index 00000000..57432751 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaRefreshCommand.java @@ -0,0 +1,68 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.cmd; + +import org.onap.cli.fw.OnapCommand; +import org.onap.cli.fw.OnapCommandSchema; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.utils.ExternalSchema; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Refresh external schema. + * + */ +@OnapCommandSchema(name = "schema-refresh", schema = "schema-refresh.yaml") +public class OnapSchemaRefreshCommand extends OnapCommand { + + @Override + protected void run() throws OnapCommandException { + + List<ExternalSchema> schemas = OnapCommandUtils.findAllExternalSchemas(); + // Will override the existing json file + OnapCommandUtils.persist(schemas); + + List<String> slNumbers = new ArrayList<>(); + List<String> cmdNames = new ArrayList<>(); + List<String> cmdFiles = new ArrayList<>(); + List<String> versions = new ArrayList<>(); + + for (int i = 0; i < schemas.size(); i++) { + ExternalSchema schema = schemas.get(i); + slNumbers.add(String.valueOf(i + 1)); + cmdNames.add(schema.getCmdName()); + cmdFiles.add(schema.getSchemaName()); + versions.add(schema.getVersion()); + } + for (OnapCommandResultAttribute attribute : this.getResult().getRecords()) { + if ("sl-no".equals(attribute.getName())) { + attribute.setValues(slNumbers); + } else if ("command".equals(attribute.getName())) { + attribute.setValues(cmdNames); + } else if ("schema".equals(attribute.getName())) { + attribute.setValues(cmdFiles); + } else if ("version".equals(attribute.getName())) { + attribute.setValues(versions); + } + } + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaValidateCommand.java b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaValidateCommand.java new file mode 100644 index 00000000..a4d4e7d4 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSchemaValidateCommand.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.cmd; + +import org.onap.cli.fw.OnapCommand; +import org.onap.cli.fw.OnapCommandSchema; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.schema.SchemaValidate; +import org.onap.cli.fw.schema.SchemaValidator; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Validate schema command. + * + */ +@OnapCommandSchema(name = "schema-validate", schema = "schema-validate.yaml") +public class OnapSchemaValidateCommand extends OnapCommand { + + @Override + protected void run() throws OnapCommandException { + Map<String, OnapCommandParameter> paramMap = getParametersMap(); + OnapCommandParameter locationParam = paramMap.get("schema-location"); + String location = String.valueOf(locationParam.getValue()); + OnapCommandParameter interSchemaParam = paramMap.get("internal-schema"); + boolean isInternalSchema = Boolean.valueOf(String.valueOf(interSchemaParam.getValue())); + SchemaValidate schema; + if (isInternalSchema) { + location = location.substring(1); + schema = new SchemaValidator(location); + } else { + schema = new SchemaValidator(new File(location)); + } + + List<String> error = schema.validate(); + List<String> slNumber = new ArrayList<>(); + for (int i = 1; i <= error.size(); i++) { + slNumber.add(String.valueOf(i)); + } + this.getResult().getRecords().get(0).setValues(slNumber); + this.getResult().getRecords().get(1).setValues(error); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/cmd/OnapSwaggerCommand.java b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSwaggerCommand.java new file mode 100644 index 00000000..fa3e7d7e --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/cmd/OnapSwaggerCommand.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.cmd; + +import org.onap.cli.fw.OnapCommand; +import org.onap.cli.fw.error.OnapCommandClientInitialzationFailed; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandResultInitialzationFailed; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.run.OnapCommandExecutor; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +public abstract class OnapSwaggerCommand extends OnapCommand { + + + private OnapCommandExecutor cmdExecutor; + + public OnapCommandExecutor getExecutor() { + return cmdExecutor; + } + + public void setExecutor(OnapCommandExecutor executor) { + this.cmdExecutor = executor; + } + + /** + * Initialize the given ApiClient object with AUTH token and base path. + * + * @param client + * api client + * @throws OnapCommandClientInitialzationFailed + * client initialization failed + */ + protected <T> T initializeApiClient(T client) throws OnapCommandClientInitialzationFailed { + try { + Method basePath = client.getClass().getMethod("setBasePath", String.class); + basePath.invoke(client, this.getBasePath()); + + if (this.getAuthToken() != null) { + Method apiKey = client.getClass().getMethod("setApiKey", String.class); + apiKey.invoke(client, this.getAuthToken()); + } + return client; + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | OnapCommandException e) { + throw new OnapCommandClientInitialzationFailed(this.getName(), e); + } + } + + protected <T> void initializeResult(T obj) throws OnapCommandResultInitialzationFailed { + this.getResult().setOutput(obj); + if (obj instanceof List) { + this.initializeListResult((List) obj); + } else { + this.initializeRow(obj); + } + } + + private <T> void initializeRow(T obj) throws OnapCommandResultInitialzationFailed { + for (OnapCommandResultAttribute row : this.getResult().getRecords()) { + String methodName = OnapCommandUtils.formMethodNameFromAttributeName(row.getName(), "get"); + Method get; + try { + get = obj.getClass().getMethod(methodName); + row.getValues().add(get.invoke(obj).toString()); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + throw new OnapCommandResultInitialzationFailed(this.getName(), e); + } + } + } + + protected <T> void initializeListResult(List<T> rows) throws OnapCommandResultInitialzationFailed { + this.getResult().setOutput(rows); + for (T row : rows) { + this.initializeRow(row); + } + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/conf/Constants.java b/framework/src/main/java/org/onap/cli/fw/conf/Constants.java new file mode 100644 index 00000000..928cbc79 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/conf/Constants.java @@ -0,0 +1,160 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.conf; + +/** + * Constants. + * + */ +public class Constants { + + public static final String SSLCONTEST_TLS = "TLSV1.2"; + public static final String APPLICATION_JSON = "application/json"; + public static final String X_AUTH_TOKEN = "X-Auth-Token"; + + public static final String AUTH_SERVICE = "auth"; + public static final String AUTH_SERVICE_VERSION = "v1"; + public static final String TOKEN = "{\"userName\": \"%s\",\"password\": \"%s\"}"; + public static final String MSB_URI = "/api/microservices/v1"; + public static final String MSB_SERVICE_URI = MSB_URI + "/services/%s/version/%s"; + + public static final String MSB = "msb"; + + //http + public static final String URI = "uri"; + public static final String BODY = "body"; + public static final String MERHOD = "method"; + public static final String HEADERS = "headers"; + public static final String QUERIES = "queries"; + public static final String COOKIES = "cookies"; + + public static final String HTTP = "http"; + public static final String REQUEST = "request"; + public static final String SAMPLE_RESPONSE = "sample_response"; + public static final String SUCCESS_CODES = "success_codes"; + public static final String RESULT_MAP = "result_map"; + + //swagger + public static final String EXECUTOR = "exec"; + + public static final String API = "api"; + public static final String CLIENT = "client"; + public static final String ENTITY = "entity"; + public static final String METHOD = "method"; + public static final String EXCEPTION = "exception"; + + public static final String SCOPE = "scope"; + + public static final String ONAP_CMD_SCHEMA_VERSION_VALUE = "1.0"; + public static final String DESCRIPTION = "description"; + public static final String SERVICE = "service"; + public static final String PARAMETERS = "parameters"; + public static final String RESULTS = "results"; + + public static final String ONAP_CMD_SCHEMA_VERSION = "onap_cmd_schema_version"; + public static final String NAME = "name"; + public static final String VERSION = "version"; + public static final String BASE_PATH = "base_path"; + public static final String NO_AUTH = "no-auth"; + + public static final String SHORT_OPTION = "short_option"; + public static final String LONG_OPTION = "long_option"; + public static final String TYPE = "type"; + public static final String IS_OPTIONAL = "is_optional"; + public static final String DEFAULT_VALUE = "default_value"; + public static final String IS_SECURED = "is_secured"; + + public static final String DIRECTION = "direction"; + public static final String ATTRIBUTES = "attributes"; + + public static final String DEFAULT_PARAMETER_FILE_NAME = "default_input_parameters.yaml"; + + // Common parameters used across all commands. + public static final String DEAFULT_PARAMETER_USERNAME = "onap-username"; + public static final String DEAFULT_PARAMETER_PASS_WORD = "onap-password"; + public static final String DEAFULT_PARAMETER_MSB_URL = "msb-url"; + public static final String DEFAULT_PARAMETER_HELP = "help"; + public static final String DEFAULT_PARAMETER_VERSION = "version"; + public static final String DEFAULT_PARAMETER_DEBUG = "debug"; + public static final String DEFAULT_PARAMETER_OUTPUT_FORMAT = "format"; + public static final String DEFAULT_PARAMETER_OUTPUT_ATTR_LONG = "long"; + public static final String DEFAULT_PARAMETER_OUTPUT_NO_TITLE = "no-title"; + public static final String DEFAULT_PARAMETER_OUTPUT_NO_AUTH = "no-auth"; + + // Configuration properties + public static final String CONF = "onap.properties"; + public static final String ONAP_IGNORE_AUTH = "cli.ignore_auth"; + public static final String ONAP_CLI_VERSION = "cli.version"; + public static final String HTTP_API_KEY_USE_COOKIES = "http.api_key_use_cookies"; + public static final String HTTP_X_AUTH_TOKEN = "http.x_auth_token"; + + // Used while printing the column name during PORTRAIT mode print + public static final String PORTRAINT_COLUMN_NAME_PROPERTY = "property"; + public static final String PORTRAINT_COLUMN_NAME_VALUE = "value"; + + public static final String EXTERNAL_SCHEMA_DIRECTORY = "onap-cli-schema"; + public static final String EXTERNAL_YAML_PATTERN = "/**/*.yaml"; + public static final String EXTERNAL_JSON_PATTERN = "/**/*.json"; + public static final String EXTERNAL_SCHEMA_PATH_PATERN = EXTERNAL_SCHEMA_DIRECTORY + EXTERNAL_YAML_PATTERN; + public static final String EXTERNAL_DISCOVERY_DIRECTORY = "data"; + public static final String EXTERNAL_DISCOVERY_FILE = "external-schema.json"; + public static final String EXTERNAL_DISCOVERY_DIRECTORY_PATTERN = EXTERNAL_DISCOVERY_DIRECTORY + + EXTERNAL_JSON_PATTERN; + + public static final String PARAMETER_TYPE_JSON = "json"; + public static final String PARAMETER_TYPE_YAML = "yaml"; + public static final String PARAMETER_TYPE_STRING = "string"; + public static final String PARAMETER_TYPE_LONG = "long"; + public static final String PARAMETER_TYPE_URL = "url"; + public static final String PARAMETER_TYPE_BOOL = "bool"; + public static final String PARAMETER_TYPE_ARRAY = "array"; + public static final String PARAMETER_TYPE_BINARY = "binary"; + public static final String PARAMETER_TYPE_MAP = "map"; + + public static final String BOOLEAN_TRUE = "true"; + public static final String BOOLEAN_FALSE = "false"; + + public static final String DIRECTION_PORTRAIT = "portrait"; + public static final String DIRECTION_LANDSCAPE = "landscape"; + + public static final String RESULT_SCOPE_SHORT = "short"; + public static final String RESULT_SCOPE_LONG = "long"; + + public static final String POST = "post"; + public static final String GET = "get"; + public static final String DELETE = "delete"; + public static final String PUT = "put"; + public static final String HEAD = "delete"; + + public static final String DEFAULT_SCHEMA_FILE_NAME = "default_input_parameters.yaml"; + + // Error message + public static final String SCHEMA_FILE_EMPTY = "The schema file cann't be null or empty"; + public static final String SCHEMA_FILE_WRONG_EXTN = "Schema file should be '.yaml' extension"; + public static final String SCHEMA_FILE_NOT_EXIST = "Schema file doesn't exist"; + public static final String HTTP_SECTION_EMPTY = "Http Section cann't be null or empty"; + public static final String HTTP_BODY_SECTION_EMPTY = "http body section under 'request:' cann't be null or empty"; + public static final String HTTP_BODY_FAILED_PARSING = "The http body json is failed to parse"; + public static final String HTTP_BODY_JSON_EMPTY = "The http body json cann't be null or empty"; + public static final String HTTP_SUCCESS_CODE_INVALID = "Invalid http success code."; + public static final String HTTP_SAMPLE_RESPONSE_EMPTY = "Sample response cann't be null or empty"; + public static final String HTTP_SAMPLE_RESPONSE_FAILED_PARSING = "The http Sample response json is failed to parse."; + + private Constants() { + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/conf/OnapCommandConfg.java b/framework/src/main/java/org/onap/cli/fw/conf/OnapCommandConfg.java new file mode 100644 index 00000000..d5025e1b --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/conf/OnapCommandConfg.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.conf; + +import java.io.IOException; +import java.util.Properties; + +/** + * Onap command constants. + * + */ +public final class OnapCommandConfg { + + private static Properties prps = new Properties(); + + /** + * Private constructor. + */ + private OnapCommandConfg() { + + } + + static { + try { + prps.load(OnapCommandConfg.class.getClassLoader().getResourceAsStream(Constants.CONF)); + } catch (IOException e) { + throw new RuntimeException(e); // NOSONAR + } + } + + /** + * is auth service ignored. + * + * @return boolean + */ + public static boolean isAuthIgnored() { + if ("true".equals(prps.getProperty(Constants.ONAP_IGNORE_AUTH))) { + return true; + } + + return false; + } + + public static String getVersion() { + return prps.getProperty(Constants.ONAP_CLI_VERSION); + } + + /** + * checks if cookies based auth. + * + * @return boolean + */ + public static boolean isCookiesBasedAuth() { + if ("true".equals(prps.getProperty(Constants.HTTP_API_KEY_USE_COOKIES))) { + return true; + } + + return false; + } + + public static String getXAuthTokenName() { + return prps.getProperty(Constants.HTTP_X_AUTH_TOKEN, "X-Auth-Token"); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandClientInitialzationFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandClientInitialzationFailed.java new file mode 100644 index 00000000..be88d18a --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandClientInitialzationFailed.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command not registered in MSB. + * + */ +public class OnapCommandClientInitialzationFailed extends OnapCommandException { + + private static final long serialVersionUID = 8580121615330415000L; + private static final String ERROR_CODE = "0x0021"; + private static final String ERROR_MESSAGE1 = "API client for the command "; + private static final String ERROR_MESSAGE2 = " is failed, "; + + public OnapCommandClientInitialzationFailed(String cmd, String error) { + super(ERROR_CODE, ERROR_MESSAGE1 + cmd + ERROR_MESSAGE2 + error); + } + + public OnapCommandClientInitialzationFailed(String cmd, Throwable throwable) { + this(cmd, throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandDiscoveryFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandDiscoveryFailed.java new file mode 100644 index 00000000..582e4cfc --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandDiscoveryFailed.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +public class OnapCommandDiscoveryFailed extends OnapCommandException { + + private static final long serialVersionUID = 424464582747161435L; + + private static final String ERROR_CODE = "0x0010"; + private static final String ERROR_MESSAGE1 = "Failed auto discover schema files from "; + private static final String ERROR_MESSAGE2 = " under class path, "; + private static final String ERROR_MESSAGE3 = "' under class path directory '"; + private static final String ERROR_MESSAGE4 = "Failed auto generate json file '"; + + public OnapCommandDiscoveryFailed(String name) { + this(name, new Exception("")); + } + + public OnapCommandDiscoveryFailed(String name, Throwable throwable) { + super(ERROR_CODE, ERROR_MESSAGE1 + name + ERROR_MESSAGE2 + throwable.getMessage()); + } + + public OnapCommandDiscoveryFailed(String directory, String fileName) { + this(directory, fileName, new Exception("")); + } + + public OnapCommandDiscoveryFailed(String directory, String fileName, Throwable throwable) { + super(ERROR_CODE, ERROR_MESSAGE4 + fileName + ERROR_MESSAGE3 + directory + "' , " + throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandException.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandException.java new file mode 100644 index 00000000..3ef1b400 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandException.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Base command exception. + * + */ +public class OnapCommandException extends Exception { + + private static final long serialVersionUID = 2833124031431731711L; + + /* + * Command Error Code + */ + private final String errorCode; + + /* + * Command error message + */ + private final String errorMessage; + + /* + * Command HTTP status code + */ + private final long httpStatusCode; + + /** + * OnapCommandException constructor. + * + * @param errorCode + * error code + * @param errorMessage + * error message + * @param httpStatusCode + * http status code + */ + public OnapCommandException(String errorCode, String errorMessage, long httpStatusCode) { + super(); + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.httpStatusCode = httpStatusCode; + } + + public OnapCommandException(String errorCode, String errorMessage) { + this(errorCode, errorMessage, -1); + } + + @Override + public String getMessage() { + String message = this.errorCode + "::" + this.errorMessage; + if (this.httpStatusCode != -1) { + message = this.httpStatusCode + "::" + message; + } + + return message; + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutionFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutionFailed.java new file mode 100644 index 00000000..22d11acb --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutionFailed.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command execution failed. + * + */ +public class OnapCommandExecutionFailed extends OnapCommandException { + private static final long serialVersionUID = 488775545436993019L; + + private static final String ERROR_CODE = "0x0001"; + private static final String ERROR_MESSAGE1 = "Command "; + private static final String ERROR_MESSAGE2 = " failed to execute, "; + private static final String ERROR_MESSAGE3 = "Failed to retrive service url, "; + + public OnapCommandExecutionFailed(String cmdName, String error, long httpStatus) { + super(ERROR_CODE, ERROR_MESSAGE1 + cmdName + ERROR_MESSAGE2 + error, httpStatus); + } + + public OnapCommandExecutionFailed(String cmdName, Throwable throwable, long httpStatus) { + this(cmdName,throwable.getMessage(),httpStatus); + } + + public OnapCommandExecutionFailed(String error) { + super(ERROR_CODE, error); + } + + public OnapCommandExecutionFailed(Throwable throwable, String details) { + this(ERROR_MESSAGE3 + details + ", " + throwable.getMessage()); + } + + + public OnapCommandExecutionFailed(String cmdName, String error) { + super(ERROR_CODE, ERROR_MESSAGE1 + cmdName + ERROR_MESSAGE2 + error); + } + + public OnapCommandExecutionFailed(String cmd, Throwable throwable) { + this(cmd , throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutorInfoMissing.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutorInfoMissing.java new file mode 100644 index 00000000..b4945dda --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandExecutorInfoMissing.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command result initialization failed. + * + */ +public class OnapCommandExecutorInfoMissing extends OnapCommandException { + + private static final long serialVersionUID = 8580121615330415456L; + + public OnapCommandExecutorInfoMissing(String cmd) { + super("0x0023", "Command " + cmd + " excutor info is missing from schema"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHelpFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHelpFailed.java new file mode 100644 index 00000000..12e711e3 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHelpFailed.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command help failed. + * + */ +public class OnapCommandHelpFailed extends OnapCommandException { + private static final long serialVersionUID = -1833571383961748518L; + + /** + * Help failed exception. + * + * @param error + * message + */ + public OnapCommandHelpFailed(String error) { + super("0x0002", "Command failed to print help message, " + error); + } + + public OnapCommandHelpFailed(Throwable throwable) { + this(throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpFailure.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpFailure.java new file mode 100644 index 00000000..80f99695 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpFailure.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command execution failed. + * + */ +public class OnapCommandHttpFailure extends OnapCommandException { + private static final long serialVersionUID = 488775545436993345L; + + private static final String ERROR = "0x0025"; + + public OnapCommandHttpFailure(String error, long httpStatus) { + super(ERROR, error, httpStatus); + } + + public OnapCommandHttpFailure(String error) { + super(ERROR, error); + } + + public OnapCommandHttpFailure(Throwable throwable) { + this(throwable.getMessage()); + } + + public OnapCommandHttpFailure(Throwable throwable, long httpStatus) { + this(throwable.getMessage(), httpStatus); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpHeaderNotFound.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpHeaderNotFound.java new file mode 100644 index 00000000..ba0006ec --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpHeaderNotFound.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * OnapCommandParameterNotFound. + * + */ +public class OnapCommandHttpHeaderNotFound extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + public OnapCommandHttpHeaderNotFound(String name) { + super("0x0027", "Http header " + name + " is not returned from the service"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpInvalidResponseBody.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpInvalidResponseBody.java new file mode 100644 index 00000000..1451440a --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandHttpInvalidResponseBody.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * OnapCommandParameterNotFound. + * + */ +public class OnapCommandHttpInvalidResponseBody extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + public OnapCommandHttpInvalidResponseBody(String name, String error) { + super("0x0028", "Http response body does not have json entry " + name + ", " + error); + } + + public OnapCommandHttpInvalidResponseBody(String name, Throwable throwable) { + this(name, throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterType.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterType.java new file mode 100644 index 00000000..066e2699 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterType.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command input parameter type is invalid. + * + */ +public class OnapCommandInvalidParameterType extends OnapCommandException { + + private static final long serialVersionUID = 2821256032317061066L; + + public OnapCommandInvalidParameterType(String paramName) { + super("0x0003", "Parameter type " + paramName + " is invalid"); + + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterValue.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterValue.java new file mode 100644 index 00000000..652789a6 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidParameterValue.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command input parameter value is invalid. + * + */ +public class OnapCommandInvalidParameterValue extends OnapCommandException { + + private static final long serialVersionUID = 2821256032317061437L; + + public OnapCommandInvalidParameterValue(String paramName) { + this(paramName,new Exception("")); + } + + public OnapCommandInvalidParameterValue(String paramName, Throwable throwable) { + super("0x0028", "Parameter " + paramName + " value is invalid, " + throwable.getMessage()); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidPrintDirection.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidPrintDirection.java new file mode 100644 index 00000000..960bfa40 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidPrintDirection.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command print direction invalid. + * + */ +public class OnapCommandInvalidPrintDirection extends OnapCommandException { + + private static final long serialVersionUID = -6008135162231523072L; + + public OnapCommandInvalidPrintDirection(String direction) { + super("0x0004", "Print direction " + direction + " is invalid"); + + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidRegistration.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidRegistration.java new file mode 100644 index 00000000..c403a4ad --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidRegistration.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +import org.onap.cli.fw.OnapCommand; + +/** + * Command class invalid. + * + */ +public class OnapCommandInvalidRegistration extends OnapCommandException { + + private static final long serialVersionUID = 7722163282274482532L; + + public OnapCommandInvalidRegistration(Class cls) { + super("0x0005", "Invalid commad class " + cls.getCanonicalName() + " registration, it should be derived from " + + OnapCommand.class.getCanonicalName()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidResultAttributeScope.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidResultAttributeScope.java new file mode 100644 index 00000000..d4a3a5ee --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidResultAttributeScope.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Result attribute invalid. + * + */ +public class OnapCommandInvalidResultAttributeScope extends OnapCommandException { + + private static final long serialVersionUID = 117926166492101573L; + + public OnapCommandInvalidResultAttributeScope(String attr) { + super("0x0006", "Result atrribute " + attr + " is invalid"); + + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchema.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchema.java new file mode 100644 index 00000000..a32a8f2a --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchema.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command schema is invalid. + * + */ +public class OnapCommandInvalidSchema extends OnapCommandException { + + private static final long serialVersionUID = -3387652326582792833L; + + public OnapCommandInvalidSchema(String schema, String error) { + super("0x0007", "Command schema " + schema + " is invalid, " + error); + } + + public OnapCommandInvalidSchema(String schema, Throwable throwable) { + this(schema, throwable.getMessage()); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchemaVersion.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchemaVersion.java new file mode 100644 index 00000000..75530ab4 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandInvalidSchemaVersion.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command schema version is invalid. + * + */ +public class OnapCommandInvalidSchemaVersion extends OnapCommandException { + + private static final long serialVersionUID = 4459731110721370387L; + + public OnapCommandInvalidSchemaVersion(String schemaVersion) { + super("0x0008", "Command schema onap_cmd_schema_version " + schemaVersion + " is invalid or missing"); + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLoginFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLoginFailed.java new file mode 100644 index 00000000..c2d69bc1 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLoginFailed.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Login failed. + * + */ +public class OnapCommandLoginFailed extends OnapCommandException { + + private static final long serialVersionUID = 5518154493762956959L; + + private static final String ERROR_CODE = "0x0009"; + private static final String ERROR_MESSAGE1 = "Login failed, "; + + public OnapCommandLoginFailed(String error) { + super(ERROR_CODE, ERROR_MESSAGE1 + error); + } + + public OnapCommandLoginFailed(String error, int httpStatus) { + super(ERROR_CODE, ERROR_MESSAGE1 + error, httpStatus); + } + + public OnapCommandLoginFailed(Throwable throwable) { + this(throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLogoutFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLogoutFailed.java new file mode 100644 index 00000000..3b415de0 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandLogoutFailed.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Logout failed. + * + */ +public class OnapCommandLogoutFailed extends OnapCommandException { + + private static final long serialVersionUID = 1150649507734289032L; + private static final String ERROR_CODE = "0x0010"; + private static final String ERROR_MESSAGE1 = "Logout failed, "; + + public OnapCommandLogoutFailed(String error) { + super(ERROR_CODE, ERROR_MESSAGE1 + error); + } + + public OnapCommandLogoutFailed(Throwable throwable) { + this(throwable.getMessage()); + } + + public OnapCommandLogoutFailed(int statusCode) { + super(ERROR_CODE, ERROR_MESSAGE1, statusCode); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotFound.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotFound.java new file mode 100644 index 00000000..172d60bb --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotFound.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command not registered in CLI registrar. + * + */ +public class OnapCommandNotFound extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + public OnapCommandNotFound(String cmdName) { + super("0x0011", "Command " + cmdName + " is not registered"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotInitialized.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotInitialized.java new file mode 100644 index 00000000..8c3f6c22 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandNotInitialized.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command not initialized. + * + */ +public class OnapCommandNotInitialized extends OnapCommandException { + + private static final long serialVersionUID = -2828462844645573902L; + + public OnapCommandNotInitialized(String cmdName) { + super("0x0012", "Command " + cmdName + " is not initialized"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputFormatNotsupported.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputFormatNotsupported.java new file mode 100644 index 00000000..e54171ef --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputFormatNotsupported.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command does not support to format of output. + * + */ +public class OnapCommandOutputFormatNotsupported extends OnapCommandException { + + private static final long serialVersionUID = 2429471829315901896L; + + public OnapCommandOutputFormatNotsupported(String format) { + super("0x0013", "Command does not support the output format " + format); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputPrintingFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputPrintingFailed.java new file mode 100644 index 00000000..31ee3e0b --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandOutputPrintingFailed.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Output print failed. + * + */ +public class OnapCommandOutputPrintingFailed extends OnapCommandException { + + private static final long serialVersionUID = -1957064141442406239L; + + public OnapCommandOutputPrintingFailed(String error) { + super("0x0014", "Command is failed to print the result, " + error); + } + + public OnapCommandOutputPrintingFailed(Throwable throwable) { + this(throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterMissing.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterMissing.java new file mode 100644 index 00000000..54e0a0de --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterMissing.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command input parameters are invalid. + * + */ +public class OnapCommandParameterMissing extends OnapCommandException { + + private static final long serialVersionUID = 2821256032317061066L; + + public OnapCommandParameterMissing(String paramName) { + super("0x0015", "Parameter " + paramName + " is mandatory"); + + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNameConflict.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNameConflict.java new file mode 100644 index 00000000..d5dc185c --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNameConflict.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command input parameter options are conflicting. + * + */ +public class OnapCommandParameterNameConflict extends OnapCommandException { + + private static final long serialVersionUID = -993203017969910920L; + + public OnapCommandParameterNameConflict(String name) { + super("0x0016", "Parameter name " + name + " is in conflict"); + + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNotFound.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNotFound.java new file mode 100644 index 00000000..ea3eb3a8 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterNotFound.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * OnapCommandParameterNotFound. + * + */ +public class OnapCommandParameterNotFound extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + public OnapCommandParameterNotFound(String paramName) { + super("0x0026", "Command input parameter " + paramName + " is not valid"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterOptionConflict.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterOptionConflict.java new file mode 100644 index 00000000..91decf99 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandParameterOptionConflict.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command input parameter names are conflicting. + * + */ +public class OnapCommandParameterOptionConflict extends OnapCommandException { + + private static final long serialVersionUID = -3107017890769007297L; + + public OnapCommandParameterOptionConflict(String name) { + super("0x0017", "Parameter option " + name + " is in conflict, only one option is allowed with given name"); + + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandRegistrationFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandRegistrationFailed.java new file mode 100644 index 00000000..d920f7d0 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandRegistrationFailed.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command Not registered in Onap Command Registrar. + * + */ +public class OnapCommandRegistrationFailed extends OnapCommandException { + + private static final long serialVersionUID = 5513297861129088460L; + + public OnapCommandRegistrationFailed(String cmdName, String error) { + super("0x0018", "Command " + cmdName + " is failed to register, " + error); + } + + public OnapCommandRegistrationFailed(String cmdName, Throwable throwable) { + this(cmdName, throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultEmpty.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultEmpty.java new file mode 100644 index 00000000..5d7e4fd3 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultEmpty.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command result empty. + * + */ +public class OnapCommandResultEmpty extends OnapCommandWarning { + + private static final long serialVersionUID = 8580121615330415123L; + + /** + * Command result empty. + */ + public OnapCommandResultEmpty() { + super("0x1001", "Command result is empty"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultInitialzationFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultInitialzationFailed.java new file mode 100644 index 00000000..20060531 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultInitialzationFailed.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command result initialization failed. + * + */ +public class OnapCommandResultInitialzationFailed extends OnapCommandException { + + private static final long serialVersionUID = 8580121615330415123L; + + public OnapCommandResultInitialzationFailed(String cmd, String error) { + super("0x0022", "Command " + cmd + " result format is failed, " + error); + } + + public OnapCommandResultInitialzationFailed(String cmd, Throwable throwable) { + this(cmd, throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultMapProcessingFailed.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultMapProcessingFailed.java new file mode 100644 index 00000000..191ced06 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandResultMapProcessingFailed.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Result map failure. + * + */ +public class OnapCommandResultMapProcessingFailed extends OnapCommandException { + private static final long serialVersionUID = 488775545436113019L; + + private static final String errorCode = "0x0028"; + + public OnapCommandResultMapProcessingFailed(String resultMap, String error) { + super(errorCode, "Failed to process the result map " + resultMap + " in http section, " + error); + } + + public OnapCommandResultMapProcessingFailed(String resultMap, Throwable throwable) { + this(resultMap, throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandSchemaNotFound.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandSchemaNotFound.java new file mode 100644 index 00000000..cbd6fa69 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandSchemaNotFound.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command schema not found. + * + */ +public class OnapCommandSchemaNotFound extends OnapCommandException { + + private static final long serialVersionUID = -3919580583845280200L; + + public OnapCommandSchemaNotFound(String cmdName) { + this(cmdName, new Exception("")); + } + + public OnapCommandSchemaNotFound(String cmdName, Throwable throwable) { + super("0x0019", "Command schema " + cmdName + " is not found, " + throwable.getMessage()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandServiceNotFound.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandServiceNotFound.java new file mode 100644 index 00000000..fbbaafbd --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandServiceNotFound.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command not registered in MSB. + * + */ +public class OnapCommandServiceNotFound extends OnapCommandException { + + private static final long serialVersionUID = 8580121615330415065L; + + public OnapCommandServiceNotFound(String service) { + super("0x0020", "Service " + service + " is not found in MSB"); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/error/OnapCommandWarning.java b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandWarning.java new file mode 100644 index 00000000..bb102a5b --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/error/OnapCommandWarning.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.error; + +/** + * Command warning. + * + */ +public abstract class OnapCommandWarning extends OnapCommandException { + public OnapCommandWarning(String errorCode, String errorMessage, long httpStatusCode) { + super(errorCode, errorMessage, httpStatusCode); + } + + public OnapCommandWarning(String errorCode, String errorMessage) { + super(errorCode, errorMessage); + } + + private static final long serialVersionUID = -1833571383961748520L; +} diff --git a/framework/src/main/java/org/onap/cli/fw/http/HttpInput.java b/framework/src/main/java/org/onap/cli/fw/http/HttpInput.java new file mode 100644 index 00000000..3ab6cf4b --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/http/HttpInput.java @@ -0,0 +1,128 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.http; + +import java.util.HashMap; +import java.util.Map; + +/** + * Captures HTTP request URI, body and request &query parameters. <br> + */ +public class HttpInput { + + private String reqUri = ""; + + private String reqBody = ""; + + private String reqMethod = ""; + + private Map<String, String> reqHeaders = new HashMap<>(); + + private Map<String, String> reqQueries = new HashMap<>(); + + private Map<String, String> reqCookies = new HashMap<>(); + + private boolean binaryData; + + public String getUri() { + return this.reqUri; + } + + public HttpInput setUri(String uri) { + this.reqUri = uri; + return this; + } + + public String getBody() { + return this.reqBody; + } + + public HttpInput setBody(String body) { + this.reqBody = body; + return this; + } + + public Map<String, String> getReqHeaders() { + return this.reqHeaders; + } + + /** + * header parameter setter. + * + * @param reqHeaders + * header map + * @return HttpInput + */ + public HttpInput setReqHeaders(Map<String, String> reqHeaders) { + if (reqHeaders != null) { + this.reqHeaders = reqHeaders; + } + return this; + } + + public String getMethod() { + return this.reqMethod; + } + + public HttpInput setMethod(String method) { + this.reqMethod = method; + return this; + } + + public Map<String, String> getReqQueries() { + return reqQueries; + } + + /** + * Request query parameters. + * + * @param reqQueries + * request queries + * @return HttpInput + */ + public HttpInput setReqQueries(Map<String, String> reqQueries) { + if (reqQueries != null) { + this.reqQueries = reqQueries; + } + return this; + } + + public Map<String, String> getReqCookies() { + return reqCookies; + } + + public HttpInput setReqCookies(Map<String, String> reqCookies) { + this.reqCookies = reqCookies; + return this; + } + + public boolean isBinaryData() { + return binaryData; + } + + public void setBinaryData(boolean binaryData) { + this.binaryData = binaryData; + } + + @Override + public String toString() { + return "\nURL: " + this.getUri() + "\nMethod: " + this.getMethod() + "\nRequest Queries: " + + this.getReqQueries() + "\nRequest Body: " + this.getBody() + "\nRequest Headers: " + + this.getReqHeaders().toString() + "\nRequest Cookies: " + this.getReqCookies().toString() + + "\nbinaryData=" + this.binaryData; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/http/HttpResult.java b/framework/src/main/java/org/onap/cli/fw/http/HttpResult.java new file mode 100644 index 00000000..e000ee15 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/http/HttpResult.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.http; + +import java.util.HashMap; +import java.util.Map; + +/** + * Captures HTTP response status, body and headers. <br> + * + */ +public class HttpResult { + + private int status; + + private String resBody; + + private Map<String, String> respHeaders = new HashMap<>(); + + private Map<String, String> respCookies = new HashMap<>(); + + public int getStatus() { + return this.status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getBody() { + return this.resBody; + } + + public void setBody(String body) { + this.resBody = body; + } + + public void setRespHeaders(Map<String, String> respHeaders) { + this.respHeaders = respHeaders; + } + + public Map<String, String> getRespHeaders() { + return this.respHeaders; + } + + public Map<String, String> getRespCookies() { + return respCookies; + } + + public void setRespCookies(Map<String, String> respCookies) { + this.respCookies = respCookies; + } + + public boolean isSuccess() { + return this.getStatus() >= 200 && this.getStatus() <= 300; + } + + @Override + public String toString() { + return "\nHTTP Status: " + this.getStatus() + "\nResponse Body: " + this.getBody() + "\nResponse Headers: " + + this.getRespHeaders() + "\nResponse Cookies: " + this.getRespCookies(); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/http/OnapHttpConnection.java b/framework/src/main/java/org/onap/cli/fw/http/OnapHttpConnection.java new file mode 100644 index 00000000..5b8cf8b1 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/http/OnapHttpConnection.java @@ -0,0 +1,346 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.http; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.ParseException; +import org.apache.http.client.CookieStore; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; +import org.apache.http.cookie.Cookie; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.client.LaxRedirectStrategy; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.error.OnapCommandHttpFailure; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * Helps to make http connection.<br> + */ +public class OnapHttpConnection { + + private HttpClient httpClient = null; + + private String xauthToken = null; + + protected boolean debug = false; + + private String debugDetails = ""; + + public static class TrustAllX509TrustManager implements X509TrustManager { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + // No need to implement. + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + // No need to implement. + } + } + + /** + * OnapHttpConnection Constructor. + * + * @param isSecured + * boolean + * @param debug + * boolean + * @throws OnapCommandHttpFailure + * exception + */ + public OnapHttpConnection(boolean isSecured, boolean debug) throws OnapCommandHttpFailure { + try { + if (isSecured) { + SSLContext sslContext = SSLContext.getInstance(Constants.SSLCONTEST_TLS); + sslContext.init(null, new TrustManager[] { new TrustAllX509TrustManager() }, + new java.security.SecureRandom()); + X509HostnameVerifier hostnameVerifier = new AllowAllHostnameVerifier(); + Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder + .<ConnectionSocketFactory>create() + .register("https", new SSLConnectionSocketFactory(sslContext, hostnameVerifier)).build(); + HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + + this.httpClient = HttpClients.custom().setConnectionManager(connManager) + .setRedirectStrategy(new LaxRedirectStrategy()).build(); + } else { + this.httpClient = HttpClients.createDefault(); + } + } catch (Exception e) { + throw new OnapCommandHttpFailure(e); + } + + this.debug = debug; + } + + public String getDebugInfo() { + return this.debugDetails; + } + + public void setAuthToken(String token) { + this.xauthToken = token; + } + + public String getAuthToken() { + return this.xauthToken; + } + + private Map<String, String> getHttpHeaders(HttpResponse resp) { + Map<String, String> result = new HashMap<>(); + + Header[] hs = resp.getAllHeaders(); + for (int i = 0; i < hs.length; i++) { + result.put(hs[i].getName(), hs[i].getValue()); + } + + return result; + } + + private String getResponseBody(HttpResponse resp) throws OnapCommandHttpFailure { + if (resp.getEntity() == null) { + return null; + } + try { + String body = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8); + EntityUtils.consume(resp.getEntity()); + return body; + } catch (IOException e) { + throw new OnapCommandHttpFailure(e); + } + } + + private StringEntity getStringEntity(HttpInput input) { + return new StringEntity(input.getBody(), StandardCharsets.UTF_8); + } + + /** + * Post. <br> + * + * @param input + * HttpInput Obj + * @return HttpResult + * @throws OnapCommandHttpFailure + * http failure + */ + public HttpResult post(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("post"); + return this.request(input); + } + + /** + * Get. <br> + * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * excpetion + */ + public HttpResult get(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("get"); + return this.request(input); + } + + /** + * Put. <br> + * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * Exception + */ + public HttpResult put(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("put"); + return this.request(input); + } + + /** + * Delete. <br> + * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult delete(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("delete"); + return this.request(input); + } + + private void addCommonHeaders(HttpInput input) { + if (!input.isBinaryData()) { + input.getReqHeaders().put("Content-Type", Constants.APPLICATION_JSON); + } + input.getReqHeaders().put("Accept", Constants.APPLICATION_JSON); + if (this.xauthToken != null) { + input.getReqHeaders().put(Constants.X_AUTH_TOKEN, this.xauthToken); + } + } + + private void addCommonCookies(CookieStore cookieStore) { + Cookie cookie = new BasicClientCookie(Constants.X_AUTH_TOKEN, this.xauthToken); + cookieStore.addCookie(cookie); + } + + private void updateResultFromCookies(HttpResult result, List<Cookie> cookies) { + for (Cookie cookie : cookies) { + result.getRespCookies().put(cookie.getName(), cookie.getValue()); + } + } + + private String getDomain(String url) { + try { + return new URL(url).getHost(); + } catch (MalformedURLException e) { + // url is always proper !! + return url; + } + } + + private void updateInputFromCookies(HttpInput input, CookieStore cookieStore) { + addCommonCookies(cookieStore); + for (String cookieName : input.getReqCookies().keySet()) { + BasicClientCookie cookie = new BasicClientCookie(cookieName, input.getReqCookies().get(cookieName)); + cookie.setDomain(this.getDomain(input.getUri())); + cookieStore.addCookie(cookie); + } + + } + + /** + * Handles http method requests. + * + * @param input + * HttpInput + * @return HttpResult + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult request(HttpInput input) throws OnapCommandHttpFailure { + this.addCommonHeaders(input); + + HttpRequestBase requestBase = null; + if ("post".equals(input.getMethod())) { + HttpPost httpPost = new HttpPost(); + if (input.isBinaryData()) { + httpPost.setEntity(getMultipartEntity(input)); + } else { + httpPost.setEntity(this.getStringEntity(input)); + } + requestBase = httpPost; + } else if ("put".equals(input.getMethod())) { + HttpPut httpPut = new HttpPut(); + httpPut.setEntity(this.getStringEntity(input)); + requestBase = httpPut; + } else if ("get".equals(input.getMethod())) { + requestBase = new HttpGet(); + } else if ("delete".equals(input.getMethod())) { + requestBase = new HttpDelete(); + } else { + throw new IllegalArgumentException("Invalid HTTP method"); + } + + requestBase.setURI(URI.create(input.getUri())); + + for (Entry<String, String> h : input.getReqHeaders().entrySet()) { + requestBase.addHeader(h.getKey(), h.getValue()); + } + + HttpResult result = new HttpResult(); + + try { + this.debugDetails = ""; + CookieStore cookieStore = new BasicCookieStore(); + updateInputFromCookies(input, cookieStore); + HttpContext localContext = new BasicHttpContext(); + localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); + + HttpResponse resp = this.httpClient.execute(requestBase, localContext); + String respContent = this.getResponseBody(resp); + result.setBody(respContent); + result.setStatus(resp.getStatusLine().getStatusCode()); + result.setRespHeaders(this.getHttpHeaders(resp)); + this.updateResultFromCookies(result, cookieStore.getCookies()); + } catch (ParseException | IOException e) { + throw new OnapCommandHttpFailure(e); + } finally { + if (this.debug) { + this.debugDetails = input + "" + result; + } + } + + return result; + } + + public void close() { + this.setAuthToken(null); + } + + private HttpEntity getMultipartEntity(HttpInput input) { + FileBody fileBody = new FileBody(new File(input.getBody().trim())); + MultipartEntity multipartEntity = new MultipartEntity(); + multipartEntity.addPart("file", fileBody); + return multipartEntity; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/input/OnapCommandParameter.java b/framework/src/main/java/org/onap/cli/fw/input/OnapCommandParameter.java new file mode 100644 index 00000000..167b353d --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/input/OnapCommandParameter.java @@ -0,0 +1,254 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.input; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.error.OnapCommandParameterMissing; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * Onap Command's input parameter. + * + */ +public class OnapCommandParameter { + + /* + * Name, for positional parameters, the place is decided from schema file definition + */ + private String cmdName; + + /* + * Description + */ + private String cmdDescription = ""; + + /* + * Short Option, like -f, for positional parameters, its not required. + */ + private String shortOption = null; + + /* + * Long Option, like --file-path, for positional parameters, its not required. + */ + private String longOption = null; + + /* + * Parameter type such as int, json, yaml, string, etc + */ + private ParameterType parameterType; + + /* + * Default value + */ + private String defaultValue = ""; + + /* + * Is optional + */ + private boolean isOptional = false; + + /* + * Is secured + */ + private boolean isSecured = false; + + /* + * Parameter Value + */ + private Object value; + + public String getName() { + return cmdName; + } + + public void setName(String name) { + this.cmdName = name; + } + + public String getDescription() { + return cmdDescription; + } + + public void setDescription(String description) { + this.cmdDescription = description; + } + + public String getShortOption() { + return shortOption; + } + + public void setShortOption(String shortOption) { + this.shortOption = shortOption; + } + + public String getLongOption() { + return longOption; + } + + public void setLongOption(String longOption) { + this.longOption = longOption; + } + + public ParameterType getParameterType() { + return parameterType; + } + + public void setParameterType(ParameterType parameterType) { + this.parameterType = parameterType; + } + + /** + * Returns default value. + * + * @return string + */ + public String getDefaultValue() { + if (this.isDefaultValueAnEnv()) { + String envVar = this.getEnvVarNameFromDefaultValue(); + this.defaultValue = System.getenv(envVar); + } else if (this.getParameterType().equals(ParameterType.BOOL)) { + // For bool type always the default param is false + this.defaultValue = "false"; + } + + return defaultValue; + } + + /** + * check if the default value is ${ENV_VAR_NAME}. + * + * @return boolean + */ + public boolean isDefaultValueAnEnv() { + return this.defaultValue.trim().startsWith("${") && this.defaultValue.trim().endsWith("}"); + } + + /** + * check if the default value is ${ENV_VAR_NAME} and return the ENV_VAR_NAME. + * + * @return ENV_VAR_NAME + */ + public String getEnvVarNameFromDefaultValue() { + return this.defaultValue.trim().substring(2, this.defaultValue.length() - 1); + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Returns param value. + * + * @return value + * @throws OnapCommandInvalidParameterValue + * exception + */ + public Object getValue() throws OnapCommandInvalidParameterValue { + if (value != null) { + if (ParameterType.URL.equals(parameterType) && !value.toString().startsWith("http") + && !value.toString().startsWith("/")) { + value = "/" + value; + } else if (ParameterType.ARRAY.equals(parameterType)) { + if (!(value instanceof List)) { + throw new OnapCommandInvalidParameterValue(this.getName()); + } + + List<String> list = (List<String>) value; + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.writeValueAsString(list); + } catch (JsonProcessingException e) { + throw new OnapCommandInvalidParameterValue(this.getName(), e); + } + } else if (ParameterType.MAP.equals(parameterType)) { + if (!(value instanceof Map)) { + throw new OnapCommandInvalidParameterValue(this.getName()); + } + + Map<String, String> map = (Map<String, String>) value; + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.writeValueAsString(map); + } catch (JsonProcessingException e) { + throw new OnapCommandInvalidParameterValue(this.getName(), e); + } + } + + return value; + } + return getDefaultValue(); + } + + public void setValue(Object value) { + this.value = value; + } + + public boolean isOptional() { + return isOptional; + } + + public void setOptional(boolean isOptional) { + this.isOptional = isOptional; + } + + public boolean isSecured() { + return isSecured; + } + + public void setSecured(boolean isSecured) { + this.isSecured = isSecured; + } + + public static String printShortOption(String option) { + return "-" + option; + } + + public static String printLongOption(String option) { + return "-" + printShortOption(option); + } + + /** + * Validate parameter value. + * + * @throws OnapCommandParameterMissing + * exception + * @throws OnapCommandInvalidParameterValue + * exception + */ + public void validate() throws OnapCommandException { + // (mrkanag) empty check needs to revisit + if (!this.isOptional() && (this.getValue() == null || this.getValue().toString().isEmpty())) { + throw new OnapCommandParameterMissing(this.getName()); + } + + if (!this.isOptional() && ParameterType.BINARY.equals(parameterType)) { + File file = new File(value.toString()); + if (!file.isFile()) { + throw new OnapCommandInvalidParameterValue(this.getName()); + } + } + + // (mrkanag) validate for type supported ParameterType using constraints + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/input/ParameterType.java b/framework/src/main/java/org/onap/cli/fw/input/ParameterType.java new file mode 100644 index 00000000..ec76e0b4 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/input/ParameterType.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.input; + +import org.onap.cli.fw.error.OnapCommandInvalidParameterType; + +/** + * Parameter type supported by Onap CLI. + * + */ +public enum ParameterType { + /** + * JSON file. + */ + JSON, + /** + * YAML file. + */ + YAML, STRING, LONG, + /** + * URL location. + */ + URL, BOOL, ARRAY, MAP, BINARY; + + /** + * Get parameter type. + * + * @param name + * type name + * @return type + * @throws OnapCommandInvalidParameterType + * exception + */ + public static ParameterType get(String name) throws OnapCommandInvalidParameterType { + if (JSON.name().equalsIgnoreCase(name)) { + return JSON; + } else if (YAML.name().equalsIgnoreCase(name)) { + return YAML; + } else if (STRING.name().equalsIgnoreCase(name)) { + return STRING; + } else if (LONG.name().equalsIgnoreCase(name)) { + return LONG; + } else if (URL.name().equalsIgnoreCase(name)) { + return URL; + } else if (BOOL.name().equalsIgnoreCase(name)) { + return BOOL; + } else if (ARRAY.name().equalsIgnoreCase(name)) { + return ARRAY; + } else if (MAP.name().equalsIgnoreCase(name)) { + return MAP; + } else if (BINARY.name().equalsIgnoreCase(name)) { + return BINARY; + } else { + throw new OnapCommandInvalidParameterType(name); + } + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/log/OnapCommandLogger.java b/framework/src/main/java/org/onap/cli/fw/log/OnapCommandLogger.java new file mode 100644 index 00000000..a29d3597 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/log/OnapCommandLogger.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.log; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helps to log the command method boundary calls. + * + */ +@Aspect +public class OnapCommandLogger { + private static final Logger LOGGER = LoggerFactory.getLogger(OnapCommandLogger.class); + + //(mrkanag) verify that it logs for all classes in this project. + /** + * Logging intercepter. + * + * @param joinPoint + * joinpoint + * @return object + * @throws Throwable + * exception + */ + @Around("execution(* org.onap.cli.fw*(..))") + public Object log(ProceedingJoinPoint joinPoint) throws Throwable { // NOSONAR + LOGGER.info(joinPoint.getThis().toString() + "->" + joinPoint.getSignature().getName() + "(" + + joinPoint.getArgs() + ")"); + + Object response = joinPoint.proceed(); + LOGGER.info(response.toString()); + + return response; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResult.java b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResult.java new file mode 100644 index 00000000..5dd761c6 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResult.java @@ -0,0 +1,249 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output; + +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandOutputFormatNotsupported; +import org.onap.cli.fw.error.OnapCommandOutputPrintingFailed; +import org.onap.cli.fw.input.ParameterType; +import org.onap.cli.fw.output.print.OnapCommandPrint; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Onap Command result holds the final output of the command. + * + */ +public class OnapCommandResult { + + /* + * if type=JSON, then JSON response of the command from back-end Onap service, by default all the command would + * set this value once the back-end call returns, which would be useful to print the output in JSON format, returned + * from the back-end service. + * + * if type=TEXT, then it holds the result in text format such as help message + */ + private Object output; + + /* + * Type requested by user + */ + private ResultType type = ResultType.TABLE; + + /* + * Scope requested by user + */ + private OnapCommandResultAttributeScope scope = OnapCommandResultAttributeScope.SHORT; + + /* + * if type=TABLE, then List of result records, which could be printed on the CLI console, loaded from schema file + */ + private List<OnapCommandResultAttribute> records = new ArrayList<>(); + + /* + * Print horizontally or vertically, Mostly for show command, horizontal table while for list commands , it will be + * vertically printed. Respective command should set appropriately. + * + * loaded from schema file + */ + private PrintDirection printDirection = PrintDirection.LANDSCAPE; + + private String debugInfo = ""; + + /** + * Requested by user. + */ + private boolean includeTitle = true; + + /** + * Requested by user. + */ + private boolean includeSeparator = true; + + /** + * Requested by user. + */ + private boolean isDebug = false; + + public PrintDirection getPrintDirection() { + return printDirection; + } + + public void setPrintDirection(PrintDirection printDirection) { + this.printDirection = printDirection; + } + + public Object getOutput() { + return output; + } + + public void setOutput(Object output) { + this.output = output; + } + + public List<OnapCommandResultAttribute> getRecords() { + return records; + } + + public void setRecords(List<OnapCommandResultAttribute> records) { + this.records = records; + } + + /** + * Record mapping. + * + * @return attributes + */ + public Map<String, OnapCommandResultAttribute> getRecordsMap() { + Map<String, OnapCommandResultAttribute> recordMap = new HashMap<>(); + + for (OnapCommandResultAttribute record : this.getRecords()) { + recordMap.put(record.getName(), record); + } + + return recordMap; + } + + public ResultType getType() { + return type; + } + + public void setType(ResultType type) { + this.type = type; + } + + public OnapCommandResultAttributeScope getScope() { + return scope; + } + + public void setScope(OnapCommandResultAttributeScope scope) { + this.scope = scope; + } + + public boolean isIncludeTitle() { + return includeTitle; + } + + public void setIncludeTitle(boolean includeTitle) { + this.includeTitle = includeTitle; + } + + public boolean isIncludeSeparator() { + return includeSeparator; + } + + public void setIncludeSeparator(boolean includeSeparator) { + this.includeSeparator = includeSeparator; + } + + public String getDebugInfo() { + return debugInfo; + } + + public void setDebugInfo(String debugInfo) { + this.debugInfo = debugInfo; + } + + public boolean isDebug() { + return isDebug; + } + + public void setDebug(boolean isDebug) { + this.isDebug = isDebug; + } + + /** + * Helps to print the result based on the type. + * + * @return string + * @throws OnapCommandOutputFormatNotsupported + * excpetion + * @throws OnapCommandOutputPrintingFailed + * exception + */ + public String print() throws OnapCommandException { + String printOutput = ""; + + if (this.getRecords().isEmpty()) { + return printOutput; + } + + OnapCommandPrint print = new OnapCommandPrint(); + print.setPrintTitle(this.isIncludeTitle()); + if (this.getPrintDirection().equals(PrintDirection.LANDSCAPE)) { + for (OnapCommandResultAttribute record : this.getScopedRecords()) { + if (record.getType().equals(ParameterType.JSON)) { + print.addColumn(record.getName(), OnapCommandUtils.jsonFlatten(record.getValues())); + } else { + print.addColumn(record.getName(), record.getValues()); + } + } + } else { + // Add property column + OnapCommandResultAttribute prp = new OnapCommandResultAttribute(); + prp.setName(Constants.PORTRAINT_COLUMN_NAME_PROPERTY); + prp.setScope(OnapCommandResultAttributeScope.SHORT); + // Add value column + OnapCommandResultAttribute val = new OnapCommandResultAttribute(); + val.setName(Constants.PORTRAINT_COLUMN_NAME_VALUE); + val.setScope(OnapCommandResultAttributeScope.SHORT); + + for (OnapCommandResultAttribute record : this.getScopedRecords()) { + prp.getValues().add(record.getName()); + if (record.getValues().size() == 1) { + val.getValues().add(record.getValues().get(0)); + } else { + val.getValues().add(record.getValues().toString()); + } + } + + print.addColumn(prp.getName(), prp.getValues()); + print.addColumn(val.getName(), val.getValues()); + } + + if (this.isDebug()) { + printOutput = this.getDebugInfo() + "\n"; + } + + if (this.getType().equals(ResultType.JSON)) { + return printOutput + print.printJson(); + } else if (this.getType().equals(ResultType.TABLE)) { + return printOutput + print.printTable(this.isIncludeSeparator()); + } else if (this.getType().equals(ResultType.CSV)) { + return printOutput + print.printCsv(); + } + + throw new OnapCommandOutputFormatNotsupported(this.getType().name()); + } + + private List<OnapCommandResultAttribute> getScopedRecords() { + List<OnapCommandResultAttribute> recordList = new ArrayList<>(); + for (OnapCommandResultAttribute record : this.getRecords()) { + if (record.getScope().ordinal() > this.getScope().ordinal()) { + continue; + } + recordList.add(record); + } + + return recordList; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttribute.java b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttribute.java new file mode 100644 index 00000000..73617049 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttribute.java @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output; + +import org.onap.cli.fw.input.ParameterType; + +import java.util.ArrayList; +import java.util.List; + +/** + * Onap command output records, helps to define the title and its description while command is defined and during run + * time, it captures the value of the output as well. + */ +public class OnapCommandResultAttribute { + + /* + * Output name + */ + private String outName; + + /* + * Output description + */ + private String outDescription; + + /* + * Output values, in case list out, it holds values for all rows for show output, it will have one value + */ + private List<String> values = new ArrayList<>(); + + /* + * Output scope + */ + private OnapCommandResultAttributeScope outScope = OnapCommandResultAttributeScope.SHORT; + + private ParameterType paramType = ParameterType.STRING; + + private boolean isSecured = false; + + public void setValues(List<String> values) { + this.values = values; + } + + public String getName() { + return outName; + } + + public void setName(String name) { + this.outName = name; + } + + public String getDescription() { + return outDescription; + } + + public void setDescription(String description) { + this.outDescription = description; + } + + public List<String> getValues() { + return values; + } + + public OnapCommandResultAttributeScope getScope() { + return outScope; + } + + public void setScope(OnapCommandResultAttributeScope scope) { + this.outScope = scope; + } + + public ParameterType getType() { + return paramType; + } + + public void setType(ParameterType type) { + this.paramType = type; + } + + public boolean isSecured() { + return isSecured; + } + + public void setSecured(boolean isSecured) { + this.isSecured = isSecured; + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttributeScope.java b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttributeScope.java new file mode 100644 index 00000000..e03937d3 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/OnapCommandResultAttributeScope.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output; + +import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope; + +/** + * Onap command supports to print output with given set of defined attributes, and each attributes are marked with this + * visibility. + * + */ +public enum OnapCommandResultAttributeScope { + /** + * By default, all output attributes which are tagged with short would be printed. + */ + SHORT, + /** + * When user provides --long or -l, all attributes including short tagged will be printed. otherwise, attributes + * tagged with long, whould be ignored as part of output + */ + LONG; + + /** + * get attribute scope enum type. + * + * @param name + * scope + * @return type + * @throws OnapCommandInvalidResultAttributeScope + * exception + */ + public static OnapCommandResultAttributeScope get(String name) throws OnapCommandInvalidResultAttributeScope { + if (LONG.name().equalsIgnoreCase(name)) { + return LONG; + } else if (SHORT.name().equalsIgnoreCase(name)) { + return SHORT; + } + + throw new OnapCommandInvalidResultAttributeScope(name); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/PrintDirection.java b/framework/src/main/java/org/onap/cli/fw/output/PrintDirection.java new file mode 100644 index 00000000..96ad713f --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/PrintDirection.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output; + +import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection; + +/** + * How to print the result. + * + */ +public enum PrintDirection { + LANDSCAPE, PORTRAIT; + /** + * Get print direction. + * + * @param name + * direction + * @return type + * @throws OnapCommandInvalidPrintDirection + * exception + */ + public static PrintDirection get(String name) throws OnapCommandInvalidPrintDirection { + if (LANDSCAPE.name().equalsIgnoreCase(name)) { + return LANDSCAPE; + } else if (PORTRAIT.name().equalsIgnoreCase(name)) { + return PORTRAIT; + } else { + throw new OnapCommandInvalidPrintDirection(name); + } + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/ResultType.java b/framework/src/main/java/org/onap/cli/fw/output/ResultType.java new file mode 100644 index 00000000..37449447 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/ResultType.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output; + +/** + * Onap command result format. + * + */ +public enum ResultType { + TABLE, CSV, JSON, YAML, TEXT; + + /** + * Check whether the output to be formatted in tabular format. + * + * @param type + * output format type + * @return boolean + */ + public static boolean isTabularForm(String type) { + if (type.equalsIgnoreCase(TABLE.name())) { + return true; + } + + return false; + } + + /** + * Get ResultType. + * + * @param name + * format name + * @return ResultType + */ + public static ResultType get(String name) { + if (TABLE.name().equalsIgnoreCase(name)) { + return TABLE; + } + if (CSV.name().equalsIgnoreCase(name)) { + return CSV; + } + if (JSON.name().equalsIgnoreCase(name)) { + return JSON; + } + if (YAML.name().equalsIgnoreCase(name)) { + return YAML; + } + return TEXT; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/print/OnapCommandPrint.java b/framework/src/main/java/org/onap/cli/fw/output/print/OnapCommandPrint.java new file mode 100644 index 00000000..48a4e6ea --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/print/OnapCommandPrint.java @@ -0,0 +1,252 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output.print; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.onap.cli.fw.error.OnapCommandOutputPrintingFailed; +import org.onap.cli.fw.output.PrintDirection; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * Onap Command Table print. + * + */ +public class OnapCommandPrint { + + public static final int MAX_COLUMN_LENGTH = 50; + + private PrintDirection direction; + + private Map<String, List<String>> data = new LinkedHashMap<>(); + + private boolean printTitle = true; + + public PrintDirection getDirection() { + return direction; + } + + public void setDirection(PrintDirection direction) { + this.direction = direction; + } + + public void addColumn(String header, List<String> data) { + this.data.put(header, data); + } + + /** + * Get column. + * + * @param header + * string + * @return list + */ + public List<String> getColumn(String header) { + if (this.data.get(header) == null) { + this.data.put(header, new ArrayList<String>()); + } + return this.data.get(header); + } + + public boolean isPrintTitle() { + return printTitle; + } + + public void setPrintTitle(boolean printTitle) { + this.printTitle = printTitle; + } + + private int findMaxRows() { + int max = 1; + if (!this.isPrintTitle()) { + max = 0; + } + for (List<String> cols : this.data.values()) { + if (cols != null && max < cols.size()) { + max = cols.size(); + } + } + + return max; + } + + /** + * Helps to form the rows from columns. + * + * @param isNormalize + * boolean + * @return +--------------+-----------+-----------------------------+ | header1 | header 2 | header 3 | + * +--------------+-----------+-----------------------------+ | v1 | List[line| v 3 | | | 1, line2]| | + * +--------------+-----------+-----------------------------+ | null | yyyyyy 2 | xxxxxx 3 | + * +--------------+-----------+-----------------------------+ + */ + private List<List<Object>> formRows(boolean isNormalize) { + List<List<Object>> rows = new ArrayList<>(); + + // add title + if (this.isPrintTitle()) { + List<Object> list = new ArrayList<>(); + for (String key : this.data.keySet()) { + if (isNormalize && key != null && key.length() > MAX_COLUMN_LENGTH) { + list.add(splitIntoList(key, MAX_COLUMN_LENGTH)); + } else { + list.add(key); + } + } + rows.add(list); + } + + // form row + for (int i = 0; i < this.findMaxRows(); i++) { + List<Object> row = new ArrayList<>(); + for (List<String> cols : this.data.values()) { + if (cols.size() > i) { + String value = cols.get(i); + // split the cell into multiple sub rows + if (isNormalize && value != null && value.length() > MAX_COLUMN_LENGTH) { + row.add(splitIntoList(value, MAX_COLUMN_LENGTH)); + } else { + // store as string (one entry) + row.add(value); + } + } else { + // now value exist for this column + row.add(null); + } + } + rows.add(row); + } + + return rows; + } + + /** + * Splits big strings into list of strings based on maxCharInLine size. + * + * @param input + * input string + * @param maxCharInLine + * max length + * @return list of strings + */ + public List<String> splitIntoList(String input, int maxCharInLine) { + + String inp = input; + + if (inp == null || "".equals(inp) || maxCharInLine <= 0) { + return Collections.emptyList(); + } + // new line is converted to space char + if (inp.contains("\n")) { + inp = inp.replaceAll("\n", ""); + } + + StringTokenizer tok = new StringTokenizer(inp, " "); + StringBuilder output = new StringBuilder(inp.length()); + int lineLen = 0; + while (tok.hasMoreTokens()) { + String word = tok.nextToken(); + + while (word.length() >= maxCharInLine) { + output.append(word.substring(0, maxCharInLine - lineLen) + "\n"); + word = word.substring(maxCharInLine - lineLen); + lineLen = 0; + } + + if (lineLen + word.length() >= maxCharInLine) { + output.append("\n"); + lineLen = 0; + } + output.append(word + " "); + + lineLen += word.length() + 1; + } + String[] strArray = output.toString().split("\n"); + + return Arrays.asList(strArray); + } + + /** + * Helps to print table. + * + * @param printSeparator + * Prints with line separator + * @return +--------------+-----------+-----------------------------+ | header1 | header 2 | header 3 | + * +--------------+-----------+-----------------------------+ | v1 | line 1 | v 3 | | | line 2 | | + * +--------------+-----------+-----------------------------+ | | yyyyyy 2 | xxxxxx 3 | + * +--------------+-----------+-----------------------------+ + */ + public String printTable(boolean printSeparator) { + List<List<Object>> rows = this.formRows(true); + TableGenerator table = new TableGenerator(); + return table.generateTable(rows, printSeparator); + } + + /** + * Print output in csv format. + * + * @return string + * @throws OnapCommandOutputPrintingFailed + * exception + */ + public String printCsv() throws OnapCommandOutputPrintingFailed { + StringWriter writer = new StringWriter(); + CSVPrinter printer = null; + try { + CSVFormat formattor = CSVFormat.DEFAULT.withRecordSeparator(System.getProperty("line.separator")); + printer = new CSVPrinter(writer, formattor); + + List<List<Object>> rows = this.formRows(false); + + for (int i = 0; i < this.findMaxRows(); i++) { + printer.printRecord(rows.get(i)); + } + + return writer.toString(); + } catch (IOException e) { + throw new OnapCommandOutputPrintingFailed(e); + } finally { + try { + if (printer != null) { + printer.close(); + } + writer.close(); + } catch (IOException e) { + throw new OnapCommandOutputPrintingFailed(e); // NOSONAR + } + } + } + + public String printJson() { + // (mrkanag) print in json + return null; + } + + public String printYaml() { + // (mrkanag) print in yaml + return null; + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/output/print/TableGenerator.java b/framework/src/main/java/org/onap/cli/fw/output/print/TableGenerator.java new file mode 100644 index 00000000..8be7952d --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/output/print/TableGenerator.java @@ -0,0 +1,313 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.output.print; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Printing Command result in Table format. + * + */ +public class TableGenerator { + + private static final int PADDING_SIZE = 1; + private static final String NEW_LINE = "\n"; + private static final String TABLE_JOINT_SYMBOL = "+"; + private static final String TABLE_V_SPLIT_SYMBOL = "|"; + private static final String TABLE_H_SPLIT_SYMBOL = "-"; + + /** + * Generate list of rows into table format. + * + * @param rowsList + * list of rows + * @param printSeparator + * boolean + * @return stringBuilder in tabular format + */ + public String generateTable(List<List<Object>> rowsList, boolean printSeparator) { + StringBuilder stringBuilder = new StringBuilder(); + + if (rowsList.isEmpty()) { + return stringBuilder.toString(); + } + + Map<Integer, Integer> columnMaxWidthMapping = getMaximumWidhtofColumns(rowsList); + Map<Integer, Integer> rowMaxWidthMapping = getMaximumWidhtofRows(rowsList); + + if (printSeparator) { + createRowLine(stringBuilder, rowsList.get(0).size(), columnMaxWidthMapping); + stringBuilder.append(NEW_LINE); + } + + for (int rowIndex = 0; rowIndex < rowsList.size(); rowIndex++) { + + List<Object> row = rowsList.get(rowIndex); + int splitRowSize = rowMaxWidthMapping.get(rowIndex); + if (splitRowSize > 1) { + for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) { + Object cell = row.get(cellIndex); + String finalCell; + if (cell != null) { + if (cell instanceof String) { + finalCell = (String) cell; + } else { + finalCell = ((List<String>) cell).get(0); + } + fillCell(stringBuilder, finalCell, cellIndex, columnMaxWidthMapping, printSeparator); + } + } + + stringBuilder.append(NEW_LINE); + + for (int splitCellIndex = 1; splitCellIndex < splitRowSize; splitCellIndex++) { + for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) { + Object cell = row.get(cellIndex); + String finalCell = ""; + if (cell != null && cell instanceof List) { + List<String> list = (List<String>) cell; + if (splitCellIndex < list.size()) { + finalCell = list.get(splitCellIndex); + } + } + fillCell(stringBuilder, finalCell, cellIndex, columnMaxWidthMapping, printSeparator); + } + + stringBuilder.append(NEW_LINE); + } + + } else { + for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) { + fillCell(stringBuilder, (String) row.get(cellIndex), cellIndex, columnMaxWidthMapping, + printSeparator); + } + stringBuilder.append(NEW_LINE); + } + + if (printSeparator) { + createRowLine(stringBuilder, rowsList.get(0).size(), columnMaxWidthMapping); + stringBuilder.append(NEW_LINE); + } + + } + return stringBuilder.toString(); + } + + /** + * Fill required space. + * + * @param stringBuilder + * table + * @param length + * No. of spaces + */ + private void fillSpace(StringBuilder stringBuilder, int length) { + for (int i = 0; i < length; i++) { + stringBuilder.append(" "); + } + } + + /** + * Create a new row line. + * + * @param stringBuilder + * table + * @param headersListSize + * No. of colums + * @param columnMaxWidthMapping + * mapping of columns with cell width + */ + private void createRowLine(StringBuilder stringBuilder, int headersListSize, + Map<Integer, Integer> columnMaxWidthMapping) { + for (int i = 0; i < headersListSize; i++) { + if (i == 0) { + stringBuilder.append(TABLE_JOINT_SYMBOL); + } + + for (int j = 0; j < columnMaxWidthMapping.get(i) + PADDING_SIZE * 2; j++) { + stringBuilder.append(TABLE_H_SPLIT_SYMBOL); + } + stringBuilder.append(TABLE_JOINT_SYMBOL); + } + } + + /** + * Get max width of columns. + * + * @param rowsList + * list of rows + * @return mapping of column and max cell width + */ + private Map<Integer, Integer> getMaximumWidhtofColumns(List<List<Object>> rowsList) { + Map<Integer, Integer> columnMaxWidthMapping = new HashMap<>(); + if (rowsList == null || rowsList.isEmpty()) { + return new HashMap<>(); + } + for (int columnIndex = 0; columnIndex < rowsList.get(0).size(); columnIndex++) { + columnMaxWidthMapping.put(columnIndex, 0); + } + + for (List<Object> row : rowsList) { + updateColWidth(row, columnMaxWidthMapping); + } + + for (int columnIndex = 0; columnIndex < rowsList.get(0).size(); columnIndex++) { + + if (columnMaxWidthMapping.get(columnIndex) % 2 != 0) { + columnMaxWidthMapping.put(columnIndex, columnMaxWidthMapping.get(columnIndex) + 1); + } + } + + return columnMaxWidthMapping; + } + + /** + * update the column width. + * + * @param row + * list of values + * @param columnMaxWidthMapping + * mapping of column and max cell width + */ + private void updateColWidth(List<Object> row, Map<Integer, Integer> columnMaxWidthMapping) { + for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) { + Object obj = row.get(columnIndex); + if (obj instanceof String) { + String str = (String) obj; + if (str.length() > columnMaxWidthMapping.get(columnIndex)) { + columnMaxWidthMapping.put(columnIndex, str.length()); + } + } else if (obj instanceof List) { + List<String> list = (List<String>) obj; + + int maxLength = list.get(0).length(); + + for (String str : list) { + if (str.length() > maxLength) { + maxLength = str.length(); + } + } + + if (maxLength > columnMaxWidthMapping.get(columnIndex)) { + columnMaxWidthMapping.put(columnIndex, maxLength); + } + + } + + } + } + + /** + * Get max width of rows. + * + * @param rowsList + * list of rows + * @return map of rows and max width + */ + private Map<Integer, Integer> getMaximumWidhtofRows(List<List<Object>> rowsList) { + Map<Integer, Integer> rowMaxWidthMapping = new HashMap<>(); + + for (int rowIndex = 0; rowIndex < rowsList.size(); rowIndex++) { + rowMaxWidthMapping.put(rowIndex, 1); + } + + for (int rowIndex = 0; rowIndex < rowsList.size(); rowIndex++) { + int maxSize = 1; + for (Object obj : rowsList.get(rowIndex)) { + if (obj instanceof List && ((List) obj).size() > maxSize) { + maxSize = ((List) obj).size(); + } + } + + if (maxSize > 1) { + rowMaxWidthMapping.put(rowIndex, maxSize); + } + } + return rowMaxWidthMapping; + } + + /** + * Get optimal cell padding. + * + * @param cellIndex + * cell index + * @param datalength + * data length + * @param columnMaxWidthMapping + * map of column and max cell width + * @param cellPaddingSize + * cell padding size + * @return cell padding + */ + private int getOptimumCellPadding(int cellIndex, int datalength, Map<Integer, Integer> columnMaxWidthMapping, + int cellPaddingSize) { + int datLen = datalength; + int paddingSize = cellPaddingSize; + if (datLen % 2 != 0) { + datLen++; + } + + if (datLen < columnMaxWidthMapping.get(cellIndex)) { + paddingSize = paddingSize + (columnMaxWidthMapping.get(cellIndex) - datLen) / 2; + } + + return paddingSize; + } + + /** + * Fill the cell with required value. + * + * @param stringBuilder + * table + * @param cell + * table cell value + * @param cellIndex + * cell index + * @param columnMaxWidthMapping + * map of column and max cell width + */ + private void fillCell(StringBuilder stringBuilder, String cell, int cellIndex, + Map<Integer, Integer> columnMaxWidthMapping, boolean printSeparator) { + + String filledCell = cell; + + if (filledCell == null) { + filledCell = ""; + } + int cellLength = filledCell.length(); + int cellPaddingSize = getOptimumCellPadding(cellIndex, cellLength, columnMaxWidthMapping, PADDING_SIZE); + + if (cellIndex == 0 && printSeparator) { + stringBuilder.append(TABLE_V_SPLIT_SYMBOL); + } + + stringBuilder.append(filledCell); + fillSpace(stringBuilder, cellPaddingSize); + + if (cellLength % 2 != 0) { + stringBuilder.append(" "); + } + + fillSpace(stringBuilder, cellPaddingSize); + if (printSeparator) { + stringBuilder.append(TABLE_V_SPLIT_SYMBOL); + } + + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/run/OnapCommandExecutor.java b/framework/src/main/java/org/onap/cli/fw/run/OnapCommandExecutor.java new file mode 100644 index 00000000..abd04b02 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/run/OnapCommandExecutor.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.run; + +/** + * Onap Command executor. + * + */ +public class OnapCommandExecutor { + + private String apiName; + private String clientName; + private String entityName; + private String methodName; + private String exceptionName; + + public String getApi() { + return this.apiName; + } + + public void setApi(String api) { + this.apiName = api; + } + + public String getClient() { + return this.clientName; + } + + public void setClient(String client) { + this.clientName = client; + } + + public String getEntity() { + return entityName; + } + + public void setEntity(String entity) { + this.entityName = entity; + } + + public String getMethod() { + return methodName; + } + + public void setMethod(String method) { + this.methodName = method; + } + + public String getException() { + return exceptionName; + } + + public void setException(String exception) { + this.exceptionName = exception; + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/schema/AbstractSchemaValidate.java b/framework/src/main/java/org/onap/cli/fw/schema/AbstractSchemaValidate.java new file mode 100644 index 00000000..28671521 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/schema/AbstractSchemaValidate.java @@ -0,0 +1,563 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.schema; + +import org.onap.cli.fw.error.OnapCommandInvalidSchema; +import org.onap.cli.fw.utils.OnapCommandUtils; +import org.springframework.core.io.Resource; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.parser.ParserException; + +import static org.onap.cli.fw.conf.Constants.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * Abstract schema validation class. + * + */ +public abstract class AbstractSchemaValidate implements SchemaValidate { + + /** + * Supported schema types. + * + */ + protected enum SchemaType { + HTTP, BASIC + } + + protected List<String> schemaErrors = new ArrayList<>(); + protected Map<String, Object> yamlMap = new HashMap<>(); + protected Map<String, Object> defaultYamlMap = new HashMap<>(); + + protected static final List<String> HTTP_SCHEMA_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, DESCRIPTION, + SERVICE, PARAMETERS, RESULTS, HTTP); + + protected static final List<String> HTTP_SCHEMA_MANDATORY_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, + DESCRIPTION, SERVICE, HTTP); + protected static final List<String> BASIC_SCHEMA_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, DESCRIPTION, + PARAMETERS, RESULTS); + + protected static final List<String> BASIC_SCHEMA_MANDATORY_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, + DESCRIPTION, PARAMETERS); + + protected static final List<String> TOP_LEVEL_PARAMS_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, + DESCRIPTION); + + protected static final List<String> TOP_LEVEL_MANDATORY_LIST = Arrays.asList(ONAP_CMD_SCHEMA_VERSION, NAME, + DESCRIPTION); + + protected static final List<String> SERVICE_PARAMS_LIST = Arrays.asList(NAME, VERSION, NO_AUTH); + + protected static final List<String> SERVICE_PARAMS_MANDATORY_LIST = Arrays.asList(NAME, VERSION); + + protected static final List<String> INPUT_PARAMS_LIST = Arrays.asList(NAME, DESCRIPTION, TYPE, SHORT_OPTION, + LONG_OPTION, IS_OPTIONAL, DEFAULT_VALUE, IS_SECURED); + + protected static final List<String> INPUT_PARAMS_MANDATORY_LIST = Arrays.asList(NAME, DESCRIPTION, TYPE); + + protected static final List<String> PARAMETER_TYPES = Arrays.asList(PARAMETER_TYPE_JSON, PARAMETER_TYPE_YAML, + PARAMETER_TYPE_STRING, PARAMETER_TYPE_LONG, PARAMETER_TYPE_URL, PARAMETER_TYPE_BOOL, PARAMETER_TYPE_ARRAY, + PARAMETER_TYPE_MAP, PARAMETER_TYPE_BINARY); + + protected static final List<String> RESULT_PARAMS_LIST = Arrays.asList(NAME, DESCRIPTION, TYPE, SHORT_OPTION, + LONG_OPTION, IS_OPTIONAL, DEFAULT_VALUE, IS_SECURED); + + protected static final List<String> RESULT_PARAMS_MANDATORY_LIST = Arrays.asList(NAME, DESCRIPTION, TYPE); + + protected static final List<String> HTTP_PARAMS_LIST = Arrays.asList(URI, METHOD, BODY, HEADERS, QUERIES); + + protected static final List<String> HTTP_PARAMS_MANDATORY_LIST = Arrays.asList(URI, METHOD, BODY, HEADERS, QUERIES); + + protected static final List<String> HTTP_MANDATORY_SECTIONS = Arrays.asList(REQUEST, SUCCESS_CODES); + + protected static final List<String> HTTP_SECTIONS = Arrays.asList(REQUEST, SUCCESS_CODES, RESULT_MAP, + SAMPLE_RESPONSE); + + protected static final List<String> HTTP_REQUEST_MANDATORY_PARAMS = Arrays.asList(URI, METHOD); + + protected static final List<String> HTTP_REQUEST_PARAMS = Arrays.asList(URI, METHOD, BODY, HEADERS, QUERIES); + + protected static final List<String> BOOLEAN_VALUES = Arrays.asList(BOOLEAN_TRUE, BOOLEAN_FALSE); + protected static final List<String> DIRECTIONS = Arrays.asList(DIRECTION_PORTRAIT, DIRECTION_LANDSCAPE); + protected static final List<String> RESULT_SCOPES = Arrays.asList(RESULT_SCOPE_SHORT, RESULT_SCOPE_LONG); + + protected static final List<String> HTTP_METHODS = Arrays.asList(POST, GET, DELETE, PUT, HEAD); + + /** + * Constructor. + * + * @param schemaFile + * schemafile + * @throws OnapCommandInvalidSchema + * exception + */ + public AbstractSchemaValidate(File schemaFile) throws OnapCommandInvalidSchema { + loadYaml(schemaFile); + loadDefaultYaml(); + } + + /** + * Constructor. + * + * @param schemaFile + * resourceName + * @throws OnapCommandInvalidSchema + * exception + */ + public AbstractSchemaValidate(String schemaFile) throws OnapCommandInvalidSchema { + + try { + Resource res = OnapCommandUtils.getExternalResource(schemaFile, EXTERNAL_SCHEMA_PATH_PATERN); + InputStream inputStream; + if (res == null) { + inputStream = OnapCommandUtils.class.getClassLoader().getResourceAsStream(schemaFile); + } else { + inputStream = res.getInputStream(); + } + + if (inputStream != null) { + loadYamlFromInputStream(schemaFile, inputStream); + } else { + throw new OnapCommandInvalidSchema(schemaFile, SCHEMA_FILE_NOT_EXIST); + } + + } catch (IOException e) { + throw new OnapCommandInvalidSchema(schemaFile, e); + } + loadDefaultYaml(); + } + + private final void loadYaml(File schemaFile) throws OnapCommandInvalidSchema { + if (!schemaFile.isFile()) { + throw new OnapCommandInvalidSchema(schemaFile.getName(), SCHEMA_FILE_NOT_EXIST); + } + String fileName = schemaFile.getName(); + + if (!fileName.endsWith(".yaml")) { + throw new OnapCommandInvalidSchema(fileName, SCHEMA_FILE_WRONG_EXTN); + } + + try { + InputStream inputStream = new FileInputStream(schemaFile); + loadYamlFromInputStream(schemaFile.getName(), inputStream); + } catch (FileNotFoundException e) { + throw new OnapCommandInvalidSchema(fileName, e); + } + } + + @SuppressWarnings("unchecked") + private final void loadYamlFromInputStream(String fileName, InputStream inputStream) + throws OnapCommandInvalidSchema { + try { + yamlMap = (Map<String, Object>) new Yaml().load(inputStream); + } catch (ParserException e) { + throw new OnapCommandInvalidSchema(fileName, e); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + throw new OnapCommandInvalidSchema(fileName, e); // NOSONAR + } + } + } + + if (yamlMap == null) { + throw new OnapCommandInvalidSchema(fileName, SCHEMA_FILE_EMPTY); + } + } + + @SuppressWarnings("unchecked") + private final void loadDefaultYaml() throws OnapCommandInvalidSchema { + InputStream inputStream = AbstractSchemaValidate.class.getClassLoader() + .getResourceAsStream(DEFAULT_SCHEMA_FILE_NAME); + try { + defaultYamlMap = (Map<String, Object>) new Yaml().load(inputStream); + } catch (ParserException e) { + throw new OnapCommandInvalidSchema(DEFAULT_SCHEMA_FILE_NAME, e); + } + + if (defaultYamlMap == null) { + throw new OnapCommandInvalidSchema(DEFAULT_SCHEMA_FILE_NAME, SCHEMA_FILE_EMPTY); + } + } + + /* + * Validate method. + * + * @throws OnapCommandInvalidSchema exception + */ + @Override + public List<String> validate() throws OnapCommandInvalidSchema { + + SchemaType type; + Set<String> mainSections = yamlMap.keySet(); + if (mainSections.containsAll(HTTP_SCHEMA_MANDATORY_LIST)) { + type = SchemaType.HTTP; + } else if (mainSections.containsAll(BASIC_SCHEMA_MANDATORY_LIST)) { + type = SchemaType.BASIC; + } else { + schemaErrors.add(SchemaValidate.invalidSections(mainSections, HTTP_SCHEMA_MANDATORY_LIST, + BASIC_SCHEMA_MANDATORY_LIST)); + return schemaErrors; + } + + if (type.equals(SchemaType.BASIC)) { + validateTopLevelAttributes(); + validateInputParameters(); + validateResultParameters(); + } else { + validateTopLevelAttributes(); + validateServiceAttributes(); + validateInputParameters(); + validateResultParameters(); + validateSpecificSchema(SchemaType.HTTP); + } + return schemaErrors; + } + + private void validateResultAttributes(List<Map<String, Object>> resultAttributes) { + Set<String> resultParamNames = new HashSet<>(); + for (Map<String, Object> attribute : resultAttributes) { + + // Validate mandatory parameters + validateMandatoryParams(attribute, RESULT_PARAMS_LIST, RESULT_PARAMS_MANDATORY_LIST, ATTRIBUTES); + + String name = String.valueOf(attribute.get(NAME)); + + if (resultParamNames.contains(name)) { + schemaErrors.add(SchemaValidate.attributeNameExist(name, ATTRIBUTES)); + } else { + resultParamNames.add(name); + } + + // Validate specific parameters + Object type = attribute.get(TYPE); + String value = String.valueOf(type); + if (!PARAMETER_TYPES.contains(value.toLowerCase())) { + schemaErrors.add(SchemaValidate.invalidType(ATTRIBUTES, name, PARAMETER_TYPES)); + } + + Object scope = attribute.get(SCOPE); + if (scope == null) { + schemaErrors.add(SchemaValidate.attributeScopeEmpty(name)); + } else if (!RESULT_SCOPES.contains(scope)) { + schemaErrors.add(SchemaValidate.invalidAttributeScope(name, RESULT_SCOPES)); + } + + Object isSecured = attribute.get(IS_SECURED); + if (isSecured != null) { + String value2 = String.valueOf(isSecured); + if (!validateBoolean(value2)) { + schemaErrors.add(SchemaValidate.invalidBooleanValueMessage(ATTRIBUTES, IS_SECURED, value2)); + } + } + } + + } + + private void validateResultParameters() { + @SuppressWarnings("unchecked") + Map<String, Object> resultParams = (Map<String, Object>) yamlMap.get(RESULTS); + + if (resultParams == null || resultParams.isEmpty()) { + return; + } + + Object direction = resultParams.get(DIRECTION); + + if (direction != null && !DIRECTIONS.contains(direction)) { + schemaErrors.add(SchemaValidate.invalidType(PARAMETERS, DIRECTION, DIRECTIONS)); + } + + @SuppressWarnings("unchecked") + List<Map<String, Object>> resultAttributes = (List<Map<String, Object>>) resultParams.get(ATTRIBUTES); + validateResultAttributes(resultAttributes); + } + + /** + * Get all default short options. + * + * @return set + */ + protected Set<String> getDefaultShortOptions() { + + Set<String> set = new HashSet<>(); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> inputParams = (List<Map<String, Object>>) defaultYamlMap.get(PARAMETERS); + for (Map<String, Object> parameter : inputParams) { + Object name = parameter.get(SHORT_OPTION); + if (name != null && !String.valueOf(name).isEmpty() && !"null".equals(name)) { + set.add(String.valueOf(name)); + } + } + + return set; + } + + /** + * Get all default long options. + * + * @return set + */ + protected Set<String> getDefaultLongOptions() { + + Set<String> set = new HashSet<>(); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> inputParams = (List<Map<String, Object>>) defaultYamlMap.get(PARAMETERS); + for (Map<String, Object> parameter : inputParams) { + Object name = parameter.get(LONG_OPTION); + if (name != null && !String.valueOf(name).isEmpty() && !"null".equals(name)) { + set.add(String.valueOf(name)); + } + } + + return set; + } + + private void validateTopLevelAttributes() { + validateMandatoryParams(yamlMap, TOP_LEVEL_PARAMS_LIST, TOP_LEVEL_MANDATORY_LIST, "root level"); + } + + private void validateServiceAttributes() { + + @SuppressWarnings("unchecked") + Map<String, Object> serviceMap = (Map<String, Object>) yamlMap.get(SERVICE); + + if (serviceMap == null) { + schemaErrors.add(SchemaValidate.emptySection(SERVICE)); + return; + } + + validateMandatoryParams(serviceMap, SERVICE_PARAMS_LIST, SERVICE_PARAMS_MANDATORY_LIST, SERVICE); + + // Validate specific parameters + + if (serviceMap.containsKey(NO_AUTH)) { + Object obj = serviceMap.get(NO_AUTH); + if (obj == null) { + schemaErrors.add(SchemaValidate.emptyValue(SERVICE, NO_AUTH)); + } else { + String value = String.valueOf(obj); + if (!validateBoolean(value)) { + schemaErrors.add(SchemaValidate.invalidBooleanValueMessage(SERVICE, NO_AUTH, value)); + } + } + } + + } + + private void validateInputParameters() { + + @SuppressWarnings("unchecked") + List<Map<String, Object>> inputParams = (List<Map<String, Object>>) yamlMap.get(PARAMETERS); + if (inputParams == null) { + return; + } + validateInputAttributes(inputParams); + } + + protected abstract void validateSpecificSchema(SchemaType type) throws OnapCommandInvalidSchema; + + private void validateInputAttributes(List<Map<String, Object>> inputParams) { + Set<String> inputParamNames = new HashSet<>(); + Set<String> inputShortOptions = new HashSet<>(); + Set<String> inputLongOptions = new HashSet<>(); + + Set<String> defaultShortOptions = getDefaultShortOptions(); + Set<String> defaultLongOptions = getDefaultLongOptions(); + + for (Map<String, Object> parameter : inputParams) { + + // Validate mandatory parameters + validateMandatoryParams(parameter, INPUT_PARAMS_LIST, INPUT_PARAMS_MANDATORY_LIST, PARAMETERS); + + // Validate specific parameters + + String name = String.valueOf(parameter.get(NAME)); + + if (inputParamNames.contains(name)) { + schemaErrors.add(SchemaValidate.nameExist(name, PARAMETERS)); + } else { + inputParamNames.add(name); + } + + String value = String.valueOf(parameter.get(TYPE)); + + if (!PARAMETER_TYPES.contains(value.toLowerCase())) { + schemaErrors.add(SchemaValidate.invalidAttrType(name, PARAMETERS, PARAMETER_TYPES)); + } + + Object isOptional = parameter.get(IS_OPTIONAL); + if (isOptional != null) { + String value1 = String.valueOf(isOptional); + if (!validateBoolean(value1)) { + schemaErrors.add(SchemaValidate.invalidBooleanValueMessage(name, IS_OPTIONAL, value1)); + } + } + + Object isSecured = parameter.get(IS_SECURED); + if (isSecured != null) { + String value2 = String.valueOf(isSecured); + if (!validateBoolean(value2)) { + schemaErrors.add(SchemaValidate.invalidBooleanValueMessage(name, IS_SECURED, value2)); + } + } + + String shortOption = String.valueOf(parameter.get(SHORT_OPTION)); + String longOption = String.valueOf(parameter.get(LONG_OPTION)); + + if (inputShortOptions.contains(shortOption)) { + schemaErrors.add(SchemaValidate.optionExist(SHORT_OPTION, shortOption, name)); + } else if (defaultShortOptions.contains(shortOption)) { + + schemaErrors + .add(SchemaValidate.optionDefaultExist(SHORT_OPTION, shortOption, name, defaultShortOptions)); + + } else if (shortOption != null && !shortOption.isEmpty() && !"null".equals(shortOption)) { + inputShortOptions.add(shortOption); + } + + if (inputLongOptions.contains(longOption)) { + schemaErrors.add(SchemaValidate.optionExist(LONG_OPTION, longOption, name)); + } else if (defaultLongOptions.contains(longOption)) { + + schemaErrors.add(SchemaValidate.optionDefaultExist(LONG_OPTION, longOption, name, defaultLongOptions)); + } else if (longOption != null && !longOption.isEmpty() && !"null".equals(shortOption)) { + inputLongOptions.add(longOption); + } + + } + + } + + /** + * Validate mandatory parameters. + * + * @param yamlMap + * yaml map + * @param totalParams + * list + * @param mandatoryParams + * list + * @param section + * section + */ + protected void validateMandatoryParams(Map<String, Object> yamlMap, List<String> totalParams, + List<String> mandatoryParams, String section) { + + for (String param : totalParams) { + boolean isMandatory = mandatoryParams.contains(param); + boolean isYamlContains = yamlMap.containsKey(param); + if (isMandatory) { + if (!isYamlContains) { + schemaErrors.add(SchemaValidate.mandatoryAttrMissing(param, section)); + } else { + String value = String.valueOf(yamlMap.get(param)); + if (value == null || "".equals(value) || "null".equals(value)) { + schemaErrors.add(SchemaValidate.mandatoryAttrEmpty(param, section)); + } + } + } + } + } + + /** + * Load result attributes. + * + * @return set + */ + @SuppressWarnings("unchecked") + protected Set<String> getResultAttributes() { + + Set<String> set = new HashSet<>(); + + List<Map<String, Object>> resultAttributes = yamlMap.get(RESULTS) != null + ? (List<Map<String, Object>>) ((Map<String, Object>) yamlMap.get(RESULTS)).get(ATTRIBUTES) + : Collections.emptyList(); + + if (resultAttributes != null) { + for (Map<String, Object> map : resultAttributes) { + for (Entry<String, Object> entry : map.entrySet()) { + Object key = entry.getKey(); + + if (NAME.equals(key)) { + set.add(String.valueOf(entry.getValue())); + break; + } + } + } + } + + return set; + } + + /** + * Get request parameters. + * + * @return set + */ + protected Set<String> getRequestParams() { + + Set<String> set = new HashSet<>(); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> inputParams = (List<Map<String, Object>>) yamlMap.get(PARAMETERS); + + if (inputParams != null) { + for (Map<String, Object> map : inputParams) { + for (Entry<String, Object> entry : map.entrySet()) { + Object key = entry.getKey(); + + if (NAME.equals(key)) { + set.add(String.valueOf(entry.getValue())); + break; + } + } + } + } + + return set; + } + + /** + * Validate Boolean. + * + * @param toValidate + * string + * @return boolean + */ + protected static boolean validateBoolean(String toValidate) { + return BOOLEAN_VALUES.contains(toValidate.toLowerCase()); + } +} diff --git a/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidate.java b/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidate.java new file mode 100644 index 00000000..27bc4661 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidate.java @@ -0,0 +1,324 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.schema; + +import org.onap.cli.fw.error.OnapCommandInvalidSchema; + +import java.util.List; +import java.util.Set; + +/** + * Schema validate interface. + * + */ +@FunctionalInterface +public interface SchemaValidate { + /** + * Validates HTTP or Basic Schema. + * + * @return List of errors + * @throws OnapCommandInvalidSchema + * Failed to load schema file + */ + public List<String> validate() throws OnapCommandInvalidSchema; + + /** + * Static interface method. + * + * @param section + * section + * @return errorMessage + */ + public static String defaultYamlSchema(String section) { + return "The section '" + section + ":' cann't be null or empty"; + } + + /** + * Static interface method. + * + * @param section + * string + * @param attribute + * string + * @param value + * string + * @return string + */ + public static String invalidBooleanValueMessage(String section, String attribute, String value) { + return "The value '" + value + "' of '" + attribute + "' present under '" + section + "' should be boolean"; + } + + /** + * Static interface method. + * + * @param section + * string + * @param attribute + * string + * @return string + */ + public static String emptyValue(String section, String attribute) { + return "Attribute '" + attribute + "' under '" + section + "' is null or empty"; + } + + /** + * Static interface method. + * + * @param section + * string + * @param attribute + * string + * @param types + * list + * @return string + */ + public static String invalidType(String section, String attribute, List<String> types) { + return "Attribute '" + attribute + "' under '" + section + "' is invalid, correct types are " + + types.toString(); + } + + /** + * Static interface method. + * + * @param subSection + * string + * @param attribute + * string + * @return string + */ + public static String invalidRequestParam(String subSection, String attribute) { + return "The http request '" + subSection + "' parameter '" + attribute + + "' is not declared under 'parameters:' section"; + } + + /** + * Static interface method. + * + * @param section + * string + * @return string + */ + public static String emptySection(String section) { + return "The section '" + section + ":' cann't be null or empty"; + } + + /** + * Static interface method. + * + * @param mainSections + * list + * @param http + * list + * @param basic + * list + * @return string + */ + public static String invalidSections(Set<String> mainSections, List<String> http, List<String> basic) { + return "No matching schema type found due to extra or missing sections in the file" + mainSections.toString() + + " , Supported schema sections are http" + http.toString() + " and basic" + basic.toString(); + } + + /** + * Static interface method. + * + * @param name + * string + * @param section + * string + * @return string + */ + public static String attributeNameExist(String name, String section) { + return "Attribute name='" + name + "' under '" + section + ":' is already used, Take different one."; + } + + /** + * Static interface method. + * + * @param name + * string + * @param scopes + * list + * @return string + */ + public static String invalidAttributeScope(String name, List<String> scopes) { + return "The attribute '" + name + "' scope is invalid, valid scopes are " + scopes.toString(); + } + + /** + * Static interface method. + * + * @param name + * string + * @return string + */ + public static String attributeScopeEmpty(String name) { + return "The attribute '" + name + "' scope is null or empty."; + } + + /** + * Static interface method. + * + * @param option + * string + * @param attrValue + * string + * @param name + * string + * @return string + */ + public static String optionExist(String option, String attrValue, String name) { + return "Attribute " + option + " option '" + attrValue + "' of parameter '" + name + + "' is already used, Take different one."; + } + + /** + * Static interface method. + * + * @param option + * string + * @param attrValue + * string + * @param name + * string + * @param list + * list + * @return string + */ + public static String optionDefaultExist(String option, String attrValue, String name, Set<String> list) { + return "Attribute " + option + " option '" + attrValue + "' of parameter '" + name + + "' is already used in default parameters list " + list.toString() + ", Take different one."; + } + + /** + * Static interface method. + * + * @param name + * string + * @return string + */ + public static String longOptionExist(String name) { + return "The attribute '" + name + "' scope is null or empty."; + } + + /** + * Static interface method. + * + * @param name + * string + * @return string + */ + public static String shortOptionExist(String name) { + return "The attribute '" + name + "' scope is null or empty."; + } + + /** + * Static interface method. + * + * @param name + * string + * @param section + * string + * @return string + */ + public static String nameExist(String name, String section) { + + return "Attribute name='" + name + "' under '" + section + ":' is already used, Take different one."; + } + + /** + * Static interface method. + * + * @param name + * string + * @param section + * string + * @param types + * list + * @return string + */ + public static String invalidAttrType(String name, String section, List<String> types) { + return "Attribute type of '" + name + "' under '" + section + "' is invalid, correct types are " + + types.toString(); + } + + /** + * Static interface method. + * + * @param param + * string + * @param section + * string + * @return string + */ + public static String mandatoryAttrMissing(String param, String section) { + + return "Mandatory attribute '" + param + "' is missing under '" + section + "'"; + } + + /** + * Static interface method. + * + * @param param + * string + * @param section + * string + * @return string + */ + public static String mandatoryAttrEmpty(String param, String section) { + + return "Mandatory attribute '" + param + "' under '" + section + "' shouldn't be null or empty"; + } + + /** + * Static interface method. + * + * @param attribute + * string + * @return string + */ + public static String missingInResultMap(String attribute) { + + return "The attribute '" + attribute + + "' declared under result 'attributes:' section is missing from http 'result_map:'."; + } + + /** + * Static interface method. + * + * @param attribute + * string + * @return string + */ + public static String missingInResultAttribute(String attribute) { + + return "Mapped attribute '" + attribute + "' is missing declaration in result attributes section."; + } + + /** + * Static interface method. + * + * @param declaredParam + * string + * @return string + */ + public static String parameterNotMapped(String declaredParam) { + + return "The parameter '" + declaredParam + + "' declared under 'parameters:' section is not mapped into request section."; + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidator.java b/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidator.java new file mode 100644 index 00000000..bb1248b9 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/schema/SchemaValidator.java @@ -0,0 +1,292 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.schema; + +import com.fasterxml.jackson.databind.ObjectMapper; +import net.minidev.json.JSONObject; + +import org.onap.cli.fw.error.OnapCommandInvalidSchema; + +import static org.onap.cli.fw.conf.Constants.*; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import java.util.Set; + +/** + * Schema Validation impl. + * + */ +public class SchemaValidator extends AbstractSchemaValidate { + + /** + * Constructor. + * + * @param schemaFile + * file + * @throws OnapCommandInvalidSchema + * exception + */ + public SchemaValidator(File schemaFile) throws OnapCommandInvalidSchema { + super(schemaFile); + } + + public SchemaValidator(String schemaFile) throws OnapCommandInvalidSchema { + super(schemaFile); + } + + @Override + protected void validateSpecificSchema(SchemaType type) throws OnapCommandInvalidSchema { + if (type.equals(SchemaType.HTTP)) { + validateHttpParameters(); + } + } + + @SuppressWarnings("unchecked") + private void validateHttpParameters() { + + Map<String, Object> httpMap = (Map<String, Object>) yamlMap.get(HTTP); + + if (httpMap == null || httpMap.isEmpty()) { + schemaErrors.add(HTTP_SECTION_EMPTY); + return; + } + + validateMandatoryParams(httpMap, HTTP_SECTIONS, HTTP_MANDATORY_SECTIONS, PARAMETERS); + + Map<String, Object> requestMap = (Map<String, Object>) httpMap.get(REQUEST); + + if (requestMap != null && !requestMap.isEmpty()) { + validateHttpRequestParams(requestMap); + } else { + schemaErrors.add(SchemaValidate.emptySection(REQUEST)); + } + + List<Object> requestSuccessCodes = (List<Object>) httpMap.get(SUCCESS_CODES); + if (requestSuccessCodes != null && !requestSuccessCodes.isEmpty()) { + validateHttpSccessCodes(requestSuccessCodes); + } else { + schemaErrors.add(SchemaValidate.emptySection(SUCCESS_CODES)); + } + + Map<String, Object> resultMap = (Map<String, Object>) httpMap.get(RESULT_MAP); + + if (resultMap != null && !resultMap.isEmpty()) { + validateHttpResultMapping(resultMap); + } + + Object object = httpMap.get(SAMPLE_RESPONSE); + if (object != null) { + if (object instanceof String) { + schemaErrors.add(HTTP_SAMPLE_RESPONSE_FAILED_PARSING); + } else { + validateSampleResponse((Map<String, Object>) object); + } + } + } + + private void validateHttpRequestParams(Map<String, Object> requestMap) { + + if (requestMap == null || requestMap.isEmpty()) { + return; + } + // validate mandatory parameters + validateMandatoryParams(requestMap, HTTP_REQUEST_PARAMS, HTTP_REQUEST_MANDATORY_PARAMS, REQUEST); + + // Validate method types + String method = (String) requestMap.get(METHOD); + if (method != null && !method.isEmpty()) { + if (!HTTP_METHODS.contains(method.toLowerCase())) { + schemaErrors.add(SchemaValidate.invalidType(REQUEST, METHOD, HTTP_METHODS)); + } + } else { + schemaErrors.add("Http request method cann't be null or empty"); + } + + Set<String> requestParams = getRequestParams(); + + // validate uriParams + Set<String> uriParams = validateHttpUri(requestMap); + + // validate body + Set<String> bodyParams = validateHttpBody(requestMap); + + // validate header + Set<String> headerParams = validateHttpHeaders(requestMap); + + // validate queries + Set<String> queryParams = validateHttpQueries(requestMap); + + for (String declaredParam : requestParams) { + if (!uriParams.contains(declaredParam) && !bodyParams.contains(declaredParam) + && !headerParams.contains(declaredParam) && !queryParams.contains(declaredParam)) { + schemaErrors.add(SchemaValidate.parameterNotMapped(declaredParam)); + } + } + + Set<String> totalParams = new HashSet<>(); + totalParams.addAll(uriParams); + totalParams.addAll(bodyParams); + totalParams.addAll(queryParams); + totalParams.addAll(headerParams); + + for (String definedParam : totalParams) { + if (!requestParams.contains(definedParam)) { + if (uriParams.contains(definedParam)) { + schemaErrors.add(SchemaValidate.invalidRequestParam(URI, definedParam)); + } else if (bodyParams.contains(definedParam)) { + schemaErrors.add(SchemaValidate.invalidRequestParam(BODY, definedParam)); + } else if (queryParams.contains(definedParam)) { + schemaErrors.add(SchemaValidate.invalidRequestParam(QUERIES, definedParam)); + } else if (headerParams.contains(definedParam)) { + schemaErrors.add(SchemaValidate.invalidRequestParam(HEADERS, definedParam)); + } + } + } + + } + + private Set<String> validateHttpUri(Map<String, Object> requestMap) { + Set<String> uriParamNames = new HashSet<>(); + String uri = (String) requestMap.get(URI); + if (uri == null || uri.isEmpty()) { + schemaErrors.add(SchemaValidate.emptySection(URI)); + return uriParamNames; + } + parseParameters(uri, uriParamNames); + return uriParamNames; + } + + @SuppressWarnings("unchecked") + private Set<String> validateHttpHeaders(Map<String, Object> requestMap) { + + Map<String, Object> headers = (Map<String, Object>) requestMap.get(HEADERS); + Set<String> headerParamNames = new HashSet<>(); + if (headers != null) { + for (Entry<String, Object> entry : headers.entrySet()) { + parseParameters(String.valueOf(entry.getValue()), headerParamNames); + } + } + return headerParamNames; + } + + @SuppressWarnings("unchecked") + private Set<String> validateHttpQueries(Map<String, Object> requestMap) { + Map<String, Object> queries = (Map<String, Object>) requestMap.get(QUERIES); + Set<String> queryParamNames = new HashSet<>(); + if (queries != null) { + for (Entry<String, Object> entry : queries.entrySet()) { + parseParameters(String.valueOf(entry.getValue()), queryParamNames); + } + } + return queryParamNames; + } + + private Set<String> validateHttpBody(Map<String, Object> requestMap) { + Set<String> bodyParamNames = new HashSet<>(); + Object bodyString = requestMap.get(BODY); + if (bodyString == null) { + return bodyParamNames; + } + + String body = String.valueOf(bodyString); + JSONObject obj = null; + try { + obj = new ObjectMapper().readValue(body, JSONObject.class); + } catch (IOException e1) { // NOSONAR + schemaErrors.add(HTTP_BODY_FAILED_PARSING); + } + if (obj == null || "".equals(obj.toString())) { + schemaErrors.add(HTTP_BODY_JSON_EMPTY); + } + parseParameters(body, bodyParamNames); + + return bodyParamNames; + } + + private void parseParameters(String line, Set<String> paramNames) { + + int currentIdx = 0; + while (currentIdx < line.length()) { + int idxS = line.indexOf("${", currentIdx); + if (idxS == -1) { + break; + } + int idxE = line.indexOf("}", idxS); + String paramName = line.substring(idxS + 2, idxE); + paramNames.add(paramName.trim()); + + currentIdx = idxE + 1; + } + + } + + private void validateHttpSccessCodes(List<Object> requestSuccessCodes) { + + for (Object successCode : requestSuccessCodes) { + Integer code = (Integer) successCode; + if (code < 200 || code >= 300) { + schemaErrors.add(HTTP_SUCCESS_CODE_INVALID); + } + } + + } + + private void validateHttpResultMapping(Map<String, Object> resultMap) { + Set<String> resultAttributes = getResultAttributes(); + + // Validate if all result attributes are used in the result mapping + for (String attribute : resultAttributes) { + if (!resultMap.containsKey(attribute)) { + schemaErrors.add(SchemaValidate.missingInResultMap(attribute)); + } + } + + // Validate if all result mapping keys are defined in the result attributes + for (Entry<String, Object> entry : resultMap.entrySet()) { + if (!resultAttributes.contains(entry.getKey())) { + schemaErrors.add(SchemaValidate.missingInResultAttribute(entry.getKey())); + } + } + } + + private void validateSampleResponse(Map<String, Object> sampleResponseBodyMap) { + + // validate the json + Object json = sampleResponseBodyMap.get(BODY); + if (json == null) { + schemaErrors.add(HTTP_SAMPLE_RESPONSE_EMPTY); + return; + } + String jsonString = json.toString(); + try { + if (jsonString.startsWith("[")) { + new ObjectMapper().readValue(jsonString, JSONObject[].class); + } else { + new ObjectMapper().readValue(jsonString, JSONObject.class); + } + } catch (IOException e1) { // NOSONAR + schemaErrors.add(HTTP_SAMPLE_RESPONSE_FAILED_PARSING); + } + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/utils/ExternalSchema.java b/framework/src/main/java/org/onap/cli/fw/utils/ExternalSchema.java new file mode 100644 index 00000000..e9f19673 --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/utils/ExternalSchema.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.utils; + +public class ExternalSchema { + + private String schemaName; + private String cmdName; + private String version; + + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + public String getCmdName() { + return cmdName; + } + + public void setCmdName(String cmdName) { + this.cmdName = cmdName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/framework/src/main/java/org/onap/cli/fw/utils/OnapCommandUtils.java b/framework/src/main/java/org/onap/cli/fw/utils/OnapCommandUtils.java new file mode 100644 index 00000000..79b9596c --- /dev/null +++ b/framework/src/main/java/org/onap/cli/fw/utils/OnapCommandUtils.java @@ -0,0 +1,1087 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.cli.fw.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.JsonPath; +import net.minidev.json.JSONArray; + +import org.onap.cli.fw.OnapCommand; +import org.onap.cli.fw.ad.OnapCredentials; +import org.onap.cli.fw.ad.OnapService; +import org.onap.cli.fw.cmd.OnapHttpCommand; +import org.onap.cli.fw.cmd.OnapSwaggerCommand; +import org.onap.cli.fw.conf.Constants; +import org.onap.cli.fw.error.OnapCommandDiscoveryFailed; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandHelpFailed; +import org.onap.cli.fw.error.OnapCommandHttpHeaderNotFound; +import org.onap.cli.fw.error.OnapCommandHttpInvalidResponseBody; +import org.onap.cli.fw.error.OnapCommandInvalidParameterType; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection; +import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope; +import org.onap.cli.fw.error.OnapCommandInvalidSchema; +import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion; +import org.onap.cli.fw.error.OnapCommandParameterNameConflict; +import org.onap.cli.fw.error.OnapCommandParameterNotFound; +import org.onap.cli.fw.error.OnapCommandParameterOptionConflict; +import org.onap.cli.fw.error.OnapCommandResultEmpty; +import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed; +import org.onap.cli.fw.error.OnapCommandSchemaNotFound; +import org.onap.cli.fw.http.HttpInput; +import org.onap.cli.fw.http.HttpResult; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.input.ParameterType; +import org.onap.cli.fw.output.OnapCommandResult; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.output.OnapCommandResultAttributeScope; +import org.onap.cli.fw.output.PrintDirection; +import org.onap.cli.fw.output.ResultType; +import org.onap.cli.fw.run.OnapCommandExecutor; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ServiceLoader; +import java.util.Set; + +/** + * Provides helper method to parse Yaml files and produce required objects. + * + */ +public class OnapCommandUtils { + + /** + * Private constructor. + */ + private OnapCommandUtils() { + + } + + /** + * Validates schema version. + * + * @param schemaName + * schema name + * @param version + * schema version + * @return map + * @throws OnapCommandInvalidSchemaVersion + * invalid schema version exception + * @throws OnapCommandInvalidSchema + * invalid schema + * @throws OnapCommandSchemaNotFound + * schema not found + */ + public static Map<String, ?> validateSchemaVersion(String schemaName, String version) throws OnapCommandException { + InputStream inputStream = OnapCommandUtils.class.getClassLoader().getResourceAsStream(schemaName); + + try { + Resource resource = getExternalResource(schemaName, Constants.EXTERNAL_SCHEMA_PATH_PATERN); + + if (resource != null) { + inputStream = resource.getInputStream(); + } + + } catch (IOException e) { + throw new OnapCommandSchemaNotFound(schemaName, e); + } + if (inputStream == null) { + throw new OnapCommandSchemaNotFound(schemaName); + } + + Map<String, ?> values = null; + try { + values = (Map<String, ?>) new Yaml().load(inputStream); + } catch (Exception e) { + throw new OnapCommandInvalidSchema(schemaName, e); + } + String schemaVersion = ""; + if (values.keySet().contains(Constants.ONAP_CMD_SCHEMA_VERSION)) { + Object obj = values.get(Constants.ONAP_CMD_SCHEMA_VERSION); + schemaVersion = obj.toString(); + } + + if (!version.equals(schemaVersion)) { + throw new OnapCommandInvalidSchemaVersion(schemaVersion); + } + + return values; + } + + /** + * Retrieve OnapCommand from schema. + * + * @param cmd + * OnapCommand + * @param schemaName + * schema name + * @param includeDefault + * include if default + * @throws OnapCommandParameterNameConflict + * param name conflict exception + * @throws OnapCommandParameterOptionConflict + * param option conflict exception + * @throws OnapCommandInvalidParameterType + * invalid param type exception + * @throws OnapCommandInvalidPrintDirection + * invalid print direction exception + * @throws OnapCommandInvalidResultAttributeScope + * invalid scope exception + * @throws OnapCommandSchemaNotFound + * schema not found + * @throws OnapCommandInvalidSchema + * invalid schema + * @throws OnapCommandInvalidSchemaVersion + * invalid schema version + */ + public static void loadSchema(OnapCommand cmd, String schemaName, boolean includeDefault) + throws OnapCommandException { + List<String> shortOptions = new ArrayList<>(); + List<String> longOptions = new ArrayList<>(); + List<String> names = new ArrayList<>(); + + if (includeDefault) { + loadSchema(cmd, Constants.DEFAULT_PARAMETER_FILE_NAME, shortOptions, longOptions, names); + } + + loadSchema(cmd, schemaName, shortOptions, longOptions, names); + + } + + private static void loadSchema(OnapCommand cmd, String schemaName, List<String> shortOptions, + List<String> longOptions, List<String> names) throws OnapCommandException { + try { + Map<String, ?> values = validateSchemaVersion(schemaName, cmd.getSchemaVersion()); + + for (Map.Entry<String, ?> entry : values.entrySet()) { + String key = entry.getKey(); + + if (Constants.NAME.equals(key)) { + Object val = values.get(key); + cmd.setName(val.toString()); + } else if (Constants.DESCRIPTION.equals(key)) { + Object val = values.get(key); + cmd.setDescription(val.toString()); + } else if (Constants.SERVICE.equals(key)) { + Map<String, String> map = (Map<String, String>) values.get(key); + OnapService srv = new OnapService(); + + for (Map.Entry<String, String> entry1 : map.entrySet()) { + String key1 = entry1.getKey(); + + if (Constants.NAME.equals(key1)) { + srv.setName(map.get(key1)); + } else if (Constants.VERSION.equals(key1)) { + srv.setVersion(map.get(key1)); + } else if (Constants.NO_AUTH.equals(key1)) { + Object obj = map.get(key1); + srv.setNoAuth("true".equalsIgnoreCase(obj.toString())); + } + } + + cmd.setService(srv); + } else if (Constants.PARAMETERS.equals(key)) { + List<Map<String, String>> list = (ArrayList) values.get(key); + + for (Map<String, String> map : list) { + OnapCommandParameter param = new OnapCommandParameter(); + + for (Map.Entry<String, String> entry1 : map.entrySet()) { + String key2 = entry1.getKey(); + + if (Constants.NAME.equals(key2)) { + if (names.contains(map.get(key2))) { + throw new OnapCommandParameterNameConflict(map.get(key2)); + } + names.add(map.get(key2)); + param.setName(map.get(key2)); + } else if (Constants.DESCRIPTION.equals(key2)) { + param.setDescription(map.get(key2)); + } else if (Constants.SHORT_OPTION.equals(key2)) { + if (shortOptions.contains(map.get(key2))) { + throw new OnapCommandParameterOptionConflict(map.get(key2)); + } + shortOptions.add(map.get(key2)); + param.setShortOption(map.get(key2)); + } else if (Constants.LONG_OPTION.equals(key2)) { + if (longOptions.contains(map.get(key2))) { + throw new OnapCommandParameterOptionConflict(map.get(key2)); + } + longOptions.add(map.get(key2)); + param.setLongOption(map.get(key2)); + } else if (Constants.DEFAULT_VALUE.equals(key2)) { + Object obj = map.get(key2); + param.setDefaultValue(obj.toString()); + } else if (Constants.TYPE.equals(key2)) { + param.setParameterType(ParameterType.get(map.get(key2))); + } else if (Constants.IS_OPTIONAL.equals(key2)) { + if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) { + param.setOptional(true); + } else { + param.setOptional(false); + } + } else if (Constants.IS_SECURED.equals(key2)) { + if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) { + param.setSecured(true); + } else { + param.setSecured(false); + } + } + } + cmd.getParameters().add(param); + + } + } else if (Constants.RESULTS.equals(key)) { + Map<String, ?> valueMap = (Map<String, ?>) values.get(key); + OnapCommandResult result = new OnapCommandResult(); + for (Map.Entry<String, ?> entry1 : valueMap.entrySet()) { + String key3 = entry1.getKey(); + + if (Constants.DIRECTION.equals(key3)) { + result.setPrintDirection(PrintDirection.get((String) valueMap.get(key3))); + } else if (Constants.ATTRIBUTES.equals(key3)) { + List<Map<String, String>> attrs = (ArrayList) valueMap.get(key3); + + for (Map<String, String> map : attrs) { + OnapCommandResultAttribute attr = new OnapCommandResultAttribute(); + for (Map.Entry<String, String> entry4 : map.entrySet()) { + String key4 = entry4.getKey(); + + if (Constants.NAME.equals(key4)) { + attr.setName(map.get(key4)); + } else if (Constants.DESCRIPTION.equals(key4)) { + attr.setDescription(map.get(key4)); + } else if (Constants.SCOPE.equals(key4)) { + attr.setScope(OnapCommandResultAttributeScope.get(map.get(key4))); + } else if (Constants.TYPE.equals(key4)) { + attr.setType(ParameterType.get(map.get(key4))); + } else if (Constants.IS_SECURED.equals(key4)) { + if ("true".equals(String.valueOf(map.get(key4)))) { + attr.setSecured(true); + } else { + attr.setSecured(false); + } + } + + } + result.getRecords().add(attr); + } + } + } + cmd.setResult(result); + } + } + } catch (OnapCommandException e) { + throw e; + } catch (Exception e) { + throw new OnapCommandInvalidSchema(schemaName, e); + } + } + + /** + * Load the schema. + * + * @param cmd + * OnapSwaggerBasedCommand + * @param schemaName + * schema name + * @throws OnapCommandParameterNameConflict + * param name conflict exception + * @throws OnapCommandParameterOptionConflict + * param option conflict exception + * @throws OnapCommandInvalidParameterType + * invalid param type exception + * @throws OnapCommandInvalidPrintDirection + * invalid print direction exception + * @throws OnapCommandInvalidResultAttributeScope + * invalid scope exception + * @throws OnapCommandSchemaNotFound + * schema not found + * @throws OnapCommandInvalidSchema + * invalid schema + * @throws OnapCommandInvalidSchemaVersion + * invalid schema version + */ + public static void loadSchema(OnapSwaggerCommand cmd, String schemaName) throws OnapCommandException { + try { + Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion()); + Map<String, String> valueMap = (Map<String, String>) values.get(Constants.EXECUTOR); + OnapCommandExecutor exec = new OnapCommandExecutor(); + + for (Map.Entry<String, String> entry1 : valueMap.entrySet()) { + String key1 = entry1.getKey(); + + if (Constants.API.equals(key1)) { + exec.setApi(valueMap.get(key1)); + } else if (Constants.CLIENT.equals(key1)) { + exec.setClient(valueMap.get(key1)); + } else if (Constants.ENTITY.equals(key1)) { + exec.setEntity(valueMap.get(key1)); + } else if (Constants.EXCEPTION.equals(key1)) { + exec.setException(valueMap.get(key1)); + } else if (Constants.METHOD.equals(key1)) { + exec.setMethod(valueMap.get(key1)); + } + } + + cmd.setExecutor(exec); + } catch (OnapCommandException e) { + throw e; + } catch (Exception e) { + throw new OnapCommandInvalidSchema(schemaName, e); + } + } + + /** + * Load the schema. + * + * @param cmd + * OnapHttpCommand + * @param schemaName + * schema name + * @throws OnapCommandParameterNameConflict + * param name conflict exception + * @throws OnapCommandParameterOptionConflict + * param option conflict exception + * @throws OnapCommandInvalidParameterType + * invalid param type exception + * @throws OnapCommandInvalidPrintDirection + * invalid print direction exception + * @throws OnapCommandInvalidResultAttributeScope + * invalid scope exception + * @throws OnapCommandSchemaNotFound + * schema not found + * @throws OnapCommandInvalidSchema + * invalid schema + * @throws OnapCommandInvalidSchemaVersion + * invalid schema version + */ + public static void loadSchema(OnapHttpCommand cmd, String schemaName) throws OnapCommandException { + try { + Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion()); + Map<String, ?> valMap = (Map<String, ?>) values.get(Constants.HTTP); + + for (Map.Entry<String, ?> entry1 : valMap.entrySet()) { + String key1 = entry1.getKey(); + if (Constants.REQUEST.equals(key1)) { + Map<String, ?> map = (Map<String, ?>) valMap.get(key1); + + for (Map.Entry<String, ?> entry2 : map.entrySet()) { + String key2 = entry2.getKey(); + + if (Constants.URI.equals(key2)) { + Object obj = map.get(key2); + cmd.getInput().setUri(obj.toString()); + } else if (Constants.MERHOD.equals(key2)) { + Object obj = map.get(key2); + cmd.getInput().setMethod(obj.toString()); + } else if (Constants.BODY.equals(key2)) { + Object obj = map.get(key2); + cmd.getInput().setBody(obj.toString()); + } else if (Constants.HEADERS.equals(key2)) { + Map<String, String> head = (Map<String, String>) map.get(key2); + cmd.getInput().setReqHeaders(head); + } else if (Constants.QUERIES.equals(key2)) { + Map<String, String> query = (Map<String, String>) map.get(key2); + + cmd.getInput().setReqQueries(query); + } + } + } else if (Constants.SUCCESS_CODES.equals(key1)) { + cmd.setSuccessStatusCodes((ArrayList) valMap.get(key1)); + } else if (Constants.RESULT_MAP.equals(key1)) { + cmd.setResultMap((Map<String, String>) valMap.get(key1)); + } else if (Constants.SAMPLE_RESPONSE.equals(key1)) { + // (mrkanag) implement sample response handling + } + } + + } catch (OnapCommandException e) { + throw e; + } catch (Exception e) { + throw new OnapCommandInvalidSchema(schemaName, e); + } + } + + /** + * Returns Help. + * + * @param cmd + * OnapCommand + * @return help string + * @throws OnapCommandHelpFailed + * help failed exception + */ + public static String help(OnapCommand cmd) throws OnapCommandHelpFailed { + String help = "usage: onap " + cmd.getName(); + + // Add description + help += "\n\n" + cmd.getDescription(); + + // Add service + help += "\n\nOnap service: " + cmd.getService(); + + // Add whole command + String commandOptions = ""; + + // Add parameters + OnapCommandResult paramTable = new OnapCommandResult(); + paramTable.setPrintDirection(PrintDirection.LANDSCAPE); + paramTable.setType(ResultType.TABLE); + paramTable.setIncludeTitle(false); + paramTable.setIncludeSeparator(false); + + OnapCommandResultAttribute attrName = new OnapCommandResultAttribute(); + attrName.setName(Constants.NAME); + attrName.setDescription(Constants.NAME); + attrName.setScope(OnapCommandResultAttributeScope.SHORT); + paramTable.getRecords().add(attrName); + + OnapCommandResultAttribute attrDescription = new OnapCommandResultAttribute(); + attrDescription.setName(Constants.DESCRIPTION); + attrDescription.setDescription(Constants.DESCRIPTION); + attrDescription.setScope(OnapCommandResultAttributeScope.SHORT); + paramTable.getRecords().add(attrDescription); + + int newLineOptions = 0; + for (OnapCommandParameter param : cmd.getParameters()) { + // First column Option or positional args + String optFirstCol; + if (newLineOptions == 3) { + newLineOptions = 0; + commandOptions += "\n"; + } + + if (param.getShortOption() != null || param.getLongOption() != null) { + optFirstCol = OnapCommandParameter.printShortOption(param.getShortOption()) + " | " + + OnapCommandParameter.printLongOption(param.getLongOption()); + commandOptions += "[" + optFirstCol + "] "; + } else { + optFirstCol = param.getName(); + commandOptions += "<" + optFirstCol + "> "; + } + + newLineOptions++; + + attrName.getValues().add(optFirstCol); + + // Second column description + String optSecondCol = param.getDescription().trim(); + if (!optSecondCol.endsWith(".")) { + optSecondCol += "."; + } + optSecondCol += " It is of type " + param.getParameterType().name() + "."; + + if (param.getParameterType().equals(ParameterType.JSON) + || param.getParameterType().equals(ParameterType.YAML)) { + optSecondCol += " It's recommended to input the complete path of the file, which is having the value for it."; + } + if (param.isOptional()) { + optSecondCol += " It is optional."; + } + + String defaultMsg = " By default, it is "; + if (param.isDefaultValueAnEnv()) { + optSecondCol += defaultMsg + "read from environment variable " + param.getEnvVarNameFromDefaultValue() + + "."; + } else if (param.getDefaultValue() != null && !param.getDefaultValue().isEmpty()) { + optSecondCol += defaultMsg + param.getDefaultValue() + "."; + } + + if (param.isSecured()) { + optSecondCol += " Secured."; + } + // (mrkanag) Add help msg for reading default value from env + attrDescription.getValues().add(optSecondCol); + } + + try { + help += "\n\nOptions:\n" + commandOptions + "\nwhere,\n" + paramTable.print(); + } catch (OnapCommandException e) { + throw new OnapCommandHelpFailed(e); + } + + // Add results + OnapCommandResult resultTable = new OnapCommandResult(); + resultTable.setPrintDirection(PrintDirection.PORTRAIT); + resultTable.setType(ResultType.TABLE); + resultTable.setIncludeTitle(false); + resultTable.setIncludeSeparator(false); + + for (OnapCommandResultAttribute attr : cmd.getResult().getRecords()) { + OnapCommandResultAttribute attrHelp = new OnapCommandResultAttribute(); + attrHelp.setName(attr.getName()); + attrHelp.setDescription(attr.getDescription()); + String msg = attr.getDescription() + " and is of type " + attr.getType().name() + "."; + if (attr.isSecured()) { + msg += " It is secured."; + } + attrHelp.getValues().add(msg); + attrHelp.setType(attr.getType()); + resultTable.getRecords().add(attrHelp); + } + try { + help += "\n\nResults:\n" + resultTable.print(); + } catch (OnapCommandException e) { + throw new OnapCommandHelpFailed(e); + } + + // Error + help += "\n\nError:\nOn error, it prints <HTTP STATUS CODE>::<ERROR CODE>::<ERROR MESSAGE>\n"; + return help; + } + + /** + * Helps to create OnapCredentials from default params. + * + * @param params + * list of parameters + * @return OnapCredentials + * @throws OnapCommandInvalidParameterValue + * exception + */ + public static OnapCredentials fromParameters(List<OnapCommandParameter> params) + throws OnapCommandInvalidParameterValue { + Map<String, String> paramMap = new HashMap<>(); + + for (OnapCommandParameter param : params) { + paramMap.put(param.getName(), param.getValue().toString()); + } + + return new OnapCredentials(paramMap.get(Constants.DEAFULT_PARAMETER_USERNAME), + paramMap.get(Constants.DEAFULT_PARAMETER_PASS_WORD), + paramMap.get(Constants.DEAFULT_PARAMETER_MSB_URL)); + } + + /** + * Create Dict from list of Parameters. + * + * @param inputs + * list of parameters + * @return map + */ + public static Map<String, OnapCommandParameter> getInputMap(List<OnapCommandParameter> inputs) { + Map<String, OnapCommandParameter> map = new HashMap<>(); + for (OnapCommandParameter param : inputs) { + map.put(param.getName(), param); + } + return map; + } + + /** + * Discover the Onap commands. + * + * @return list + */ + public static List<Class<OnapCommand>> findOnapCommands() { + ServiceLoader<OnapCommand> loader = ServiceLoader.load(OnapCommand.class); + List<Class<OnapCommand>> clss = new ArrayList<>(); + for (OnapCommand implClass : loader) { + clss.add((Class<OnapCommand>) implClass.getClass()); + } + + return clss; + } + + /** + * sort the set. + * + * @param col + * set + * @return list + */ + public static List<String> sort(Set<String> col) { + List<String> results = new ArrayList<>(); + results.addAll(col); + Collections.sort(results); + return results; + } + + /** + * Flatten the json list. + * + * @param jsons + * list json strings + * @return list + */ + public static List<String> jsonFlatten(List<String> jsons) { + List<String> results = new ArrayList<>(); + for (String json : jsons) { + try { + results.add(JsonPath.parse(json).jsonString()); + } catch (Exception e) { // NOSONAR + results.add(json); + } + } + + return results; + } + + /** + * Construct method name. + * + * @param name + * name + * @param prefix + * prefix + * @return string + */ + public static String formMethodNameFromAttributeName(String name, String prefix) { + if (name == null || name.isEmpty()) { + return name; + } + + String methodName = prefix; + for (String tk : name.split("-")) { + methodName += Character.toString(tk.charAt(0)).toUpperCase(); + methodName += tk.substring(1); + } + return methodName; + } + + private static String replaceLineFromInputParameters(String line, Map<String, OnapCommandParameter> params) + throws OnapCommandException { + String result = ""; + + if (!line.contains("${")) { + return line; + } + + int currentIdx = 0; + while (currentIdx < line.length()) { + int idxS = line.indexOf("${", currentIdx); + if (idxS == -1) { + result += line.substring(currentIdx); + break; + } + int idxE = line.indexOf("}", idxS); + String paramName = line.substring(idxS + 2, idxE); + paramName = paramName.trim(); + if (!params.containsKey(paramName)) { + throw new OnapCommandParameterNotFound(paramName); + } + + String value = params.get(paramName).getValue().toString(); + + OnapCommandParameter param = params.get(paramName); + if (ParameterType.ARRAY.equals(param.getParameterType()) + || ParameterType.MAP.equals(param.getParameterType()) + || ParameterType.JSON.equals(param.getParameterType()) + || ParameterType.YAML.equals(param.getParameterType())) { + // ignore the front and back double quotes in json body + result += line.substring(currentIdx, idxS - 1) + value; + currentIdx = idxE + 2; + } else { + result += line.substring(currentIdx, idxS) + value; + currentIdx = idxE + 1; + } + } + + return result; + } + + private static ArrayList<String> replaceLineFromOutputResults(String line, HttpResult resultHttp) + throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody, + OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty { + String headerProcessedLine = ""; + + ArrayList<String> result = new ArrayList<>(); + if (!line.contains("$b{") && !line.contains("$h{")) { + result.add(line); + return result; + } + + /** + * In case of empty response body [] or {} + **/ + if (resultHttp.getBody().length() <= 2) { + return result; + } + + /** + * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's + * value]-$b{$.[*].xyz} + **/ + int currentIdx = 0; + while (currentIdx < line.length()) { + int idxS = line.indexOf("$h{", currentIdx); + if (idxS == -1) { + headerProcessedLine += line.substring(currentIdx); + break; + } + int idxE = line.indexOf("}", idxS); + String headerName = line.substring(idxS + 3, idxE); + headerName = headerName.trim(); + if (!resultHttp.getRespHeaders().containsKey(headerName)) { + throw new OnapCommandHttpHeaderNotFound(headerName); + } + String value = resultHttp.getRespHeaders().get(headerName); + + headerProcessedLine += line.substring(currentIdx, idxS) + value; + currentIdx = idxE + 1; + } + + // Process body jsonpath macros + List<Object> values = new ArrayList<>(); + String bodyProcessedPattern = ""; + currentIdx = 0; + int maxRows = 1; // in normal case, only one row will be there + while (currentIdx < headerProcessedLine.length()) { + int idxS = headerProcessedLine.indexOf("$b{", currentIdx); + if (idxS == -1) { + bodyProcessedPattern += headerProcessedLine.substring(currentIdx); + break; + } + int idxE = headerProcessedLine.indexOf("}", idxS); + String jsonPath = headerProcessedLine.substring(idxS + 3, idxE); + jsonPath = jsonPath.trim(); + try { + // JSONArray or String + Object value = JsonPath.read(resultHttp.getBody(), jsonPath); + if (value instanceof JSONArray) { + JSONArray arr = (JSONArray) value; + if (arr.size() > maxRows) { + maxRows = arr.size(); + } + } + bodyProcessedPattern += headerProcessedLine.substring(currentIdx, idxS) + "%s"; + values.add(value); + currentIdx = idxE + 1; + } catch (Exception e) { + throw new OnapCommandHttpInvalidResponseBody(jsonPath, e); + } + } + + if (bodyProcessedPattern.isEmpty()) { + result.add(headerProcessedLine); + return result; + } else { + for (int i = 0; i < maxRows; i++) { + currentIdx = 0; + String bodyProcessedLine = ""; + int positionalIdx = 0; // %s positional idx + while (currentIdx < bodyProcessedPattern.length()) { + int idxS = bodyProcessedPattern.indexOf("%s", currentIdx); + if (idxS == -1) { + bodyProcessedLine += bodyProcessedPattern.substring(currentIdx); + break; + } + int idxE = idxS + 2; // %s + try { + Object value = values.get(positionalIdx); + String valueS = String.valueOf(value); + if (value instanceof JSONArray) { + JSONArray arr = (JSONArray) value; + if (!arr.isEmpty()) { + valueS = arr.get(i).toString(); + } else { + throw new OnapCommandResultEmpty(); + } + } + + bodyProcessedLine += bodyProcessedPattern.substring(currentIdx, idxS) + valueS; + currentIdx = idxE; + positionalIdx++; + } catch (OnapCommandResultEmpty e) { + throw e; + } catch (Exception e) { + throw new OnapCommandResultMapProcessingFailed(line, e); + } + } + result.add(bodyProcessedLine); + } + + return result; + } + } + + /** + * Set argument to param value. + * + * @param params + * map + * @param input + * HttpInput + * @return HttpInput + * @throws OnapCommandParameterNotFound + * exception + * @throws OnapCommandInvalidParameterValue + * exception + */ + public static HttpInput populateParameters(Map<String, OnapCommandParameter> params, HttpInput input) + throws OnapCommandException { + HttpInput inp = new HttpInput(); + for (OnapCommandParameter param : params.values()) { + if (ParameterType.BINARY.equals(param.getParameterType())) { + inp.setBinaryData(true); + break; + } + } + inp.setBody(replaceLineFromInputParameters(input.getBody(), params)); + inp.setUri(replaceLineFromInputParameters(input.getUri(), params)); + inp.setMethod(input.getMethod().toLowerCase()); + for (String h : input.getReqHeaders().keySet()) { + String value = input.getReqHeaders().get(h); + inp.getReqHeaders().put(h, replaceLineFromInputParameters(value, params)); + } + + for (String h : input.getReqQueries().keySet()) { + String value = input.getReqQueries().get(h); + inp.getReqQueries().put(h, replaceLineFromInputParameters(value, params)); + } + + return inp; + } + + /** + * Populate result. + * + * @param resultMap + * map + * @param resultHttp + * HttpResult + * @return map + * @throws OnapCommandHttpHeaderNotFound + * header not found exception + * @throws OnapCommandHttpInvalidResponseBody + * invalid response body exception + * @throws OnapCommandResultMapProcessingFailed + * map processing failed exception + */ + public static Map<String, ArrayList<String>> populateOutputs(Map<String, String> resultMap, HttpResult resultHttp) + throws OnapCommandException { + Map<String, ArrayList<String>> resultsProcessed = new HashMap<>(); + + for (Entry<String, String> entry : resultMap.entrySet()) { + String key = entry.getKey(); + resultsProcessed.put(key, replaceLineFromOutputResults(resultMap.get(key), resultHttp)); + } + + return resultsProcessed; + } + + /** + * Find external schema files. + * + * @return list ExternalSchema + * @throws OnapCommandDiscoveryFailed + * exception + * @throws OnapCommandInvalidSchema + * exception + */ + public static List<ExternalSchema> findAllExternalSchemas() throws OnapCommandException { + List<ExternalSchema> extSchemas = new ArrayList<>(); + try { + Resource[] res = getExternalResources(Constants.EXTERNAL_SCHEMA_PATH_PATERN); + if (res != null && res.length > 0) { + Map<String, ?> resourceMap; + for (Resource resource : res) { + resourceMap = getExternalSchemaMap(resource); + if (resourceMap != null && resourceMap.size() > 0) { + ExternalSchema schema = new ExternalSchema(); + schema.setSchemaName(resource.getFilename()); + schema.setCmdName((String) resourceMap.get(Constants.NAME)); + Object obj = resourceMap.get(Constants.ONAP_CMD_SCHEMA_VERSION); + schema.setVersion(obj.toString()); + extSchemas.add(schema); + } + } + } + } catch (IOException e) { + throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_SCHEMA_DIRECTORY, e); + } + + return extSchemas; + } + + /** + * Returns all resources available under certain directory in class-path. + * + * @param pattern + * search pattern + * @return resources found resources + * @throws IOException + * exception + */ + public static Resource[] getExternalResources(String pattern) throws IOException { + ClassLoader cl = OnapCommandUtils.class.getClassLoader(); + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl); + return resolver.getResources("classpath*:" + pattern); + } + + /** + * Returns a resource available under certain directory in class-path. + * + * @param pattern + * search pattern + * @return found resource + * @throws IOException + * exception + */ + public static Resource getExternalResource(String fileName, String pattern) throws IOException { + Resource[] resources = getExternalResources(pattern); + if (resources != null && resources.length > 0) { + for (Resource res : resources) { + if (res.getFilename().equals(fileName)) { + return res; + } + } + } + + return null; + } + + /** + * Get schema map. + * + * @param resource + * resource obj + * @return map + * @throws OnapCommandInvalidSchema + * exception + */ + public static Map<String, ?> getExternalSchemaMap(Resource resource) throws OnapCommandInvalidSchema { + Map<String, ?> values = null; + try { + values = (Map<String, ?>) new Yaml().load(resource.getInputStream()); + } catch (Exception e) { + throw new OnapCommandInvalidSchema(resource.getFilename(), e); + } + return values; + } + + /** + * Persist the external schema details. + * + * @param schemas + * list + * @throws OnapCommandDiscoveryFailed + * exception + */ + public static void persist(List<ExternalSchema> schemas) throws OnapCommandDiscoveryFailed { + if (schemas != null) { + try { + Resource[] resources = getExternalResources(Constants.EXTERNAL_DISCOVERY_DIRECTORY); + if (resources != null && resources.length == 1) { + String path = resources[0].getURI().getPath(); + File file = new File(path + File.separator + Constants.EXTERNAL_DISCOVERY_FILE); + ObjectMapper mapper = new ObjectMapper(); + mapper.writerWithDefaultPrettyPrinter().writeValue(file, schemas); + } + } catch (IOException e1) { + throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY, + Constants.EXTERNAL_DISCOVERY_FILE, e1); + } + } + } + + /** + * Check if json file discovered or not. + * + * @return boolean + * @throws OnapCommandDiscoveryFailed + * exception + */ + public static boolean isJsonFileDiscovered() throws OnapCommandDiscoveryFailed { + Resource resource = null; + try { + resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE, + Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN); + if (resource != null) { + return true; + } + } catch (IOException e) { + throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY, + Constants.EXTERNAL_DISCOVERY_FILE, e); + } + + return false; + } + + /** + * Load the previous discovered json file. + * + * @return list + * @throws OnapCommandInvalidSchema + * exception + * @throws OnapCommandDiscoveryFailed + * exception + */ + public static List<ExternalSchema> loadExternalSchemasFromJson() throws OnapCommandException { + List<ExternalSchema> schemas = new ArrayList<>(); + if (!isJsonFileDiscovered()) { + schemas = findAllExternalSchemas(); + if (!schemas.isEmpty()) { + persist(schemas); + } + } else { + try { + Resource resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE, + Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN); + if (resource != null) { + File file = new File(resource.getURI().getPath()); + ObjectMapper mapper = new ObjectMapper(); + ExternalSchema[] list = mapper.readValue(file, ExternalSchema[].class); + schemas.addAll(Arrays.asList(list)); + } + } catch (IOException e) { + throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY, + Constants.EXTERNAL_DISCOVERY_FILE, e); + } + } + + return schemas; + } + + /** + * Fetch a particular schema details. + * + * @param cmd + * command name + * @return ExternalSchema obj + * @throws OnapCommandInvalidSchema + * exception + * @throws OnapCommandDiscoveryFailed + * exception + */ + public static ExternalSchema loadExternalSchemaFromJson(String cmd) throws OnapCommandException { + List<ExternalSchema> list = loadExternalSchemasFromJson(); + ExternalSchema schemaStr = null; + if (list != null) { + for (ExternalSchema schema : list) { + if (cmd.equals(schema.getCmdName())) { + schemaStr = schema; + break; + } + } + } + return schemaStr; + } +} |