This is an automated email from the ASF dual-hosted git repository. jbonofre pushed a commit to branch karaf-4.3.x in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/karaf-4.3.x by this push: new 92ee273 KARAF-7289 - Provide config property name completion using MetaType info 92ee273 is described below commit 92ee273dca9e5bde239ecfd2f6f4616823d78228 Author: jassuncao <joao.assun...@exploitsys.com> AuthorDate: Wed Dec 8 19:40:09 2021 +0000 KARAF-7289 - Provide config property name completion using MetaType info ConfigurationPropertyCompleter now uses the MetaType service to retrieve configuration property names in addition to the ones already defined in the configuration. Adds an utility method in MetaServiceCaller to find MetaType info for a specified PID. This method accepts a function to do something with the result. MetaCommand is refactored to use this function. Change-Id: Ieab22ed2daaefa55675fbb2eb41e77ac534b5251 (cherry picked from commit 939ce7ae9f2dcd6b60ab3d42e5d58e8498b9f53e) --- .../apache/karaf/config/command/MetaCommand.java | 72 +++++----------------- .../completers/ConfigurationPropertyCompleter.java | 62 +++++++++++++++++-- .../karaf/config/core/impl/MetaServiceCaller.java | 66 ++++++++++++++++++++ 3 files changed, 139 insertions(+), 61 deletions(-) diff --git a/config/src/main/java/org/apache/karaf/config/command/MetaCommand.java b/config/src/main/java/org/apache/karaf/config/command/MetaCommand.java index 3687bb7..165aea3 100644 --- a/config/src/main/java/org/apache/karaf/config/command/MetaCommand.java +++ b/config/src/main/java/org/apache/karaf/config/command/MetaCommand.java @@ -16,16 +16,18 @@ */ package org.apache.karaf.config.command; -import static org.apache.karaf.config.core.impl.MetaServiceCaller.withMetaTypeService; +import static org.apache.karaf.config.core.impl.MetaServiceCaller.doWithMetaType; import java.io.IOException; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import java.util.Optional; import java.util.function.Function; import org.apache.karaf.config.command.completers.MetaCompleter; +import org.apache.karaf.config.core.impl.MetaServiceCaller.MetaInfo; import org.apache.karaf.shell.api.action.Argument; import org.apache.karaf.shell.api.action.Command; import org.apache.karaf.shell.api.action.Completion; @@ -34,13 +36,10 @@ import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.apache.karaf.shell.api.action.lifecycle.Service; import org.apache.karaf.shell.support.CommandException; import org.apache.karaf.shell.support.table.ShellTable; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.metatype.AttributeDefinition; -import org.osgi.service.metatype.MetaTypeInformation; -import org.osgi.service.metatype.MetaTypeService; import org.osgi.service.metatype.ObjectClassDefinition; @Command(scope = "config", name = "meta", description = "Lists meta type information.") @@ -77,9 +76,9 @@ public class MetaCommand extends ConfigCommandSupport { public Object doExecute() throws Exception { try { if (create) { - withMetaTypeService(context, new Create()); + doWithMetaType(context, pid, new Create()); } else { - withMetaTypeService(context, new Print()); + doWithMetaType(context, pid, new Print()); } return null; } catch (Throwable e) { @@ -95,7 +94,7 @@ public class MetaCommand extends ConfigCommandSupport { } } - abstract class AbstractMeta implements Function<MetaTypeService, Void> { + abstract class AbstractMeta implements Function<Optional<MetaInfo>, Void> { protected String getDefaultValueStr(String[] defaultValues) { if (defaultValues == null) { return ""; @@ -112,43 +111,19 @@ public class MetaCommand extends ConfigCommandSupport { } return result.toString(); } - - protected MetaInfo getMetatype(MetaTypeService metaTypeService, String pid) { - if (metaTypeService != null) { - for (Bundle bundle : context.getBundles()) { - MetaTypeInformation info = metaTypeService.getMetaTypeInformation(bundle); - if (info == null) { - continue; - } - String[] pids = info.getPids(); - for (String cPid : pids) { - if (cPid.equals(pid)) { - return new MetaInfo(info.getObjectClassDefinition(cPid, null), false); - } - } - pids = info.getFactoryPids(); - for (String cPid : pids) { - if (cPid.equals(pid)) { - return new MetaInfo(info.getObjectClassDefinition(cPid, null), true); - } - } - } - } - return null; - } + } class Create extends AbstractMeta { - public Void apply(MetaTypeService metaTypeService) { - MetaInfo info = getMetatype(metaTypeService, pid); - if (info == null) { + public Void apply(Optional<MetaInfo> info) { + if (!info.isPresent()) { System.out.println("No meta type definition found for pid: " + pid); return null; } try { - createDefaultConfig(pid, info); + createDefaultConfig(pid, info.get()); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } @@ -156,13 +131,13 @@ public class MetaCommand extends ConfigCommandSupport { } private void createDefaultConfig(String pid, MetaInfo info) throws IOException { - AttributeDefinition[] attrs = info.definition.getAttributeDefinitions(ObjectClassDefinition.ALL); + AttributeDefinition[] attrs = info.getDefinition().getAttributeDefinitions(ObjectClassDefinition.ALL); if (attrs == null) { return; } ConfigurationAdmin configAdmin = configRepository.getConfigAdmin(); Configuration config; - if(info.factory) { + if(info.isFactory()) { config = configAdmin.createFactoryConfiguration(pid, null); } else { @@ -181,13 +156,12 @@ public class MetaCommand extends ConfigCommandSupport { } class Print extends AbstractMeta { - public Void apply(MetaTypeService metaTypeService) { - MetaInfo info = getMetatype(metaTypeService, pid); - if (info == null) { + public Void apply(Optional<MetaInfo> info) { + if (!info.isPresent()) { System.out.println("No meta type definition found for pid: " + pid); return null; } - if(info.factory) { + if(info.get().isFactory()) { System.out.println("Meta type informations for factory pid: " + pid); } else { @@ -199,7 +173,7 @@ public class MetaCommand extends ConfigCommandSupport { table.column("type"); table.column("default"); table.column("description").wrap(); - AttributeDefinition[] attrs = info.definition.getAttributeDefinitions(ObjectClassDefinition.ALL); + AttributeDefinition[] attrs = info.get().getDefinition().getAttributeDefinitions(ObjectClassDefinition.ALL); if (attrs != null) { for (AttributeDefinition attr : attrs) { table.addRow().addContent(attr.getID(), attr.getName(), getType(attr.getType()), @@ -214,17 +188,5 @@ public class MetaCommand extends ConfigCommandSupport { return typeMap.get(type); } - } - - private static class MetaInfo { - final ObjectClassDefinition definition; - final boolean factory; - - MetaInfo(ObjectClassDefinition definition, boolean factory) { - - this.definition = definition; - this.factory = factory; - } - - } + } } diff --git a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java index cc0f58e..b42a0cf 100644 --- a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java +++ b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java @@ -19,24 +19,33 @@ package org.apache.karaf.config.command.completers; +import static org.apache.karaf.config.core.impl.MetaServiceCaller.doWithMetaType; + import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import org.apache.karaf.config.command.ConfigCommandSupport; +import org.apache.karaf.config.core.impl.MetaServiceCaller.MetaInfo; import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.apache.karaf.shell.api.action.lifecycle.Service; import org.apache.karaf.shell.api.console.CommandLine; import org.apache.karaf.shell.api.console.Completer; import org.apache.karaf.shell.api.console.Session; import org.apache.karaf.shell.support.completers.StringsCompleter; +import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.metatype.AttributeDefinition; +import org.osgi.service.metatype.ObjectClassDefinition; /** * {@link Completer} for Configuration Admin properties. @@ -52,6 +61,9 @@ public class ConfigurationPropertyCompleter implements Completer { @Reference private ConfigurationAdmin configAdmin; + + @Reference + private BundleContext context; public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) { StringsCompleter strings = new StringsCompleter(); @@ -98,12 +110,12 @@ public class ConfigurationPropertyCompleter implements Completer { @SuppressWarnings("rawtypes") private Set<String> getPropertyNames(String pid) { Set<String> propertyNames = new HashSet<>(); - if (pid != null) { - Configuration configuration = null; + if (pid != null) { try { + String metaPid = pid; Configuration[] configs = configAdmin.listConfigurations("(service.pid="+pid+")"); if (configs != null && configs.length > 0) { - configuration = configs[0]; + Configuration configuration = configs[0]; if (configuration != null) { Dictionary properties = configuration.getProcessedProperties(null); if (properties != null) { @@ -111,15 +123,52 @@ public class ConfigurationPropertyCompleter implements Completer { while (keys.hasMoreElements()) { propertyNames.add(String.valueOf(keys.nextElement())); } - } + } + //If we have a factory config that is the PID to use + if(configuration.getFactoryPid()!=null) { + metaPid = configuration.getFactoryPid(); + } } - } + } + //Try to fetch additional properties from the Metatype service + List<String> metaTypeProperties = getMetaTypeProperties(metaPid); + propertyNames.addAll(metaTypeProperties); } catch (IOException | InvalidSyntaxException e) { //Ignore - } + } } return propertyNames; } + + private List<String> getMetaTypeProperties(String pid){ + try { + return doWithMetaType(context, pid, this::collectMetaConfigProperties); + } catch (Throwable e) { + Throwable ncdfe = e; + while (ncdfe != null && !(ncdfe instanceof NoClassDefFoundError)) { + ncdfe = ncdfe.getCause(); + } + if (ncdfe != null && ncdfe.getMessage().equals("org/osgi/service/metatype/MetaTypeService")) { + //It seems we don't have MetaTypeService + } else { + throw e; + } + } + return Collections.emptyList(); + + } + + private List<String> collectMetaConfigProperties(Optional<MetaInfo> info){ + Optional<AttributeDefinition[]> attrs = info.map(e -> e.getDefinition().getAttributeDefinitions(ObjectClassDefinition.ALL)); + if(attrs.isPresent()) { + List<String> properties = new ArrayList<>(attrs.get().length); + for (AttributeDefinition attr : attrs.get()) { + properties.add(attr.getID()); + } + return properties; + } + return Collections.emptyList(); + } public ConfigurationAdmin getConfigAdmin() { return configAdmin; @@ -128,4 +177,5 @@ public class ConfigurationPropertyCompleter implements Completer { public void setConfigAdmin(ConfigurationAdmin configAdmin) { this.configAdmin = configAdmin; } + } diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/MetaServiceCaller.java b/config/src/main/java/org/apache/karaf/config/core/impl/MetaServiceCaller.java index 1dccbdb..87efeeb 100644 --- a/config/src/main/java/org/apache/karaf/config/core/impl/MetaServiceCaller.java +++ b/config/src/main/java/org/apache/karaf/config/core/impl/MetaServiceCaller.java @@ -21,10 +21,12 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.metatype.MetaTypeInformation; import org.osgi.service.metatype.MetaTypeService; +import org.osgi.service.metatype.ObjectClassDefinition; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.function.Function; /** @@ -66,4 +68,68 @@ public class MetaServiceCaller { return pids1; }); } + + /** + * Attempts to find MetaType information for the specified PID and + * invokes the supplied callback with the result of the search + */ + public static <T> T doWithMetaType(BundleContext context, String pid, Function<Optional<MetaInfo>, T> function) { + ServiceReference<MetaTypeService> ref = context.getServiceReference(MetaTypeService.class); + if (ref != null) { + try { + MetaTypeService metaService = context.getService(ref); + MetaInfo metaInfo = getMetatype(context, metaService, pid); + return function.apply(Optional.ofNullable(metaInfo)); + } finally { + context.ungetService(ref); + } + } + return null; + } + + private static MetaInfo getMetatype(BundleContext context, MetaTypeService metaTypeService, String pid) { + if (metaTypeService != null) { + for (Bundle bundle : context.getBundles()) { + MetaTypeInformation info = metaTypeService.getMetaTypeInformation(bundle); + if (info == null) { + continue; + } + String[] pids = info.getPids(); + for (String cPid : pids) { + if (cPid.equals(pid)) { + return new MetaInfo(info.getObjectClassDefinition(cPid, null), false); + } + } + pids = info.getFactoryPids(); + for (String cPid : pids) { + if (cPid.equals(pid)) { + return new MetaInfo(info.getObjectClassDefinition(cPid, null), true); + } + } + } + } + return null; + } + + public static class MetaInfo { + private final ObjectClassDefinition definition; + private final boolean factory; + + MetaInfo(ObjectClassDefinition definition, boolean factory) { + + this.definition = definition; + this.factory = factory; + } + + public ObjectClassDefinition getDefinition() { + + return definition; + } + + public boolean isFactory() { + + return factory; + } + + } }