Repository: karaf Updated Branches: refs/heads/karaf-3.0.x 940a2d5d8 -> 575ec6d97
[KARAF-2453] - Using features to extend existing configuration Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/575ec6d9 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/575ec6d9 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/575ec6d9 Branch: refs/heads/karaf-3.0.x Commit: 575ec6d97be6575c58ca236ccbed6ad25ab11c1a Parents: 940a2d5 Author: anierbeck <[email protected]> Authored: Wed Aug 20 21:23:39 2014 +0200 Committer: anierbeck <[email protected]> Committed: Thu Aug 21 22:05:58 2014 +0200 ---------------------------------------------------------------------- .../enterprise/src/main/feature/feature.xml | 2 +- .../framework/src/main/feature/feature.xml | 2 +- .../spring/src/main/feature/feature.xml | 4 +- .../standard/src/main/feature/feature.xml | 4 +- .../features/command/InfoFeatureCommand.java | 7 +- .../org/apache/karaf/features/Conditional.java | 3 +- .../org/apache/karaf/features/ConfigInfo.java | 31 +++ .../java/org/apache/karaf/features/Feature.java | 5 +- .../karaf/features/FeaturesNamespaces.java | 6 +- .../internal/FeatureConfigInstaller.java | 84 +++++- .../internal/FeatureValidationUtil.java | 12 +- .../karaf/features/internal/model/Config.java | 54 +++- .../karaf/features/internal/model/Content.java | 40 +-- .../features/management/codec/JmxFeature.java | 39 ++- .../karaf/features/karaf-features-1.2.1.xsd | 262 +++++++++++++++++++ .../apache/karaf/features/RepositoryTest.java | 60 ++++- .../org/apache/karaf/features/repo3.xml | 35 +++ .../apache/karaf/itests/KarafTestSupport.java | 3 + .../src/it/test-aggregate-features/control.xml | 2 +- .../src/it/test-basic-generation/control.xml | 2 +- .../src/it/test-check-dependencies/control.xml | 2 +- .../src/it/test-input-file/control.xml | 2 +- .../src/it/test-type-classifier/control.xml | 2 +- .../karaf/tooling/features/model/ConfigRef.java | 41 +++ .../karaf/tooling/features/model/Feature.java | 10 +- .../tooling/features/model/Repository.java | 3 +- .../webconsole/features/ExtendedFeature.java | 4 +- 27 files changed, 628 insertions(+), 93 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/assemblies/features/enterprise/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/enterprise/src/main/feature/feature.xml b/assemblies/features/enterprise/src/main/feature/feature.xml index a228ce1..d867813 100644 --- a/assemblies/features/enterprise/src/main/feature/feature.xml +++ b/assemblies/features/enterprise/src/main/feature/feature.xml @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<features name="enterprise-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> +<features name="enterprise-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.1 http://karaf.apache.org/xmlns/features/v1.2.1"> <!-- NB: this file is not the one really used. This file is used by the karaf-maven-plugin to define the start-level of bundles in the generated feature.xml --> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/assemblies/features/framework/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/framework/src/main/feature/feature.xml b/assemblies/features/framework/src/main/feature/feature.xml index 563207a..40bcca7 100644 --- a/assemblies/features/framework/src/main/feature/feature.xml +++ b/assemblies/features/framework/src/main/feature/feature.xml @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<features name="framework-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> +<features name="framework-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.1 http://karaf.apache.org/xmlns/features/v1.2.1"> <!-- This file is not used in the assembly., This file is used by the karaf-maven-plugin to generate a "final" feature.xml including the correct start-level for the generation of the startup.propertie file --> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/assemblies/features/spring/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/spring/src/main/feature/feature.xml b/assemblies/features/spring/src/main/feature/feature.xml index 904670b..e4688e1 100644 --- a/assemblies/features/spring/src/main/feature/feature.xml +++ b/assemblies/features/spring/src/main/feature/feature.xml @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<features name="spring-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> +<features name="spring-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.1 http://karaf.apache.org/xmlns/features/v1.2.1"> <!-- NB: this file is not the one really used. This file is used by the karaf-maven-plugin to define the start-level of bundles in the generated feature.xml --> @@ -183,7 +183,7 @@ <feature name="spring-web" description="Spring 3.2.x Web support" version="${spring32.version}" resolver="(obr)"> <feature version="${spring32.version}">spring</feature> - <feature version="${http.feature.version}">http</feature> + <feature>http</feature> <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-web/${spring32.version}</bundle> <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-webmvc/${spring32.version}</bundle> </feature> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/assemblies/features/standard/src/main/feature/feature.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml index afb8976..1129023 100644 --- a/assemblies/features/standard/src/main/feature/feature.xml +++ b/assemblies/features/standard/src/main/feature/feature.xml @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<features name="standard-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> +<features name="standard-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.1 http://karaf.apache.org/xmlns/features/v1.2.1"> <repository>mvn:org.ops4j.pax.web/pax-web-features/${pax.web.version}/xml/features</repository> @@ -107,7 +107,7 @@ </feature> <feature name="http-whiteboard" description="Provide HTTP Whiteboard pattern support" version="${project.version}" resolver="(obr)"> - <feature version="${project.version}">http</feature> + <feature>http</feature> <feature version="[${pax.web.version},5)">pax-http-whiteboard</feature> </feature> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java ---------------------------------------------------------------------- diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java index 3286a2a..87b2dc2 100644 --- a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java +++ b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java @@ -27,6 +27,7 @@ import org.apache.karaf.shell.commands.Command; import org.apache.karaf.shell.commands.Option; import org.apache.karaf.features.BundleInfo; import org.apache.karaf.features.ConfigFileInfo; +import org.apache.karaf.features.ConfigInfo; import org.apache.karaf.features.Dependency; import org.apache.karaf.features.Feature; import org.apache.karaf.features.FeaturesService; @@ -160,13 +161,13 @@ public class InfoFeatureCommand extends FeaturesCommandSupport { } private void displayConfigInformation(Feature feature, String contentType) { - Map<String, Map<String, String>> configurations = feature.getConfigurations(); + List<ConfigInfo> configurations = feature.getConfigurations(); if (configurations.isEmpty()) { System.out.println(contentType + " has no configuration"); } else { System.out.println(contentType + " configuration:"); - for (String name : configurations.keySet()) { - System.out.println(INDENT + name); + for (ConfigInfo configInfo : configurations) { + System.out.println(INDENT + configInfo.getName()); } } } http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/Conditional.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/Conditional.java index c0e4d59..c381517 100644 --- a/features/core/src/main/java/org/apache/karaf/features/Conditional.java +++ b/features/core/src/main/java/org/apache/karaf/features/Conditional.java @@ -27,7 +27,8 @@ public interface Conditional { List<BundleInfo> getBundles(); - Map<String, Map<String, String>> getConfigurations(); +// Map<String, Map<String, String>> getConfigurations(); + List<ConfigInfo> getConfigurations(); List<ConfigFileInfo> getConfigurationFiles(); http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java b/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java new file mode 100644 index 0000000..f7b6b5c --- /dev/null +++ b/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.karaf.features; + +import java.util.Properties; + +public interface ConfigInfo { + + String getName(); + + String getValue(); + + Properties getProperties(); + + boolean isAppend(); + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/Feature.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/Feature.java b/features/core/src/main/java/org/apache/karaf/features/Feature.java index 4dfb624..ee43bb1 100644 --- a/features/core/src/main/java/org/apache/karaf/features/Feature.java +++ b/features/core/src/main/java/org/apache/karaf/features/Feature.java @@ -19,6 +19,8 @@ package org.apache.karaf.features; import java.util.List; import java.util.Map; +import org.apache.karaf.features.internal.model.Config; + /** * A feature is a list of bundles associated identified by its name. */ @@ -46,7 +48,8 @@ public interface Feature { List<BundleInfo> getBundles(); - Map<String, Map<String, String>> getConfigurations(); +// Map<String, Map<String, String>> getConfigurations(); + List<ConfigInfo> getConfigurations(); List<ConfigFileInfo> getConfigurationFiles(); http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java index 8e09748..d108b63 100644 --- a/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java +++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java @@ -26,14 +26,16 @@ public interface FeaturesNamespaces { String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0"; String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0"; String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0"; + String URI_1_2_1 = "http://karaf.apache.org/xmlns/features/v1.2.1"; - String URI_CURRENT = URI_1_2_0; + String URI_CURRENT = URI_1_2_1; QName FEATURES_0_0_0 = new QName("features"); QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features"); QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features"); QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features"); + QName FEATURES_1_2_1 = new QName(URI_1_2_1, "features"); - QName FEATURES_CURRENT = FEATURES_1_2_0; + QName FEATURES_CURRENT = FEATURES_1_2_1; } http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/internal/FeatureConfigInstaller.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureConfigInstaller.java index 4f26ba0..2e1b0c1 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureConfigInstaller.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureConfigInstaller.java @@ -21,12 +21,19 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import java.util.Dictionary; +import java.util.Enumeration; import java.util.Hashtable; +import java.util.List; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.karaf.features.ConfigFileInfo; +import org.apache.karaf.features.ConfigInfo; import org.apache.karaf.features.Feature; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; @@ -82,25 +89,73 @@ public class FeatureConfigInstaller { } void installFeatureConfigs(Feature feature, boolean verbose) throws IOException, InvalidSyntaxException { - for (String config : feature.getConfigurations().keySet()) { - Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config)); - String[] pid = parsePid(config); - Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]); - if (cfg == null) { - cfg = createConfiguration(configAdmin, pid[0], pid[1]); - String key = createConfigurationKey(pid[0], pid[1]); - props.put(CONFIG_KEY, key); - if (cfg.getBundleLocation() != null) { - cfg.setBundleLocation(null); - } - cfg.update(props); - } - } +// for (String config : feature.getConfigurations().keySet()) { +// Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config)); +// String[] pid = parsePid(config); +// Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]); +// if (cfg == null) { +// cfg = createConfiguration(configAdmin, pid[0], pid[1]); +// String key = createConfigurationKey(pid[0], pid[1]); +// props.put(CONFIG_KEY, key); +// if (cfg.getBundleLocation() != null) { +// cfg.setBundleLocation(null); +// } +// cfg.update(props); +// } +// } + for (ConfigInfo config : feature.getConfigurations()) { + String name = config.getName(); + Properties props = config.getProperties(); + + // interpolation(props); + + + String[] pid = parsePid(config.getName()); + Configuration cfg = findExistingConfiguration(configAdmin, pid[0], + pid[1]); + if (cfg == null) { + Dictionary<String, String> cfgProps = convertToDict(props); + + cfg = createConfiguration(configAdmin, pid[0], pid[1]); + String key = createConfigurationKey(pid[0], pid[1]); + cfgProps.put(CONFIG_KEY, key); + if (cfg.getBundleLocation() != null) { + cfg.setBundleLocation(null); + } + cfg.update(cfgProps); + } else if (config.isAppend()) { + Dictionary<String,Object> properties = cfg.getProperties(); + for (Enumeration<String> propKeys = properties.keys(); propKeys + .hasMoreElements();) { + String key = propKeys.nextElement(); + // remove existing entry, since it's about appending. + if (props.containsKey(key)) { + props.remove(key); + } + } + if (props.size() > 0) { + // convert props to dictionary + Dictionary<String, String> cfgProps = convertToDict(props); + cfg.update(cfgProps); + } + } + } for (ConfigFileInfo configFile : feature.getConfigurationFiles()) { installConfigurationFile(configFile.getLocation(), configFile.getFinalname(), configFile.isOverride(), verbose); } } + private Dictionary<String, String> convertToDict(Properties props) { + Dictionary<String, String> cfgProps = new Hashtable<String, String>(); + for (@SuppressWarnings("rawtypes") + Enumeration e = props.propertyNames(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + String val = props.getProperty(key); + cfgProps.put(key, val); + } + return cfgProps; + } + private String createConfigurationKey(String pid, String factoryPid) { return factoryPid == null ? pid : pid + "-" + factoryPid; } @@ -163,4 +218,5 @@ public class FeatureConfigInstaller { } } + } http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java index dfb7a7d..449c461 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java @@ -44,6 +44,7 @@ public class FeatureValidationUtil { public static final QName FEATURES_1_0 = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features"); public static final QName FEATURES_1_1 = new QName("http://karaf.apache.org/xmlns/features/v1.1.0", "features"); public static final QName FEATURES_1_2 = new QName("http://karaf.apache.org/xmlns/features/v1.2.0", "features"); + public static final QName FEATURES_1_2_1 = new QName("http://karaf.apache.org/xmlns/features/v1.2.1", "features"); private static final Logger LOGGER = LoggerFactory.getLogger(FeatureValidationUtil.class); /** @@ -53,6 +54,7 @@ public class FeatureValidationUtil { * @throws Exception When validation fails. */ public static void validate(URI uri) throws Exception { + LOGGER.debug("validating URI {}", uri); Document doc = load(uri); QName name = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName()); @@ -61,11 +63,17 @@ public class FeatureValidationUtil { LOGGER.warn("Old style feature file without namespace found (URI: {}). This format is deprecated and support for it will soon be removed", uri); return; } else if (FeaturesNamespaces.FEATURES_1_0_0.equals(name)) { + LOGGER.debug("validating with schema version 1.0.0"); validate(doc, "/org/apache/karaf/features/karaf-features-1.0.0.xsd"); } else if (FeaturesNamespaces.FEATURES_1_1_0.equals(name)) { - validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd"); + LOGGER.debug("validating with schema version 1.1.0"); + validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd"); } else if (FeaturesNamespaces.FEATURES_1_2_0.equals(name)) { - validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd"); + LOGGER.debug("validating with schema version 1.2.0"); + validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd"); + } else if (FeaturesNamespaces.FEATURES_1_2_1.equals(name)) { + LOGGER.debug("validating with schema version 1.2.1"); + validate(doc, "/org/apache/karaf/features/karaf-features-1.2.1.xsd"); } else { throw new IllegalArgumentException("Unrecognized root element: " + name); http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java index a2c6674..67019be 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java @@ -19,12 +19,21 @@ package org.apache.karaf.features.internal.model; +import java.io.IOException; +import java.io.StringReader; +import java.util.Enumeration; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlValue; +import org.apache.karaf.features.ConfigInfo; + /** * @@ -52,12 +61,14 @@ import javax.xml.bind.annotation.XmlValue; @XmlType(name = "config", propOrder = { "value" }) -public class Config { +public class Config implements ConfigInfo{ @XmlValue protected String value; @XmlAttribute(required = true) protected String name; + @XmlAttribute(required = false) + private Boolean append = false; /** * Gets the value of the value property. @@ -107,4 +118,45 @@ public class Config { this.name = value; } + /** + * @return the append + */ + public boolean isAppend() { + return append; + } + + /** + * @param append the append to set + */ + public void setAppend(boolean append) { + this.append = append; + } + + public Properties getProperties() { + StringReader propStream = new StringReader(getValue()); + Properties props = new Properties(); + try { + props.load(propStream); + } catch (IOException e) { + // ignore?? + } + return props; + } + + @SuppressWarnings("rawtypes") + private void interpolation(Properties properties) { + for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + String val = properties.getProperty(key); + Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val); + while (matcher.find()) { + String rep = System.getProperty(matcher.group(1)); + if (rep != null) { + val = val.replace(matcher.group(0), rep); + matcher.reset(val); + } + } + properties.put(key, val); + } + } } http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java index 756e4c1..544057d 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java @@ -27,9 +27,12 @@ import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.xml.bind.annotation.XmlTransient; + import org.apache.karaf.features.BundleInfo; import org.apache.karaf.features.ConfigFileInfo; +import org.apache.karaf.features.ConfigInfo; @XmlTransient public class Content { @@ -155,45 +158,12 @@ public class Content { return Collections.<BundleInfo>unmodifiableList(getBundle()); } - public Map<String, Map<String, String>> getConfigurations() { - Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>(); - for (Config config : getConfig()) { - String name = config.getName(); - StringReader propStream = new StringReader(config.getValue()); - Properties props = new Properties(); - try { - props.load(propStream); - } catch (IOException e) { - //ignore?? - } - interpolation(props); - Map<String, String> propMap = new HashMap<String, String>(); - for (Map.Entry<Object, Object> entry : props.entrySet()) { - propMap.put((String) entry.getKey(), (String) entry.getValue()); - } - result.put(name, propMap); - } - return result; + public List<ConfigInfo> getConfigurations() { + return Collections.<ConfigInfo>unmodifiableList(getConfig()); } public List<ConfigFileInfo> getConfigurationFiles() { return Collections.<ConfigFileInfo>unmodifiableList(getConfigfile()); } - @SuppressWarnings("rawtypes") - protected void interpolation(Properties properties) { - for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) { - String key = (String) e.nextElement(); - String val = properties.getProperty(key); - Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val); - while (matcher.find()) { - String rep = System.getProperty(matcher.group(1)); - if (rep != null) { - val = val.replace(matcher.group(0), rep); - matcher.reset(val); - } - } - properties.put(key, val); - } - } } http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java index 54fa3c0..79d00d1 100644 --- a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java +++ b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import javax.management.openmbean.TabularData; @@ -35,6 +36,7 @@ import javax.management.openmbean.TabularDataSupport; import org.apache.karaf.features.BundleInfo; import org.apache.karaf.features.ConfigFileInfo; +import org.apache.karaf.features.ConfigInfo; import org.apache.karaf.features.Dependency; import org.apache.karaf.features.Feature; import org.apache.karaf.features.management.FeaturesServiceMBean; @@ -77,7 +79,7 @@ public class JmxFeature { itemValues[1] = feature.getVersion(); itemValues[2] = getDependencyIdentifierTable(feature.getDependencies()); itemValues[3] = getBundleUris(feature.getBundles()); - itemValues[4] = getConfigTable(feature.getConfigurations()); + itemValues[4] = getConfigList(feature.getConfigurations()); itemValues[5] = getConfigFileList(feature.getConfigurationFiles()); itemValues[6] = installed; data = new CompositeDataSupport(FEATURE, itemNames, itemValues); @@ -123,16 +125,18 @@ public class JmxFeature { return array; } - static TabularData getConfigTable(Map<String, Map<String, String>> configs) throws OpenDataException { + static TabularData getConfigList(List<ConfigInfo> config) throws OpenDataException { TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_TABLE); - for (Map.Entry<String, Map<String, String>> entry : configs.entrySet()) { - String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG; - Object[] itemValues = new Object[2]; - itemValues[0] = entry.getKey(); - itemValues[1] = getConfigElementTable(entry.getValue()); - CompositeData config = new CompositeDataSupport(FEATURE_CONFIG, itemNames, itemValues); - table.put(config); - } + for (ConfigInfo configInfo : config) { + String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG; + Object[] itemValues = new Object[3]; + itemValues[0] = configInfo.getName(); + itemValues[1] = getConfigElementTable(configInfo.getProperties()); + itemValues[2] = configInfo.isAppend(); + CompositeData configComposite = new CompositeDataSupport( + FEATURE_CONFIG, itemNames, itemValues); + table.put(configComposite); + } return table; } @@ -158,6 +162,21 @@ public class JmxFeature { return table; } + static TabularData getConfigElementTable(Properties props) + throws OpenDataException { + TabularDataSupport table = new TabularDataSupport( + FEATURE_CONFIG_ELEMENT_TABLE); + for (Object key : props.keySet()) { + String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT; + Object[] itemValues = { (String) key, + props.getProperty((String) key) }; + CompositeData element = new CompositeDataSupport( + FEATURE_CONFIG_ELEMENT, itemNames, itemValues); + table.put(element); + } + return table; + } + static { FEATURE_IDENTIFIER = createFeatureIdentifierType(); http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.1.xsd ---------------------------------------------------------------------- diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.1.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.1.xsd new file mode 100644 index 0000000..5044073 --- /dev/null +++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.1.xsd @@ -0,0 +1,262 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +--> +<xs:schema elementFormDefault="qualified" + targetNamespace="http://karaf.apache.org/xmlns/features/v1.2.1" + xmlns:tns="http://karaf.apache.org/xmlns/features/v1.2.1" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:annotation> + <xs:documentation><![CDATA[ +Karaf features mechanism. For documentation please visit the +<a href="http://karaf.apache.org/">Karaf website</a>. + ]]></xs:documentation> + </xs:annotation> + + <xs:complexType name="features"> + <xs:annotation> + <xs:documentation><![CDATA[ +Root element of Feature definition. It contains an required attribute for +designating from which repository this feature should be loaded. The Karaf +shell will show the repository name when displaying information about the feature. + ]]></xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="repository" type="xs:anyURI"> + <xs:annotation> + <xs:documentation><![CDATA[ +Additional repositories where dependencies are stored. + ]]></xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="feature" type="tns:feature"> + <xs:annotation> + <xs:documentation><![CDATA[ +Feature definition. + ]]></xs:documentation> + </xs:annotation> + </xs:element> + </xs:choice> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + + <xs:complexType name="feature"> + <xs:annotation> + <xs:documentation><![CDATA[ +Definition of the Feature. + ]]></xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="details" minOccurs="0" type="xs:string"> + <xs:annotation> + <xs:documentation><![CDATA[ +The help text shown for this feature when using feature:info console command. + ]]> + </xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="config" type="tns:config" /> + <xs:element name="configfile" type="tns:configFile" /> + <xs:element name="feature" type="tns:dependency" /> + <xs:element name="bundle" type="tns:bundle" /> + <xs:element name="conditional" type="tns:conditional" /> + </xs:choice> + <xs:attribute name="name" type="tns:featureName" use="required" /> + <xs:attribute name="version" type="xs:string" default="0.0.0" /> + <xs:attribute name="description" type="xs:string" /> + <xs:attribute name="resolver" type="tns:resolver"> + <xs:annotation> + <xs:documentation><![CDATA[ +Optional alternative resolver to use for determining the list of bundles to install for a given feature. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="install" type="tns:install"> + <xs:annotation> + <xs:documentation><![CDATA[ +Marks if the feaute will be automatically started when thrown to the deploy folder. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="start-level" type="xs:int"> + <xs:annotation> + <xs:documentation><![CDATA[ +Set this attribute to have an OSGi start level for this feature different +from the default start level defined in Karaf's config.properties. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + + <xs:complexType name="conditional"> + <xs:annotation> + <xs:documentation><![CDATA[ +Definition of the Conditional. + ]]></xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="config" type="tns:config" /> + <xs:element name="configfile" type="tns:configFile" /> + <xs:element name="feature" type="tns:dependency" /> + <xs:element name="bundle" type="tns:bundle" /> + <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" /> + </xs:choice> + </xs:complexType> + + + <xs:complexType name="bundle"> + <xs:annotation> + <xs:documentation><![CDATA[ +Deployable element to install. + ]]></xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:anyURI"> + <xs:attribute name="start-level" type="xs:int"> + <xs:annotation> + <xs:documentation><![CDATA[ +Set this attribute to have an OSGi start level for this bundle different +from the default start level defined in the Karaf's config.properties. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="start" type="xs:boolean" default="true"> + <xs:annotation> + <xs:documentation><![CDATA[ +If false, leaves bundle in resolved state rather than the default active state. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="dependency" type="xs:boolean"> + <xs:annotation> + <xs:documentation><![CDATA[ +Mark this bundle as a dependency for the resolver. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="dependency"> + <xs:annotation> + <xs:documentation><![CDATA[ +Dependency of feature. + ]]></xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="tns:featureName"> + <xs:attribute name="version" type="xs:string" default="0.0.0" /> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="config"> + <xs:annotation> + <xs:documentation><![CDATA[ +Configuration entries which should be created during feature installation. This +configuration may be used with OSGi Configuration Admin. The element content is +read in as a properties file. + ]]></xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" type="xs:string" use="required" /> + <xs:attribute name="append" type="xs:boolean" use="optional"> + <xs:annotation> + <xs:documentation><![CDATA[ +Optional flag to append unknown values to the configuration. + ]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="configFile"> + <xs:annotation> + <xs:documentation><![CDATA[ +Additional configuration files which should be created during feature installation. + ]]></xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:anyURI"> + <xs:attribute name="finalname" type="xs:string" use="required"> + <xs:annotation> + <xs:documentation><![CDATA[ +The final destination path and name for the configuration file. + ]]></xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="override" type="xs:boolean"> + <xs:annotation> + <xs:documentation><![CDATA[ +If the configFile already exists at the finalname location, whether or not to replace it. + ]]></xs:documentation> + </xs:annotation> + </xs:attribute> + + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:simpleType name="featureName"> + <xs:annotation> + <xs:documentation><![CDATA[ +Feature name should be non empty string. + ]]></xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:minLength value="1" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="resolver"> + <xs:annotation> + <xs:documentation><![CDATA[ +Resolver to use. Karaf will look for OSGi service which have following properties: +objectClass: org.apache.karaf.features.Resolver +name: the value + ]]></xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:minLength value="1" /> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="install"> + <xs:annotation> + <xs:documentation><![CDATA[ +Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when +dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the +command line or as part of the org.apache.karaf.features.cfg. + ]]></xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:minLength value="1" /> + </xs:restriction> + </xs:simpleType> + <xs:element name="features" type="tns:features" /> + +</xs:schema> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java ---------------------------------------------------------------------- diff --git a/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java b/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java index cf97a20..25e3e5e 100644 --- a/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java +++ b/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java @@ -39,9 +39,10 @@ public class RepositoryTest extends TestCase { assertEquals("f1", features[0].getName()); assertNotNull(features[0].getConfigurations()); assertEquals(1, features[0].getConfigurations().size()); - assertNotNull(features[0].getConfigurations().get("c1")); - assertEquals(1, features[0].getConfigurations().get("c1").size()); - assertEquals("v", features[0].getConfigurations().get("c1").get("k")); + assertNotNull(features[0].getConfigurations().get(0).getName()); + assertEquals("c1", features[0].getConfigurations().get(0).getName()); + assertEquals(1, features[0].getConfigurations().get(0).getProperties().size()); + assertEquals("v", features[0].getConfigurations().get(0).getProperties().get("k")); assertNotNull(features[0].getDependencies()); assertEquals(0, features[0].getDependencies().size()); assertNotNull(features[0].getBundles()); @@ -81,9 +82,56 @@ public class RepositoryTest extends TestCase { assertEquals("f1", features[0].getName()); assertNotNull(features[0].getConfigurations()); assertEquals(1, features[0].getConfigurations().size()); - assertNotNull(features[0].getConfigurations().get("c1")); - assertEquals(1, features[0].getConfigurations().get("c1").size()); - assertEquals("v", features[0].getConfigurations().get("c1").get("k")); + assertNotNull(features[0].getConfigurations().get(0).getName()); + assertEquals("c1", features[0].getConfigurations().get(0).getName()); + assertEquals(1, features[0].getConfigurations().get(0).getProperties() + .size()); + assertEquals("v", features[0].getConfigurations().get(0) + .getProperties().get("k")); + assertNotNull(features[0].getDependencies()); + assertEquals(0, features[0].getDependencies().size()); + assertNotNull(features[0].getBundles()); + assertEquals(2, features[0].getBundles().size()); + assertEquals("b1", features[0].getBundles().get(0).getLocation()); + assertEquals("b2", features[0].getBundles().get(1).getLocation()); + assertNotNull(features[1]); + assertEquals("f2", features[1].getName()); + assertNotNull(features[1].getConfigurations()); + assertEquals(0, features[1].getConfigurations().size()); + assertNotNull(features[1].getDependencies()); + assertEquals(1, features[1].getDependencies().size()); + assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString()); + assertNotNull(features[1].getBundles()); + assertEquals(1, features[1].getBundles().size()); + assertEquals("b3", features[1].getBundles().get(0).getLocation()); + assertEquals("f3", features[2].getName()); + assertNotNull(features[2].getConfigurationFiles()); + assertEquals(1, features[2].getConfigurationFiles().size()); + assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname()); + assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride()); + assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation()); + } + + public void testLoadConfigAppend() throws Exception { + RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo3.xml").toURI()); + // Check repo + URI[] repos = r.getRepositories(); + assertNotNull(repos); + assertEquals(1, repos.length); + assertEquals(URI.create("urn:r1"), repos[0]); + // Check features + Feature[] features = r.getFeatures(); + assertNotNull(features); + assertEquals(3, features.length); + assertNotNull(features[0]); + assertEquals("f1", features[0].getName()); + assertNotNull(features[0].getConfigurations()); + assertEquals(1, features[0].getConfigurations().size()); + assertNotNull(features[0].getConfigurations().get(0).getName()); + assertEquals("c1", features[0].getConfigurations().get(0).getName()); + assertEquals(1, features[0].getConfigurations().get(0).getProperties().size()); + assertEquals("v", features[0].getConfigurations().get(0).getProperties().get("k")); + assertTrue(features[0].getConfigurations().get(0).isAppend()); assertNotNull(features[0].getDependencies()); assertEquals(0, features[0].getDependencies().size()); assertNotNull(features[0].getBundles()); http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/features/core/src/test/resources/org/apache/karaf/features/repo3.xml ---------------------------------------------------------------------- diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo3.xml b/features/core/src/test/resources/org/apache/karaf/features/repo3.xml new file mode 100644 index 0000000..8f06ffa --- /dev/null +++ b/features/core/src/test/resources/org/apache/karaf/features/repo3.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1"> + <repository>urn:r1</repository> + <feature name="f1" region="foo"> + <config name="c1" append="true"> + k=v + </config> + <bundle>b1</bundle> + <bundle>b2</bundle> + </feature> + <feature name="f2"> + <feature>f1</feature> + <bundle>b3</bundle> + </feature> + <feature name="f3"> + <configfile finalname="cf1" override="true">cfloc</configfile> + <bundle>b4</bundle> + </feature> +</features> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java ---------------------------------------------------------------------- diff --git a/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java b/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java index ccde975..7636afa 100644 --- a/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java +++ b/itests/src/test/java/org/apache/karaf/itests/KarafTestSupport.java @@ -19,6 +19,7 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configure import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.replaceConfigurationFile; import java.io.ByteArrayOutputStream; @@ -62,6 +63,7 @@ import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.ProbeBuilder; import org.ops4j.pax.exam.TestProbeBuilder; +import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel; import org.ops4j.pax.exam.options.MavenArtifactUrlReference; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -125,6 +127,7 @@ public class KarafTestSupport { // enable JMX RBAC security, thanks to the KarafMBeanServerBuilder configureSecurity().enableKarafMBeanServerBuilder(), keepRuntimeFolder(), + logLevel(LogLevel.DEBUG), replaceConfigurationFile("etc/org.ops4j.pax.logging.cfg", getConfigFile("/etc/org.ops4j.pax.logging.cfg")), editConfigurationFilePut("etc/org.apache.karaf.features.cfg", "featuresBoot", "config,standard,region,package,kar,management"), editConfigurationFilePut("etc/org.ops4j.pax.web.cfg", "org.osgi.service.http.port", HTTP_PORT), http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/it/test-aggregate-features/control.xml ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/it/test-aggregate-features/control.xml b/tooling/karaf-maven-plugin/src/it/test-aggregate-features/control.xml index 7c50b96..efa21fa 100644 --- a/tooling/karaf-maven-plugin/src/it/test-aggregate-features/control.xml +++ b/tooling/karaf-maven-plugin/src/it/test-aggregate-features/control.xml @@ -18,7 +18,7 @@ ~ under the License. --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="aggregate-features"> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="aggregate-features"> <feature description="aggregate-recursive-module-c" version="1.0-SNAPSHOT" name="aggregate-recursive-module-c"> <details>Test Description</details> <bundle>mvn:test/aggregate-recursive-module-b/1.0-SNAPSHOT</bundle> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/it/test-basic-generation/control.xml ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/it/test-basic-generation/control.xml b/tooling/karaf-maven-plugin/src/it/test-basic-generation/control.xml index 06139fe..facd313 100644 --- a/tooling/karaf-maven-plugin/src/it/test-basic-generation/control.xml +++ b/tooling/karaf-maven-plugin/src/it/test-basic-generation/control.xml @@ -18,4 +18,4 @@ ~ under the License. --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="test-basic-generation"/> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="test-basic-generation"/> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/it/test-check-dependencies/control.xml ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/it/test-check-dependencies/control.xml b/tooling/karaf-maven-plugin/src/it/test-check-dependencies/control.xml index a1a81c4..df4aba0 100644 --- a/tooling/karaf-maven-plugin/src/it/test-check-dependencies/control.xml +++ b/tooling/karaf-maven-plugin/src/it/test-check-dependencies/control.xml @@ -18,7 +18,7 @@ ~ under the License. --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="check-dependencies-features"> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="check-dependencies-features"> <feature description="dependency-module-c" version="1.0-SNAPSHOT" name="dependency-module-c"> <bundle>mvn:test/dependency-module-a/1.0-SNAPSHOT</bundle> <bundle>mvn:test/dependency-module-b/1.0-SNAPSHOT</bundle> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/it/test-input-file/control.xml ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/it/test-input-file/control.xml b/tooling/karaf-maven-plugin/src/it/test-input-file/control.xml index 25a2acb..795e8d9 100644 --- a/tooling/karaf-maven-plugin/src/it/test-input-file/control.xml +++ b/tooling/karaf-maven-plugin/src/it/test-input-file/control.xml @@ -18,7 +18,7 @@ ~ under the License. --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="test-input-file"> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="test-input-file"> <feature description="Test Description" version="1.0-SNAPSHOT" name="test-input-file"> <details>Test Description</details> <bundle>mvn:test/test-input-file/1.0-SNAPSHOT</bundle> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/it/test-type-classifier/control.xml ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/it/test-type-classifier/control.xml b/tooling/karaf-maven-plugin/src/it/test-type-classifier/control.xml index 9b84d85..708c26c 100644 --- a/tooling/karaf-maven-plugin/src/it/test-type-classifier/control.xml +++ b/tooling/karaf-maven-plugin/src/it/test-type-classifier/control.xml @@ -18,4 +18,4 @@ ~ under the License. --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="test-type-classifier"/> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" name="test-type-classifier"/> http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/ConfigRef.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/ConfigRef.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/ConfigRef.java new file mode 100644 index 0000000..2661381 --- /dev/null +++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/ConfigRef.java @@ -0,0 +1,41 @@ +package org.apache.karaf.tooling.features.model; + +import java.util.Hashtable; +import java.util.Map; + +public class ConfigRef { + + private String name; + private Map<String, String> properties; + private boolean append; + + public ConfigRef(String name, Map<String, String> hashtable, String append) { + this.name = name; + this.properties = hashtable; + this.append = Boolean.parseBoolean(append); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map<String, String> getProperties() { + return properties; + } + + public void setProperties(Map<String, String> properties) { + this.properties = properties; + } + + public boolean isAppend() { + return append; + } + + public void setAppend(boolean append) { + this.append = append; + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java index a818671..3372973 100644 --- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java +++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Feature.java @@ -28,7 +28,7 @@ public class Feature { private String version; private List<String> dependencies = new ArrayList<String>(); private List<BundleRef> bundles = new ArrayList<BundleRef>(); - private Map<String, Map<String, String>> configs = new HashMap<String, Map<String, String>>(); + private List<ConfigRef> configs = new ArrayList<ConfigRef>(); private List<ArtifactRef> configFiles = new ArrayList<ArtifactRef>(); public Feature(String name) { @@ -55,8 +55,8 @@ public class Feature { return bundles; } - public Map<String, Map<String, String>> getConfigurations() { - return configs; + public List<ConfigRef> getConfigurations() { + return configs; } public List<ArtifactRef> getConfigFiles() { @@ -71,8 +71,8 @@ public class Feature { bundles.add(bundle); } - public void addConfig(String name, Map<String, String> properties) { - configs.put(name, properties); + public void addConfig(ConfigRef config) { + configs.add(config); } public void addConfigFile(ArtifactRef configFile) { http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java index f3210e2..5e539cf 100644 --- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java +++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/model/Repository.java @@ -111,6 +111,7 @@ public class Repository { Element c = (Element) configNodes.item(j); String cfgName = c.getAttribute("name"); String data = c.getTextContent(); + String append = c.getAttribute("append"); Properties properties = new Properties(); properties.load(new ByteArrayInputStream(data.getBytes())); Map<String, String> hashtable = new Hashtable<String, String>(); @@ -118,7 +119,7 @@ public class Repository { String n = key.toString(); hashtable.put(n, properties.getProperty(n)); } - f.addConfig(cfgName, hashtable); + f.addConfig(new ConfigRef(cfgName, hashtable, append)); } NodeList configFileNodes = e.getElementsByTagName("configfile"); for (int j = 0; j < configFileNodes.getLength(); j++) { http://git-wip-us.apache.org/repos/asf/karaf/blob/575ec6d9/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java ---------------------------------------------------------------------- diff --git a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java index 401cf29..b726b28 100644 --- a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java +++ b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java @@ -22,6 +22,7 @@ import java.util.Map; import org.apache.karaf.features.BundleInfo; import org.apache.karaf.features.Conditional; import org.apache.karaf.features.ConfigFileInfo; +import org.apache.karaf.features.ConfigInfo; import org.apache.karaf.features.Dependency; import org.apache.karaf.features.Feature; @@ -54,7 +55,8 @@ public class ExtendedFeature implements Feature { } @Override - public Map<String, Map<String, String>> getConfigurations() { + public List<ConfigInfo> getConfigurations() { +// public Map<String, Map<String, String>> getConfigurations() { return this.feature.getConfigurations(); }
