2 * Copyright 2017 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.cli.fw.registrar;
19 import org.apache.commons.io.IOUtils;
20 import org.onap.cli.fw.cmd.OnapCommand;
21 import org.onap.cli.fw.conf.OnapCommandConfig;
22 import org.onap.cli.fw.conf.OnapCommandConstants;
23 import org.onap.cli.fw.error.OnapCommandException;
24 import org.onap.cli.fw.error.OnapCommandHelpFailed;
25 import org.onap.cli.fw.error.OnapCommandInvalidRegistration;
26 import org.onap.cli.fw.error.OnapCommandNotFound;
27 import org.onap.cli.fw.error.OnapCommandProductVersionInvalid;
28 import org.onap.cli.fw.error.OnapCommandRegistrationProductInfoMissing;
29 import org.onap.cli.fw.error.OnapUnsupportedSchemaProfile;
30 import org.onap.cli.fw.input.cache.OnapCommandParameterCache;
31 import org.onap.cli.fw.output.OnapCommandPrintDirection;
32 import org.onap.cli.fw.output.OnapCommandResult;
33 import org.onap.cli.fw.output.OnapCommandResultAttribute;
34 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
35 import org.onap.cli.fw.output.OnapCommandResultType;
36 import org.onap.cli.fw.schema.OnapCommandSchema;
37 import org.onap.cli.fw.schema.OnapCommandSchemaInfo;
38 import org.onap.cli.fw.utils.OnapCommandDiscoveryUtils;
39 import org.onap.cli.fw.utils.OnapCommandHelperUtils;
40 import org.onap.cli.fw.utils.OnapCommandUtils;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 import java.io.IOException;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.List;
53 * Oclip Command registrar provides a common place, where every command would get registered automatically when its
57 public class OnapCommandRegistrar {
59 private static Logger log = LoggerFactory.getLogger(OnapCommandRegistrar.class);
61 private Map<String, Class<? extends OnapCommand>> registry = new HashMap<>();
63 private Map<String, Class<? extends OnapCommand>> registryProfilePlugins = new HashMap<>();
65 private Set<String> availableProductVersions = new HashSet<>();
67 private String enabledProductVersion = null;
69 private boolean isInteractiveMode = false;
71 private OnapCommandParameterCache paramCache = OnapCommandParameterCache.getInstance();
73 public boolean isInteractiveMode() {
74 return isInteractiveMode;
77 public void setInteractiveMode(boolean isInteractiveMode) {
78 this.isInteractiveMode = isInteractiveMode;
81 public Map<String, String> getParamCache() {
82 return paramCache.getParams(this.getEnabledProductVersion());
85 public void addParamCache(String paramName, String paramValue) {
86 paramCache.add(this.getEnabledProductVersion(), paramName, paramValue);
89 public void removeParamCache(String paramName) {
90 paramCache.remove(this.getEnabledProductVersion(), paramName);
93 public void setProfile(String profileName, List<String> includes, List<String> excludes) {
94 this.paramCache.setProfile(profileName);
96 for (String profile : includes) {
97 this.paramCache.includeProfile(profile);
100 for (String profile : excludes) {
101 this.paramCache.excludeProfile(profile);
105 public List<String> getUserProfiles() {
106 return paramCache.getProfiles();
109 private static OnapCommandRegistrar registrar = null;
112 * Register the command into registrar and throws OnapInvalidCommandRegistration for invalid command.
114 * @param name Command Name
115 * @param cmd Command Class
116 * @throws OnapCommandRegistrationProductInfoMissing
118 private void register(String name, String version, Class<? extends OnapCommand> cmd) throws OnapCommandRegistrationProductInfoMissing {
119 if (version == null || version.isEmpty()) {
120 throw new OnapCommandRegistrationProductInfoMissing(name);
123 this.registry.put(name + ":" + version, cmd);
124 log.info("REGISITER : " + name + ":" + version + " = " + cmd.getCanonicalName());
125 this.availableProductVersions.add(version);
129 private void registerProfilePlugin(String profile, Class<? extends OnapCommand> cmd) {
130 this.registryProfilePlugins.put(profile, cmd);
133 private OnapCommandRegistrar() {
134 this.enabledProductVersion = System.getenv(OnapCommandConstants.OPEN_CLI_PRODUCT_IN_USE_ENV_NAME);
135 if (this.enabledProductVersion == null) {
136 this.enabledProductVersion = OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_PRODUCT_NAME);
141 * Get global registrar.
143 * @throws OnapCommandException exception
145 public static OnapCommandRegistrar getRegistrar() throws OnapCommandException {
146 if (registrar == null) {
147 registrar = new OnapCommandRegistrar();
148 registrar.autoDiscoverSchemas();
155 * Get the list of discovered commands by registrar.
159 public Set<String> listCommands() {
160 return this.registry.keySet();
164 * Get the list of discovered commands for a given product version in registrar.
168 public Set<String> listCommandsForEnabledProductVersion() {
169 String version = this.getEnabledProductVersion();
171 Set<String> cmds = new HashSet<>();
172 if (!this.availableProductVersions.contains(version)) {
176 for (String cmd : this.registry.keySet()) {
177 if (cmd.split(":")[1].equalsIgnoreCase(version)) {
178 cmds.add(cmd.split(":")[0]);
184 public Class<? extends OnapCommand> getProfilePlugin(String profile) throws OnapUnsupportedSchemaProfile {
185 if (!this.registryProfilePlugins.containsKey(profile)) {
186 throw new OnapUnsupportedSchemaProfile(profile);
189 return this.registryProfilePlugins.get(profile);
192 public Set<String> getAvailableProductVersions() {
193 return this.availableProductVersions;
196 public void setEnabledProductVersion(String version) throws OnapCommandProductVersionInvalid {
197 if (!this.availableProductVersions.contains(version)) {
198 throw new OnapCommandProductVersionInvalid(version, availableProductVersions);
201 this.enabledProductVersion = version;
204 public String getEnabledProductVersion() {
205 return this.enabledProductVersion;
209 * Returns command details.
212 * @throws OnapCommandException exception
214 public List<OnapCommandSchemaInfo> listCommandInfo() throws OnapCommandException {
215 return OnapCommandDiscoveryUtils.discoverSchemas();
219 * Get the OnapCommand, which CLI main would use to find the command based on the command name.
221 * @param cmdName Name of command
222 * @return OnapCommand
223 * @throws OnapCommandException Exception
225 public OnapCommand get(String cmdName) throws OnapCommandException {
226 return this.get(cmdName, this.getEnabledProductVersion());
230 * Get the OnapCommand, which CLI main would use to find the command based on the command name.
232 * @param cmdName Name of command
233 * @param version product version
234 * @return OnapCommand
235 * @throws OnapCommandException Exception
237 public OnapCommand get(String cmdName, String version) throws OnapCommandException {
238 Class<? extends OnapCommand> cls = registry.get(cmdName + ":" + version);
239 //mrkanag: Restrict auth/catalog type commands only available during devMode. in production
240 //don't expose the auth type and catalog type commands
243 throw new OnapCommandNotFound(cmdName, version);
246 OnapCommand cmd = OnapCommandDiscoveryUtils.loadCommandClass(cls);
247 String schemaName = OnapCommandDiscoveryUtils.getSchemaInfo(cmdName, version).getSchemaName();
248 cmd.initializeSchema(schemaName);
253 private Map<String, Class<OnapCommand>> autoDiscoverCommandPlugins() throws OnapCommandException {
254 List<Class<OnapCommand>> cmds = OnapCommandDiscoveryUtils.discoverCommandPlugins();
255 Map<String, Class<OnapCommand>> map = new HashMap<>();
257 for (Class<OnapCommand> cmd : cmds) {
258 if (cmd.isAnnotationPresent(OnapCommandSchema.class)) {
259 OnapCommandSchema ano = cmd.getAnnotation(OnapCommandSchema.class);
260 if (ano.schema() != null && !ano.schema().isEmpty()) {
261 map.put(ano.schema(), cmd);
262 } else if (ano.type() != null && !ano.type().isEmpty()) {
263 this.registerProfilePlugin(ano.type(), cmd);
264 map.put(ano.type(), cmd);
266 throw new OnapUnsupportedSchemaProfile(ano.schema());
274 private void autoDiscoverSchemas() throws OnapCommandException {
275 List<OnapCommandSchemaInfo> schemas = OnapCommandDiscoveryUtils.discoverOrLoadSchemas(true);
277 Map<String, Class<OnapCommand>> plugins = this.autoDiscoverCommandPlugins();
279 for (OnapCommandSchemaInfo schema : schemas) {
280 if (schema.isIgnore()) {
281 log.info("Ignoring schema " + schema.getSchemaURI());
285 //First check if there is an specific plugin exist, otherwise check for profile plugin
286 if (plugins.containsKey(schema.getSchemaName())) {
287 this.register(schema.getCmdName(), schema.getProduct(), plugins.get(schema.getSchemaName()));
288 } else if (plugins.containsKey(schema.getSchemaProfile())) {
289 this.register(schema.getCmdName(), schema.getProduct(), plugins.get(schema.getSchemaProfile()));
291 log.info("Ignoring schema " + schema.getSchemaURI());
297 * Helps to find the Oclip CLI version, could be used with --version or -v option.
301 public String getVersion() {
302 String version = this.getClass().getPackage().getImplementationVersion();
303 if (version == null) {
304 version = OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_VERSION);
307 String buildTime = OnapCommandHelperUtils.findLastBuildTime();
308 if (buildTime != null && !buildTime.isEmpty()) {
309 buildTime = " [" + buildTime + "]";
314 String configuredProductVersion = this.getEnabledProductVersion();
316 String versionInfo = "";
318 versionInfo = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream(OnapCommandConstants.VERSION_INFO));
319 } catch (IOException e) { // NOSONAR
323 versionInfo = versionInfo.replaceAll(OnapCommandConstants.VERSION_INFO_PLACE_HOLDER_ENB_PRD_VER, configuredProductVersion);
324 versionInfo = versionInfo.replaceAll(OnapCommandConstants.VERSION_INFO_PLACE_HOLDER_AVL_PRD_VER, this.availableProductVersions.toString());
325 versionInfo = versionInfo.replaceAll(OnapCommandConstants.VERSION_INFO_PLACE_HOLDER_VERSION + "", version + buildTime);
331 * Provides the help message in tabular format for all commands registered in this registrar.
334 * @throws OnapCommandHelpFailed Help cmd failed
336 public String getHelp() throws OnapCommandHelpFailed {
337 return this.getHelp(false);
340 public String getHelpForEnabledProductVersion() throws OnapCommandHelpFailed {
341 return this.getHelp(true);
344 private String getHelp(boolean isEnabledProductVersionOnly) throws OnapCommandHelpFailed {
345 OnapCommandResult help = new OnapCommandResult();
346 help.setType(OnapCommandResultType.TABLE);
347 help.setPrintDirection(OnapCommandPrintDirection.LANDSCAPE);
349 OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
350 attr.setName(OnapCommandConstants.NAME.toUpperCase());
351 attr.setDescription(OnapCommandConstants.DESCRIPTION);
352 attr.setScope(OnapCommandResultAttributeScope.SHORT);
353 help.getRecords().add(attr);
355 OnapCommandResultAttribute attrVer = new OnapCommandResultAttribute();
356 if (!isEnabledProductVersionOnly) {
357 attrVer.setName(OnapCommandConstants.INFO_PRODUCT.toUpperCase());
358 attrVer.setDescription(OnapCommandConstants.DESCRIPTION);
359 attrVer.setScope(OnapCommandResultAttributeScope.SHORT);
360 help.getRecords().add(attrVer);
363 OnapCommandResultAttribute attrSrv = new OnapCommandResultAttribute();
364 attrSrv.setName(OnapCommandConstants.INFO_SERVICE.toUpperCase());
365 attrSrv.setDescription(OnapCommandConstants.INFO_SERVICE);
366 attrSrv.setScope(OnapCommandResultAttributeScope.SHORT);
367 help.getRecords().add(attrSrv);
369 OnapCommandResultAttribute attrState = new OnapCommandResultAttribute();
370 attrState.setName(OnapCommandConstants.INFO_STATE.toUpperCase());
371 attrState.setDescription(OnapCommandConstants.INFO_STATE);
372 attrState.setScope(OnapCommandResultAttributeScope.SHORT);
373 help.getRecords().add(attrState);
376 OnapCommandResultAttribute attrDesc = new OnapCommandResultAttribute();
377 attrDesc.setName(OnapCommandConstants.DESCRIPTION.toUpperCase());
378 attrDesc.setDescription(OnapCommandConstants.DESCRIPTION);
379 attrDesc.setScope(OnapCommandResultAttributeScope.SHORT);
380 help.getRecords().add(attrDesc);
382 for (String cmdName : isEnabledProductVersionOnly ?
383 OnapCommandUtils.sort(this.listCommandsForEnabledProductVersion()) :
384 OnapCommandUtils.sort(this.listCommands())) {
387 if (!isEnabledProductVersionOnly) {
388 String[] cmdVer = cmdName.split(":");
389 cmd = this.get(cmdVer[0], cmdVer[1]);
390 attr.getValues().add(cmdVer[0]);
391 attrVer.getValues().add(cmdVer[1]);
393 cmd = this.get(cmdName);
394 attr.getValues().add(cmdName);
397 attrSrv.getValues().add(cmd.getInfo().getService());
398 attrDesc.getValues().add(cmd.getDescription());
399 attrState.getValues().add(cmd.getInfo().getState().name());
400 } catch (OnapCommandException e) {
401 throw new OnapCommandHelpFailed(e);
406 return "\n\nCommands:\n" + help.print() + (isEnabledProductVersionOnly ? "" : "\n" + this.getVersion());
407 } catch (OnapCommandException e) {
408 throw new OnapCommandHelpFailed(e);
412 public List<Map<String, ?>> getTestSuite(String cmd) throws OnapCommandException {
413 return OnapCommandDiscoveryUtils.createTestSuite(cmd, enabledProductVersion);