You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2017/04/11 10:18:11 UTC
[1/4] karaf git commit: [KARAF-5082] Support external configurations
Repository: karaf
Updated Branches:
refs/heads/master b3572bff5 -> 9f89d2c72
[KARAF-5082] Support external configurations
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/9f89d2c7
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/9f89d2c7
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/9f89d2c7
Branch: refs/heads/master
Commit: 9f89d2c723f7022d9fd79c52cca8f65b4942602e
Parents: 02dede3
Author: Guillaume Nodet <gn...@apache.org>
Authored: Mon Apr 10 17:43:31 2017 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Apr 11 12:17:52 2017 +0200
----------------------------------------------------------------------
.../org/apache/karaf/features/ConfigInfo.java | 2 +
.../karaf/features/FeaturesNamespaces.java | 6 +-
.../karaf/features/internal/model/Config.java | 10 +
.../karaf/features/internal/model/JaxbUtil.java | 3 +
.../service/FeatureConfigInstaller.java | 6 +-
.../karaf/features/karaf-features-1.5.0.xsd | 337 +++++++++++++++++++
.../apache/karaf/itests/ExternalConfigTest.java | 79 +++++
.../assembly/AssemblyDeployCallback.java | 50 +--
.../apache/karaf/profile/assembly/Builder.java | 62 ++--
.../src/it/test-aggregate-features/control.xml | 2 +-
.../src/it/test-basic-generation/control.xml | 2 +-
.../test-check-dependencies-failure/control.xml | 2 +-
.../src/it/test-check-dependencies/control.xml | 2 +-
.../it/test-feature-dependencies/control.xml | 2 +-
.../test-feature-use-base-version/control.xml | 2 +-
.../control.xml | 2 +-
.../control.xml | 2 +-
.../test-feature-use-version-range/control.xml | 2 +-
.../test-include-project-artifact/control.xml | 2 +-
.../src/it/test-input-file/control.xml | 2 +-
.../src/it/test-rename-main-feature/control.xml | 2 +-
.../it/test-repository-dependencies/control.xml | 2 +-
.../src/it/test-simplify-bundles/control.xml | 2 +-
.../src/it/test-type-classifier/control.xml | 2 +-
24 files changed, 518 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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
index f7b6b5c..76ea330 100644
--- a/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java
+++ b/features/core/src/main/java/org/apache/karaf/features/ConfigInfo.java
@@ -28,4 +28,6 @@ public interface ConfigInfo {
boolean isAppend();
+ boolean isExternal();
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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 48237a8..a4fc589 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
@@ -30,8 +30,9 @@ public interface FeaturesNamespaces {
String URI_1_2_1 = "http://karaf.apache.org/xmlns/features/v1.2.1";
String URI_1_3_0 = "http://karaf.apache.org/xmlns/features/v1.3.0";
String URI_1_4_0 = "http://karaf.apache.org/xmlns/features/v1.4.0";
+ String URI_1_5_0 = "http://karaf.apache.org/xmlns/features/v1.5.0";
- String URI_CURRENT = URI_1_4_0;
+ String URI_CURRENT = URI_1_5_0;
QName FEATURES_0_0_0 = new QName("features");
QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
@@ -40,7 +41,8 @@ public interface FeaturesNamespaces {
QName FEATURES_1_2_1 = new QName(URI_1_2_1, "features");
QName FEATURES_1_3_0 = new QName(URI_1_3_0, "features");
QName FEATURES_1_4_0 = new QName(URI_1_4_0, "features");
+ QName FEATURES_1_5_0 = new QName(URI_1_5_0, "features");
- QName FEATURES_CURRENT = FEATURES_1_4_0;
+ QName FEATURES_CURRENT = FEATURES_1_5_0;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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 8fed515..167de33 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
@@ -53,6 +53,8 @@ public class Config implements ConfigInfo {
protected String name;
@XmlAttribute(required = false)
private Boolean append = false;
+ @XmlAttribute
+ private Boolean external = false;
/**
* Gets the value of the value property.
@@ -108,6 +110,14 @@ public class Config implements ConfigInfo {
this.append = append;
}
+ public boolean isExternal() {
+ return external;
+ }
+
+ public void setExternal(boolean external) {
+ this.external = external;
+ }
+
public Properties getProperties() {
Properties props = new Properties();
try {
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
index 6c63d16..ef307f4 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
@@ -164,6 +164,9 @@ public final class JaxbUtil {
case FeaturesNamespaces.URI_1_4_0:
schemaLocation = "/org/apache/karaf/features/karaf-features-1.4.0.xsd";
break;
+ case FeaturesNamespaces.URI_1_5_0:
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.5.0.xsd";
+ break;
default:
throw new IllegalArgumentException("Unsupported namespace: " + namespace);
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
index c95104c..92700b5 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -104,7 +104,11 @@ public class FeatureConfigInstaller {
TypedProperties props = new TypedProperties();
// trim lines
String val = config.getValue();
- props.load(new StringReader(val));
+ if (config.isExternal()) {
+ props.load(new URL(val));
+ } else {
+ props.load(new StringReader(val));
+ }
String[] pid = parsePid(config.getName());
Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
if (cfg == null) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.5.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.5.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.5.0.xsd
new file mode 100644
index 0000000..a970576
--- /dev/null
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.5.0.xsd
@@ -0,0 +1,337 @@
+<?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.5.0"
+ xmlns:tns="http://karaf.apache.org/xmlns/features/v1.5.0"
+ 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 feature repository where dependencies are stored.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-repository" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional OSGi Resource Repository where OSGi resources 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:sequence>
+ <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:element name="requirement" type="tns:requirement" />
+ <xs:element name="capability" type="tns:capability" />
+ <xs:element name="library" type="tns:library" />
+ </xs:choice>
+ <xs:element name="scoping" minOccurs="0" maxOccurs="1" type="tns:scoping" />
+ </xs:sequence>
+ <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="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:attribute name="hidden" type="xs:boolean" default="false" />
+ </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:attribute name="prerequisite" type="xs:boolean" default="false"/>
+ <xs:attribute name="dependency" type="xs:boolean" default="false"/>
+ </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:attribute name="external" type="xs:boolean" use="optional">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Specifies that this configuration is external, i.e. the content of this element
+points to the URL where the configuration can be downloaded from.
+ ]]>
+ </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:complexType name="requirement">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional requirements of this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="prerequisite" type="xs:boolean" default="false"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="capability">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional capability of this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="library">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional capability of this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="type" type="tns:libraryType" default="default"/>
+ <xs:attribute name="export" type="xs:boolean" default="false"/>
+ <xs:attribute name="delegate" type="xs:boolean" default="false"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="libraryType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="endorsed"/>
+ <xs:enumeration value="extension"/>
+ <xs:enumeration value="boot"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="scoping">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Scoping definition for this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="import" type="tns:scopeFilter"/>
+ <xs:element name="export" type="tns:scopeFilter"/>
+ </xs:choice>
+ <xs:attribute name="acceptDependencies" type="xs:boolean"/>
+ </xs:complexType>
+
+ <xs:complexType name="scopeFilter">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="namespace" type="xs:string" use="required"/>
+ </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="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/9f89d2c7/itests/src/test/java/org/apache/karaf/itests/ExternalConfigTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/ExternalConfigTest.java b/itests/src/test/java/org/apache/karaf/itests/ExternalConfigTest.java
new file mode 100644
index 0000000..468a92f
--- /dev/null
+++ b/itests/src/test/java/org/apache/karaf/itests/ExternalConfigTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.apache.karaf.itests;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.sshd.common.util.io.IoUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class ExternalConfigTest extends KarafTestSupport {
+
+ @Test
+ public void externalConfigTest() throws Exception {
+ Path dir = Paths.get(System.getProperty("karaf.base"), "system/org/foo/bar/1.0-SNAPSHOT");
+ Files.createDirectories(dir);
+ try (BufferedWriter w = Files.newBufferedWriter(dir.resolve("bar-1.0-SNAPSHOT.properties"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
+ w.write("key=value");
+ }
+ try (BufferedWriter w = Files.newBufferedWriter(dir.resolve("bar-1.0-SNAPSHOT-features.xml"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
+ w.write("<features name='org.foo'>\n" +
+ " <feature name='bar' version='1.0-SNAPSHOT'>\n" +
+ " <config name='org.foo' external='true'>\n" +
+ " mvn:org.foo/bar/1.0-SNAPSHOT/properties" +
+ " </config>\n" +
+ " </feature>\n" +
+ "</features>\n");
+ }
+
+ ConfigurationAdmin ca = getOsgiService(ConfigurationAdmin.class);
+
+ Configuration[] cfgs = ca.listConfigurations("(service.pid=org.foo)");
+ assertNull(cfgs);
+
+ getOsgiService(FeaturesService.class)
+ .addRepository(URI.create("mvn:org.foo/bar/1.0-SNAPSHOT/xml/features"), true);
+
+ cfgs = ca.listConfigurations("(service.pid=org.foo)");
+ assertNotNull(cfgs);
+ assertEquals(1, cfgs.length);
+ assertEquals("value", cfgs[0].getProperties().get("key"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
index 026bf10..cce511f 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
@@ -136,30 +136,42 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
}
}
// Install
+ Downloader downloader = manager.createDownloader();
for (Config config : ((Feature) feature).getConfig()) {
- Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
- LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
- if (!Files.exists(configFile)) {
- Files.write(configFile, config.getValue().getBytes());
- } else if (config.isAppend()) {
- Files.write(configFile, config.getValue().getBytes(), StandardOpenOption.APPEND);
+ if (config.isExternal()) {
+ downloader.download(config.getValue().trim(), provider -> {
+ Path input = provider.getFile().toPath();
+ byte[] data = Files.readAllBytes(input);
+ Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
+ LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
+ if (!Files.exists(configFile)) {
+ Files.write(configFile, data);
+ } else if (config.isAppend()) {
+ Files.write(configFile, data, StandardOpenOption.APPEND);
+ }
+ });
+ } else {
+ byte[] data = config.getValue().getBytes();
+ Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
+ LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
+ if (!Files.exists(configFile)) {
+ Files.write(configFile, data);
+ } else if (config.isAppend()) {
+ Files.write(configFile, data, StandardOpenOption.APPEND);
+ }
}
}
- Downloader downloader = manager.createDownloader();
for (final ConfigFile configFile : ((Feature) feature).getConfigfile()) {
- downloader.download(configFile.getLocation(), new DownloadCallback() {
- @Override
- public void downloaded(StreamProvider provider) throws Exception {
- Path input = provider.getFile().toPath();
- String path = configFile.getFinalname();
- if (path.startsWith("/")) {
- path = path.substring(1);
- }
- path = substFinalName(path);
- Path output = homeDirectory.resolve(path);
- LOGGER.info(" adding config file: {}", path);
- Files.copy(input, output, StandardCopyOption.REPLACE_EXISTING);
+ downloader.download(configFile.getLocation(), provider -> {
+ Path input = provider.getFile().toPath();
+ String path = configFile.getFinalname();
+ if (path.startsWith("/")) {
+ path = path.substring(1);
}
+ path = substFinalName(path);
+ Path output = homeDirectory.resolve(path);
+ LOGGER.info(" adding config file: {}", path);
+ Files.copy(input, output, StandardCopyOption.REPLACE_EXISTING);
});
}
List<String> libraries = new ArrayList<>();
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 1b57729..371a18f 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -68,6 +68,7 @@ import org.apache.karaf.features.internal.model.Bundle;
import org.apache.karaf.features.internal.model.Conditional;
import org.apache.karaf.features.internal.model.Config;
import org.apache.karaf.features.internal.model.ConfigFile;
+import org.apache.karaf.features.internal.model.Content;
import org.apache.karaf.features.internal.model.Dependency;
import org.apache.karaf.features.internal.model.Feature;
import org.apache.karaf.features.internal.model.Features;
@@ -906,29 +907,33 @@ public class Builder {
}
}
}
- // Install config files
- for (ConfigFile configFile : feature.getConfigfile()) {
- installArtifact(downloader, configFile.getLocation().trim());
- }
- for (Conditional cond : feature.getConditional()) {
- for (ConfigFile configFile : cond.getConfigfile()) {
- installArtifact(downloader, configFile.getLocation().trim());
+ List<Content> contents = new ArrayList<>();
+ contents.add(feature);
+ contents.addAll(feature.getConditional());
+ for (Content content : contents) {
+ // Install config files
+ for (Config config : content.getConfig()) {
+ if (config.isExternal()) {
+ installArtifact(downloader, config.getValue().trim());
+ }
}
- }
- // Extract configs
- for (Config config : feature.getConfig()) {
- if (pidMatching(config.getName())) {
- Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
- LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
- Files.write(configFile, config.getValue().getBytes());
+ for (ConfigFile configFile : content.getConfigfile()) {
+ installArtifact(downloader, configFile.getLocation().trim());
}
- }
- for (Conditional cond : feature.getConditional()) {
- for (Config config : cond.getConfig()) {
+ // Extract configs
+ for (Config config : content.getConfig()) {
if (pidMatching(config.getName())) {
Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
- Files.write(configFile, config.getValue().getBytes());
+ if (config.isExternal()) {
+ downloader.download(config.getValue().trim(), provider -> {
+ synchronized (provider) {
+ Files.copy(provider.getFile().toPath(), configFile, StandardCopyOption.REPLACE_EXISTING);
+ }
+ });
+ } else {
+ Files.write(configFile, config.getValue().getBytes());
+ }
}
}
}
@@ -1224,18 +1229,15 @@ public class Builder {
// for bad formed URL (like in Camel for mustache-compiler), we remove the trailing /
location = location.substring(0, location.length() - 1);
}
- downloader.download(location, new DownloadCallback() {
- @Override
- public void downloaded(final StreamProvider provider) throws Exception {
- String uri = provider.getUrl();
- if (Blacklist.isBundleBlacklisted(blacklistedBundles, uri)) {
- throw new RuntimeException("Bundle " + uri + " is blacklisted");
- }
- Path path = pathFromProviderUrl(uri);
- synchronized (provider) {
- Files.createDirectories(path.getParent());
- Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
- }
+ downloader.download(location, provider -> {
+ String uri = provider.getUrl();
+ if (Blacklist.isBundleBlacklisted(blacklistedBundles, uri)) {
+ throw new RuntimeException("Bundle " + uri + " is blacklisted");
+ }
+ Path path = pathFromProviderUrl(uri);
+ synchronized (provider) {
+ Files.createDirectories(path.getParent());
+ Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
}
});
} else {
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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 81e1844..1508054 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.4.0" name="aggregate-features">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="aggregate-features">
<feature description="aggregate-recursive-module-c" version="1.0.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/9f89d2c7/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 1d4ca2a..b0cecdb 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.4.0" name="test-basic-generation"/>
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-basic-generation"/>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-check-dependencies-failure/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-check-dependencies-failure/control.xml b/tooling/karaf-maven-plugin/src/it/test-check-dependencies-failure/control.xml
index 9e7ef4e..d4b982b 100644
--- a/tooling/karaf-maven-plugin/src/it/test-check-dependencies-failure/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-check-dependencies-failure/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="check-dependencies-features">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="check-dependencies-features">
<feature description="dependency-module-c" version="1.0.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/9f89d2c7/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 9e7ef4e..d4b982b 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.4.0" name="check-dependencies-features">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="check-dependencies-features">
<feature description="dependency-module-c" version="1.0.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/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-feature-dependencies/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-feature-dependencies/control.xml b/tooling/karaf-maven-plugin/src/it/test-feature-dependencies/control.xml
index d0f9b53..e859c84 100644
--- a/tooling/karaf-maven-plugin/src/it/test-feature-dependencies/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-feature-dependencies/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="dependencies-features">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="dependencies-features">
<feature name="dependency-feature-a" description="dependency-feature-a" version="1.0.0.SNAPSHOT">
<feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">dependency-feature-c</feature>
<bundle>mvn:test/dependency-bundle-a/1.0-SNAPSHOT</bundle>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-feature-use-base-version/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-feature-use-base-version/control.xml b/tooling/karaf-maven-plugin/src/it/test-feature-use-base-version/control.xml
index 60e46d6..8e357ed 100644
--- a/tooling/karaf-maven-plugin/src/it/test-feature-use-base-version/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-feature-use-base-version/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="test-feature-use-base-version">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-feature-use-base-version">
<feature name="test-feature-use-base-version" description="test-feature-use-base-version" version="1.0.0.SNAPSHOT">
<bundle>mvn:org.apache.commons/commons-lang3/3.4</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transfer-properties/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transfer-properties/control.xml b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transfer-properties/control.xml
index 131f23f..14a253c 100644
--- a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transfer-properties/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transfer-properties/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="feature">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="feature">
<feature name="feature" description="feature" version="1.0.0.SNAPSHOT">
<bundle>mvn:test/transitive/[0.9,1.9)</bundle>
<bundle>mvn:org.apache.commons/commons-lang3/[3.0,3.4)</bundle>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transitive/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transitive/control.xml b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transitive/control.xml
index 131f23f..14a253c 100644
--- a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transitive/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range-transitive/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="feature">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="feature">
<feature name="feature" description="feature" version="1.0.0.SNAPSHOT">
<bundle>mvn:test/transitive/[0.9,1.9)</bundle>
<bundle>mvn:org.apache.commons/commons-lang3/[3.0,3.4)</bundle>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range/control.xml b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range/control.xml
index a29d8c8..a3594a5 100644
--- a/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-feature-use-version-range/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="test-feature-use-version-range">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-feature-use-version-range">
<feature name="test-feature-use-version-range" description="test-feature-use-version-range" version="1.0.0.SNAPSHOT">
<bundle>mvn:org.apache.commons/commons-lang3/[3.0,3.4)</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-include-project-artifact/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-include-project-artifact/control.xml b/tooling/karaf-maven-plugin/src/it/test-include-project-artifact/control.xml
index caf5960..fe1b017 100644
--- a/tooling/karaf-maven-plugin/src/it/test-include-project-artifact/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-include-project-artifact/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="test-include-project-artifact">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-include-project-artifact">
<feature name="test-include-project-artifact" description="test-include-project-artifact" version="1.0.0.SNAPSHOT">
<bundle>mvn:test/test-include-project-artifact/1.0-SNAPSHOT</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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 b881b51..7ec72f0 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.4.0" name="test-input-file">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-input-file">
<feature description="Test Description" version="1.0.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/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-rename-main-feature/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-rename-main-feature/control.xml b/tooling/karaf-maven-plugin/src/it/test-rename-main-feature/control.xml
index c624790..46d0824 100644
--- a/tooling/karaf-maven-plugin/src/it/test-rename-main-feature/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-rename-main-feature/control.xml
@@ -19,7 +19,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="test-rename-project-artifact">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-rename-project-artifact">
<feature name="test-feature" description="test-rename-project-artifact" version="1.0.0.SNAPSHOT">
<bundle>mvn:test/test-rename-project-artifact/1.0-SNAPSHOT</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-repository-dependencies/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-repository-dependencies/control.xml b/tooling/karaf-maven-plugin/src/it/test-repository-dependencies/control.xml
index 0cde6c9..276b97d 100644
--- a/tooling/karaf-maven-plugin/src/it/test-repository-dependencies/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-repository-dependencies/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="dependency-feature-a">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="dependency-feature-a">
<repository>mvn:test/dependency-feature-b/1.0-SNAPSHOT/xml/features</repository>
<feature name="dependency-feature-a" description="dependency-feature-a" version="1.0.0.SNAPSHOT">
<feature version="1.0.0.SNAPSHOT" prerequisite="false" dependency="false">dependency-feature-b</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/tooling/karaf-maven-plugin/src/it/test-simplify-bundles/control.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/it/test-simplify-bundles/control.xml b/tooling/karaf-maven-plugin/src/it/test-simplify-bundles/control.xml
index 94cb36a..fdc84cf 100644
--- a/tooling/karaf-maven-plugin/src/it/test-simplify-bundles/control.xml
+++ b/tooling/karaf-maven-plugin/src/it/test-simplify-bundles/control.xml
@@ -18,7 +18,7 @@
~ under the License.
-->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="simplify-features">
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="simplify-features">
<repository>mvn:test/simplify-feature-a/1.0-SNAPSHOT/xml/features</repository>
<feature name="simplify-feature-as-is" description="simplify-feature-as-is" version="1.0.0.SNAPSHOT">
<details>Check that bundles are simplified</details>
http://git-wip-us.apache.org/repos/asf/karaf/blob/9f89d2c7/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 246e2cf..3a7371c 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.4.0" name="test-type-classifier"/>
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.5.0" name="test-type-classifier"/>
[2/4] karaf git commit: [KARAF-5074] Better support for typed configs
for built-in features and bin/client
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/util/src/main/java/org/apache/karaf/util/locks/FileLockUtils.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/locks/FileLockUtils.java b/util/src/main/java/org/apache/karaf/util/locks/FileLockUtils.java
index 9eef129..e9455c2 100644
--- a/util/src/main/java/org/apache/karaf/util/locks/FileLockUtils.java
+++ b/util/src/main/java/org/apache/karaf/util/locks/FileLockUtils.java
@@ -24,92 +24,76 @@ import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
-import org.apache.felix.utils.properties.Properties;
+import org.apache.felix.utils.properties.TypedProperties;
public final class FileLockUtils {
private FileLockUtils() { }
- public static interface Runnable {
- void run(RandomAccessFile file) throws IOException;
+ public interface Runnable<T> {
+ void run(T file) throws IOException;
}
- public static interface Callable<T> {
- T call(RandomAccessFile file) throws IOException;
+ public interface Callable<T, U> {
+ U call(T file) throws IOException;
}
- public static interface RunnableWithProperties {
- void run(Properties properties) throws IOException;
- }
-
- public static interface CallableWithProperties<T> {
- T call(Properties properties) throws IOException;
- }
-
- public static void execute(File file, Runnable callback) throws IOException {
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- try {
+ public static void execute(File file, Runnable<? super RandomAccessFile> callback) throws IOException {
+ try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
FileLock lock = raf.getChannel().lock();
try {
callback.run(raf);
} finally {
lock.release();
}
- } finally {
- raf.close();
}
}
- public static <T> T execute(File file, Callable<T> callback) throws IOException {
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- try {
+ public static <T> T execute(File file, Callable<? super RandomAccessFile, T> callback) throws IOException {
+ try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
FileLock lock = raf.getChannel().lock();
-
try {
return callback.call(raf);
} finally {
lock.release();
}
- } finally {
- raf.close();
}
}
- public static void execute(File file, final RunnableWithProperties callback, final boolean writeToFile) throws IOException {
- execute(file, new Runnable() {
- public void run(RandomAccessFile file) throws IOException {
- byte[] buffer = new byte[(int) file.length()];
- file.readFully(buffer);
- Properties props = new Properties();
- props.load(new ByteArrayInputStream(buffer));
- callback.run(props);
- if (writeToFile) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- props.store(baos, null);
- file.setLength(0);
- file.write(baos.toByteArray());
- }
+ public static void execute(File file, Runnable<? super TypedProperties> callback, boolean writeToFile) throws IOException {
+ execute(file, raf -> {
+ TypedProperties props = load(raf);
+ callback.run(props);
+ if (writeToFile) {
+ save(props, raf);
}
});
}
- public static <T> T execute(File file, final CallableWithProperties<T> callback, final boolean writeToFile) throws IOException {
- return execute(file, new Callable<T>() {
- public T call(RandomAccessFile file) throws IOException {
- byte[] buffer = new byte[(int) file.length()];
- file.readFully(buffer);
- Properties props = new Properties();
- props.load(new ByteArrayInputStream(buffer));
- T result = callback.call(props);
- if (writeToFile) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- props.store(baos, null);
- file.setLength(0);
- file.write(baos.toByteArray());
- }
- return result;
+ public static <T> T execute(File file, Callable<? super TypedProperties, T> callback, boolean writeToFile) throws IOException {
+ return execute(file, raf -> {
+ TypedProperties props = load(raf);
+ T result = callback.call(props);
+ if (writeToFile) {
+ save(props, raf);
}
+ return result;
});
}
+ private static TypedProperties load(RandomAccessFile raf) throws IOException {
+ byte[] buffer = new byte[(int) raf.length()];
+ raf.readFully(buffer);
+ TypedProperties props = new TypedProperties();
+ props.load(new ByteArrayInputStream(buffer));
+ return props;
+ }
+
+ private static void save(TypedProperties props, RandomAccessFile raf) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ props.save(baos);
+ raf.setLength(0);
+ raf.write(baos.toByteArray());
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
index 670ff9d..c1b00da 100644
--- a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
+++ b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
@@ -32,6 +32,8 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -228,6 +230,28 @@ public class BaseActivator implements BundleActivator, Runnable {
return def;
}
+ protected String[] getStringArray(String key, String def) {
+ Object val = null;
+ if (configuration != null) {
+ val = configuration.get(key);
+ }
+ if (val == null) {
+ val = def;
+ }
+ if (val == null) {
+ return null;
+ }
+ Stream<String> s;
+ if (val instanceof String[]) {
+ return (String[]) val;
+ } else if (val instanceof Iterable) {
+ return StreamSupport.stream(((Iterable<?>) val).spliterator(), false)
+ .map(Object::toString).toArray(String[]::new);
+ } else {
+ return val.toString().split(",");
+ }
+ }
+
protected void reconfigure() {
if (scheduled.compareAndSet(false, true)) {
executor.submit(this);
[3/4] karaf git commit: [KARAF-5074] Better support for typed configs
for built-in features and bin/client
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
index c5a6e19..0d30b19 100644
--- a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
@@ -20,7 +20,6 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -33,15 +32,16 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.Scanner;
import java.util.TreeMap;
+import org.apache.felix.utils.properties.InterpolationHelper;
+import org.apache.felix.utils.properties.Properties;
+import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.instance.core.Instance;
import org.apache.karaf.instance.core.InstanceService;
import org.apache.karaf.instance.core.InstanceSettings;
@@ -54,6 +54,7 @@ import org.apache.karaf.profile.ProfileBuilder;
import org.apache.karaf.profile.ProfileService;
import org.apache.karaf.shell.support.ansi.SimpleAnsi;
import org.apache.karaf.util.StreamUtils;
+import org.apache.karaf.util.config.PropertiesLoader;
import org.apache.karaf.util.locks.FileLockUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@@ -63,10 +64,10 @@ import org.slf4j.LoggerFactory;
public class InstanceServiceImpl implements InstanceService {
- private static final String RESOURCE_BASE = "org/apache/karaf/instance/resources/";
public static final String STORAGE_FILE = "instance.properties";
public static final String BACKUP_EXTENSION = ".bak";
private static final String FEATURES_CFG = "etc/org.apache.karaf.features.cfg";
+ private static final String RESOURCE_BASE = "org/apache/karaf/instance/resources/";
private static final Logger LOGGER = LoggerFactory.getLogger(InstanceServiceImpl.class);
@@ -86,7 +87,7 @@ public class InstanceServiceImpl implements InstanceService {
public static final String DEFAULT_JAVA_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass";
- private LinkedHashMap<String, InstanceImpl> proxies = new LinkedHashMap<String, InstanceImpl>();
+ private LinkedHashMap<String, InstanceImpl> proxies = new LinkedHashMap<>();
private File storageLocation;
@@ -108,13 +109,13 @@ public class InstanceServiceImpl implements InstanceService {
public State() {
//read port start value from the root instance configuration
try {
- Properties shellProperty = new Properties();
- shellProperty.load(new FileInputStream(new File(System.getProperty("karaf.etc"), "org.apache.karaf.shell.cfg")));
- defaultSshPortStart = Integer.valueOf((String)shellProperty.getOrDefault("sshPort", 8101));
- Properties managementProperty = new Properties();
- managementProperty.load(new FileInputStream(new File(System.getProperty("karaf.etc"), "org.apache.karaf.management.cfg")));
- defaultRmiRegistryPortStart = Integer.valueOf((String)managementProperty.getOrDefault("rmiRegistryPort", 1099));
- defaultRmiServerPortStart = Integer.valueOf((String)managementProperty.getOrDefault("rmiServerPort", 1099));
+ TypedProperties shellProperty = new TypedProperties();
+ shellProperty.load(new File(System.getProperty("karaf.etc"), "org.apache.karaf.shell.cfg"));
+ defaultSshPortStart = getInt(shellProperty,"sshPort", 8101);
+ TypedProperties managementProperty = new TypedProperties();
+ managementProperty.load(new File(System.getProperty("karaf.etc"), "org.apache.karaf.management.cfg"));
+ defaultRmiRegistryPortStart = getInt(managementProperty, "rmiRegistryPort", 1099);
+ defaultRmiServerPortStart = getInt(managementProperty, "rmiServerPort", 1099);
} catch (Exception e) {
LOGGER.debug("Could not read port start value from the root instance configuration.", e);
}
@@ -146,13 +147,13 @@ public class InstanceServiceImpl implements InstanceService {
this.stopTimeout = stopTimeout;
}
- private State loadData(org.apache.felix.utils.properties.Properties storage) {
+ private State loadData(TypedProperties storage) {
State state = new State();
int count = getInt(storage, "count", 0);
state.defaultSshPortStart = getInt(storage, "ssh.port", state.defaultSshPortStart);
state.defaultRmiRegistryPortStart = getInt(storage, "rmi.registry.port", state.defaultRmiRegistryPortStart);
state.defaultRmiServerPortStart = getInt(storage, "rmi.server.port", state.defaultRmiServerPortStart);
- state.instances = new LinkedHashMap<String, InstanceState>();
+ state.instances = new LinkedHashMap<>();
for (int i = 0; i < count; i++) {
InstanceState instance = new InstanceState();
@@ -169,7 +170,7 @@ public class InstanceServiceImpl implements InstanceService {
proxies.put(instance.name, new InstanceImpl(this, instance.name));
}
}
- List<String> names = new ArrayList<String>(this.proxies.keySet());
+ List<String> names = new ArrayList<>(this.proxies.keySet());
for (String name : names) {
if (!state.instances.containsKey(name)) {
this.proxies.remove(name);
@@ -178,7 +179,7 @@ public class InstanceServiceImpl implements InstanceService {
return state;
}
- private void saveData(State state, org.apache.felix.utils.properties.Properties storage) {
+ private void saveData(State state, TypedProperties storage) {
storage.put("ssh.port", Integer.toString(state.defaultSshPortStart));
storage.put("rmi.registry.port", Integer.toString(state.defaultRmiRegistryPortStart));
storage.put("rmi.server.port", Integer.toString(state.defaultRmiServerPortStart));
@@ -202,34 +203,38 @@ public class InstanceServiceImpl implements InstanceService {
}
}
- private boolean getBool(org.apache.felix.utils.properties.Properties storage, String name, boolean def) {
+ private static boolean getBool(TypedProperties storage, String name, boolean def) {
Object value = storage.get(name);
- if (value != null) {
+ if (value instanceof Boolean) {
+ return (Boolean) value;
+ } else if (value != null) {
return Boolean.parseBoolean(value.toString());
} else {
return def;
}
}
- private int getInt(org.apache.felix.utils.properties.Properties storage, String name, int def) {
+ private static int getInt(TypedProperties storage, String name, int def) {
Object value = storage.get(name);
- if (value != null) {
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ } else if (value != null) {
return Integer.parseInt(value.toString());
} else {
return def;
}
}
- private String getString(org.apache.felix.utils.properties.Properties storage, String name, String def) {
+ private static String getString(TypedProperties storage, String name, String def) {
Object value = storage.get(name);
return value != null ? value.toString() : def;
}
- interface Task<T> {
- T call(State state) throws IOException;
+ interface Task<U, T> {
+ T call(U state) throws IOException;
}
- synchronized <T> T execute(final Task<T> callback, final boolean writeToFile) {
+ synchronized <T> T execute(final Task<State, T> callback, final boolean writeToFile) {
final File storageFile = new File(storageLocation, STORAGE_FILE);
if (!storageFile.exists()) {
storageFile.getParentFile().mkdirs();
@@ -244,15 +249,13 @@ public class InstanceServiceImpl implements InstanceService {
throw new IllegalStateException("Instance storage location should be a file: " + storageFile);
}
try {
- return FileLockUtils.execute(storageFile, new FileLockUtils.CallableWithProperties<T>() {
- public T call(org.apache.felix.utils.properties.Properties properties) throws IOException {
- State state = loadData(properties);
- T t = callback.call(state);
- if (writeToFile) {
- saveData(state, properties);
- }
- return t;
+ return FileLockUtils.execute(storageFile, properties -> {
+ State state = loadData(properties);
+ T t = callback.call(state);
+ if (writeToFile) {
+ saveData(state, properties);
}
+ return t;
}, writeToFile);
} catch (IOException e) {
throw new RuntimeException(e);
@@ -283,154 +286,150 @@ public class InstanceServiceImpl implements InstanceService {
}
public synchronized Instance createInstance(final String name, final InstanceSettings settings, final boolean printOutput) throws Exception {
- return execute(new Task<Instance>() {
- public Instance call(State state) throws IOException {
- if (state.instances.get(name) != null) {
- throw new IllegalArgumentException("Instance '" + name + "' already exists");
- }
- if (!settings.getProfiles().isEmpty()) {
- try {
- ProfileApplier.verify();
- } catch (NoClassDefFoundError error) {
- throw new IllegalArgumentException("Profile service package is not available");
- }
+ return execute(state -> {
+ if (state.instances.get(name) != null) {
+ throw new IllegalArgumentException("Instance '" + name + "' already exists");
+ }
+ if (!settings.getProfiles().isEmpty()) {
+ try {
+ ProfileApplier.verify();
+ } catch (NoClassDefFoundError error) {
+ throw new IllegalArgumentException("Profile service package is not available");
}
+ }
- String loc = settings.getLocation() != null ? settings.getLocation() : name;
- File karafBase = new File(loc);
- if (!karafBase.isAbsolute()) {
- karafBase = new File(storageLocation, loc);
- }
- int sshPort = settings.getSshPort();
- if (sshPort <= 0) {
- sshPort = ++state.defaultSshPortStart;
- }
- String sshHost = settings.getAddress();
- int rmiRegistryPort = settings.getRmiRegistryPort();
- if (rmiRegistryPort <= 0) {
- rmiRegistryPort = ++state.defaultRmiRegistryPortStart;
- }
- int rmiServerPort = settings.getRmiServerPort();
- if (rmiServerPort <= 0) {
- rmiServerPort = ++state.defaultRmiServerPortStart;
- }
- logInfo("Creating new instance on SSH port %d and registry port %d / RMI server port %d at: %s",
- printOutput, sshPort, rmiRegistryPort, rmiServerPort, karafBase);
-
- mkdir(karafBase, "bin", printOutput);
- mkdir(karafBase, "etc", printOutput);
- mkdir(karafBase, "system", printOutput);
- mkdir(karafBase, "deploy", printOutput);
- mkdir(karafBase, "data", printOutput);
-
- Map<String, URL> textResources = new HashMap<String, URL>(settings.getTextResources());
- Map<String, URL> binaryResources = new HashMap<String, URL>(settings.getBinaryResources());
-
- String[] resources =
- {
- "etc/all.policy",
- "etc/config.properties",
- "etc/custom.properties",
- "etc/distribution.info",
- "etc/equinox-debug.properties",
- "etc/java.util.logging.properties",
- "etc/jmx.acl.cfg",
- "etc/jre.properties",
- "etc/keys.properties",
- "etc/org.apache.felix.fileinstall-deploy.cfg",
- "etc/org.apache.karaf.features.repos.cfg",
- "etc/org.apache.karaf.jaas.cfg",
- "etc/org.apache.karaf.kar.cfg",
- "etc/org.apache.karaf.log.cfg",
- "etc/org.ops4j.pax.logging.cfg",
- "etc/org.ops4j.pax.url.mvn.cfg",
- "etc/shell.init.script",
- "etc/users.properties",
- FEATURES_CFG
- };
- copyResourcesToDir(resources, karafBase, textResources, printOutput);
- addFeaturesFromSettings(new File(karafBase, FEATURES_CFG), settings);
-
- // The startup.properties is now generated by the karaf maven plugin, so
- // we use the one from the root instance instead of embedding it
- File rootEtc = new File(System.getProperty("karaf.etc"));
- copy(new File(rootEtc, "startup.properties"), new File(karafBase, "etc/startup.properties"));
-
- // align child with any bundles we have overriden in the root instance
- File rootOverrides = new File(rootEtc, "overrides.properties");
- if (rootOverrides.exists()) {
- copy(rootOverrides, new File(karafBase, "etc/overrides.properties"));
- }
-
- HashMap<String, String> props = new HashMap<String, String>();
- props.put("${SUBST-KARAF-NAME}", name);
- props.put("${SUBST-KARAF-HOME}", System.getProperty("karaf.home"));
- props.put("${SUBST-KARAF-BASE}", karafBase.getPath());
- props.put("${SUBST-SSH-PORT}", Integer.toString(sshPort));
- props.put("${SUBST-SSH-HOST}", sshHost);
- props.put("${SUBST-RMI-REGISTRY-PORT}", Integer.toString(rmiRegistryPort));
- props.put("${SUBST-RMI-SERVER-PORT}", Integer.toString(rmiServerPort));
-
- String[] filteredResources =
- {
- "etc/system.properties",
- "etc/org.apache.karaf.shell.cfg",
- "etc/org.apache.karaf.management.cfg",
- "bin/karaf",
- "bin/start",
- "bin/stop",
- "bin/karaf.bat",
- "bin/start.bat",
- "bin/stop.bat"
- };
- copyFilteredResourcesToDir(filteredResources, karafBase, textResources, props, printOutput);
+ String loc = settings.getLocation() != null ? settings.getLocation() : name;
+ File karafBase = new File(loc);
+ if (!karafBase.isAbsolute()) {
+ karafBase = new File(storageLocation, loc);
+ }
+ int sshPort = settings.getSshPort();
+ if (sshPort <= 0) {
+ sshPort = ++state.defaultSshPortStart;
+ }
+ String sshHost = settings.getAddress();
+ int rmiRegistryPort = settings.getRmiRegistryPort();
+ if (rmiRegistryPort <= 0) {
+ rmiRegistryPort = ++state.defaultRmiRegistryPortStart;
+ }
+ int rmiServerPort = settings.getRmiServerPort();
+ if (rmiServerPort <= 0) {
+ rmiServerPort = ++state.defaultRmiServerPortStart;
+ }
+ logInfo("Creating new instance on SSH port %d and registry port %d / RMI server port %d at: %s",
+ printOutput, sshPort, rmiRegistryPort, rmiServerPort, karafBase);
+
+ mkdir(karafBase, "bin", printOutput);
+ mkdir(karafBase, "etc", printOutput);
+ mkdir(karafBase, "system", printOutput);
+ mkdir(karafBase, "deploy", printOutput);
+ mkdir(karafBase, "data", printOutput);
+
+ Map<String, URL> textResources = new HashMap<>(settings.getTextResources());
+ Map<String, URL> binaryResources = new HashMap<>(settings.getBinaryResources());
+
+ String[] resources =
+ {
+ "etc/all.policy",
+ "etc/config.properties",
+ "etc/custom.properties",
+ "etc/distribution.info",
+ "etc/equinox-debug.properties",
+ "etc/java.util.logging.properties",
+ "etc/jmx.acl.cfg",
+ "etc/jre.properties",
+ "etc/keys.properties",
+ "etc/org.apache.felix.fileinstall-deploy.cfg",
+ "etc/org.apache.karaf.features.repos.cfg",
+ "etc/org.apache.karaf.jaas.cfg",
+ "etc/org.apache.karaf.kar.cfg",
+ "etc/org.apache.karaf.log.cfg",
+ "etc/org.ops4j.pax.logging.cfg",
+ "etc/org.ops4j.pax.url.mvn.cfg",
+ "etc/shell.init.script",
+ "etc/users.properties",
+ FEATURES_CFG
+ };
+ copyResourcesToDir(resources, karafBase, textResources, printOutput);
+ addFeaturesFromSettings(new File(karafBase, FEATURES_CFG), settings);
+
+ // The startup.properties is now generated by the karaf maven plugin, so
+ // we use the one from the root instance instead of embedding it
+ File rootEtc = new File(System.getProperty("karaf.etc"));
+ copy(new File(rootEtc, "startup.properties"), new File(karafBase, "etc/startup.properties"));
+
+ // align child with any bundles we have overriden in the root instance
+ File rootOverrides = new File(rootEtc, "overrides.properties");
+ if (rootOverrides.exists()) {
+ copy(rootOverrides, new File(karafBase, "etc/overrides.properties"));
+ }
- try {
- chmod(new File(karafBase, "bin/karaf"), "a+x");
- chmod(new File(karafBase, "bin/start"), "a+x");
- chmod(new File(karafBase, "bin/stop"), "a+x");
- } catch (IOException e) {
- LOGGER.debug("Could not set file mode on scripts.", e);
- }
+ HashMap<String, String> props = new HashMap<>();
+ props.put("${SUBST-KARAF-NAME}", name);
+ props.put("${SUBST-KARAF-HOME}", System.getProperty("karaf.home"));
+ props.put("${SUBST-KARAF-BASE}", karafBase.getPath());
+ props.put("${SUBST-SSH-PORT}", Integer.toString(sshPort));
+ props.put("${SUBST-SSH-HOST}", sshHost);
+ props.put("${SUBST-RMI-REGISTRY-PORT}", Integer.toString(rmiRegistryPort));
+ props.put("${SUBST-RMI-SERVER-PORT}", Integer.toString(rmiServerPort));
+
+ String[] filteredResources =
+ {
+ "etc/system.properties",
+ "etc/org.apache.karaf.shell.cfg",
+ "etc/org.apache.karaf.management.cfg",
+ "bin/karaf",
+ "bin/start",
+ "bin/stop",
+ "bin/karaf.bat",
+ "bin/start.bat",
+ "bin/stop.bat"
+ };
+ copyFilteredResourcesToDir(filteredResources, karafBase, textResources, props, printOutput);
- for (String resource : textResources.keySet()) {
- copyFilteredResourceToDir(resource, karafBase, textResources, props, printOutput);
- }
+ try {
+ chmod(new File(karafBase, "bin/karaf"), "a+x");
+ chmod(new File(karafBase, "bin/start"), "a+x");
+ chmod(new File(karafBase, "bin/stop"), "a+x");
+ } catch (IOException e) {
+ LOGGER.debug("Could not set file mode on scripts.", e);
+ }
- for (String resource : binaryResources.keySet()) {
- copyBinaryResourceToDir(resource, karafBase, binaryResources, printOutput);
- }
+ for (String resource : textResources.keySet()) {
+ copyFilteredResourceToDir(resource, karafBase, textResources, props, printOutput);
+ }
- if (!settings.getProfiles().isEmpty()) {
- ProfileApplier.applyProfiles(karafBase, settings.getProfiles(), printOutput);
- }
+ for (String resource : binaryResources.keySet()) {
+ copyBinaryResourceToDir(resource, karafBase, binaryResources, printOutput);
+ }
- String javaOpts = settings.getJavaOpts();
- if (javaOpts == null || javaOpts.length() == 0) {
- javaOpts = DEFAULT_JAVA_OPTS;
- }
- InstanceState is = new InstanceState();
- is.name = name;
- is.loc = karafBase.toString();
- is.opts = javaOpts;
- state.instances.put(name, is);
- InstanceImpl instance = new InstanceImpl(InstanceServiceImpl.this, name);
- InstanceServiceImpl.this.proxies.put(name, instance);
- return instance;
+ if (!settings.getProfiles().isEmpty()) {
+ ProfileApplier.applyProfiles(karafBase, settings.getProfiles(), printOutput);
+ }
+
+ String javaOpts = settings.getJavaOpts();
+ if (javaOpts == null || javaOpts.length() == 0) {
+ javaOpts = DEFAULT_JAVA_OPTS;
}
+ InstanceState is = new InstanceState();
+ is.name = name;
+ is.loc = karafBase.toString();
+ is.opts = javaOpts;
+ state.instances.put(name, is);
+ InstanceImpl instance = new InstanceImpl(InstanceServiceImpl.this, name);
+ InstanceServiceImpl.this.proxies.put(name, instance);
+ return instance;
}, true);
}
void addFeaturesFromSettings(File featuresCfg, final InstanceSettings settings) throws IOException {
- FileLockUtils.execute(featuresCfg, new FileLockUtils.RunnableWithProperties() {
- public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
- appendToPropList(properties, "featuresBoot", settings.getFeatures());
- appendToPropList(properties, "featuresRepositories", settings.getFeatureURLs());
- }
+ FileLockUtils.execute(featuresCfg, properties -> {
+ appendToPropList(properties, "featuresBoot", settings.getFeatures());
+ appendToPropList(properties, "featuresRepositories", settings.getFeatureURLs());
}, true);
}
- private static void appendToPropList(org.apache.felix.utils.properties.Properties p, String key, List<String> elements) {
+ private static void appendToPropList(TypedProperties p, String key, List<String> elements) {
if (elements == null) {
return;
}
@@ -445,36 +444,25 @@ public class InstanceServiceImpl implements InstanceService {
}
public Instance[] getInstances() {
- return execute(new Task<Instance[]>() {
- public Instance[] call(State state) throws IOException {
- return proxies.values().toArray(new Instance[proxies.size()]);
- }
- }, false);
+ return execute(state -> proxies.values().toArray(new Instance[proxies.size()]), false);
}
public Instance getInstance(final String name) {
- return execute(new Task<Instance>() {
- public Instance call(State state) throws IOException {
- return proxies.get(name);
- }
- }, false);
+ return execute(state -> proxies.get(name), false);
}
public void startInstance(final String name, final String javaOpts) {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- if (instance.pid != 0) {
- throw new IllegalStateException("Instance already started");
- }
- doStart(instance, name, javaOpts);
- return null;
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
-
+ checkPid(instance);
+ if (instance.pid != 0) {
+ throw new IllegalStateException("Instance already started");
+ }
+ doStart(instance, name, javaOpts);
+ return null;
}, true);
}
@@ -532,11 +520,7 @@ public class InstanceServiceImpl implements InstanceService {
}
private StringBuilder classpathFromLibDir(File libDir) throws IOException {
- File[] jars = libDir.listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.endsWith(".jar");
- }
- });
+ File[] jars = libDir.listFiles((dir, name) -> name.endsWith(".jar"));
StringBuilder classpath = new StringBuilder();
if (jars != null) {
for (File jar : jars) {
@@ -574,167 +558,156 @@ public class InstanceServiceImpl implements InstanceService {
}
public void restartInstance(final String name, final String javaOpts) {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- String current = System.getProperty("karaf.name");
- if (name.equals(current)) {
- String location = System.getProperty("karaf.home");
- StringBuilder classpath = new StringBuilder();
- addJar(classpath, "org.apache.karaf.instance", "org.apache.karaf.instance.core");
- addJar(classpath, "org.apache.karaf.shell", "org.apache.karaf.shell.core");
- addJar(classpath, "org.ops4j.pax.logging", "pax-logging-api");
- addJar(classpath, "jline", "jline");
- String command = "\""
- + new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath()
- + "\" "
- + " -Djava.util.logging.config.file=\"" + new File(location, "etc/java.util.logging.properties").getCanonicalPath() + "\""
- + " -Dkaraf.home=\"" + System.getProperty("karaf.home") + "\""
- + " -Dkaraf.base=\"" + new File(location).getCanonicalPath() + "\""
- + " -Dkaraf.data=\"" + new File(new File(location).getCanonicalPath(), "data") + "\""
- + " -Dkaraf.etc=\"" + new File(new File(location).getCanonicalPath(), "etc") + "\""
- + " -Dkaraf.instances=\"" + System.getProperty("karaf.instances") + "\""
- + " -classpath \"" + classpath.toString() + "\""
- + " " + Execute.class.getName()
- + " restart --java-opts \"" + javaOpts + "\" " + name;
- new ProcessBuilderFactoryImpl().newBuilder()
- .directory(new File(System.getProperty("karaf.home")))
- .command(command)
- .start();
- } else {
- checkPid(instance);
- if (instance.pid != 0) {
- cleanShutdown(instance);
- }
- doStart(instance, name, javaOpts);
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
+ String current = System.getProperty("karaf.name");
+ if (name.equals(current)) {
+ String location = System.getProperty("karaf.home");
+ StringBuilder classpath = new StringBuilder();
+ addJar(classpath, "org.apache.karaf.instance", "org.apache.karaf.instance.core");
+ addJar(classpath, "org.apache.karaf.shell", "org.apache.karaf.shell.core");
+ addJar(classpath, "org.ops4j.pax.logging", "pax-logging-api");
+ addJar(classpath, "jline", "jline");
+ String command = "\""
+ + new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath()
+ + "\" "
+ + " -Djava.util.logging.config.file=\"" + new File(location, "etc/java.util.logging.properties").getCanonicalPath() + "\""
+ + " -Dkaraf.home=\"" + System.getProperty("karaf.home") + "\""
+ + " -Dkaraf.base=\"" + new File(location).getCanonicalPath() + "\""
+ + " -Dkaraf.data=\"" + new File(new File(location).getCanonicalPath(), "data") + "\""
+ + " -Dkaraf.etc=\"" + new File(new File(location).getCanonicalPath(), "etc") + "\""
+ + " -Dkaraf.instances=\"" + System.getProperty("karaf.instances") + "\""
+ + " -classpath \"" + classpath.toString() + "\""
+ + " " + Execute.class.getName()
+ + " restart --java-opts \"" + javaOpts + "\" " + name;
+ new ProcessBuilderFactoryImpl().newBuilder()
+ .directory(new File(System.getProperty("karaf.home")))
+ .command(command)
+ .start();
+ } else {
+ checkPid(instance);
+ if (instance.pid != 0) {
+ cleanShutdown(instance);
}
- return null;
+ doStart(instance, name, javaOpts);
}
+ return null;
}, true);
}
public void stopInstance(final String name) {
-
- Integer pid = (Integer)execute(new Task<Object>() {
-
- public Object call(State state) throws IOException {
- int rootInstancePID = 0;
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- if (instance.pid == 0) {
- throw new IllegalStateException("Instance already stopped");
- }
- cleanShutdown(instance);
- if (instance.pid > 0) {
- if (!instance.root) {
- Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
- process.destroy();
- } else {
- //can't simply destroy root instance here
- //as it will lose the update in instances.properties
- //because of no chance to run the saveData
- rootInstancePID = instance.pid;
- }
- instance.pid = 0;
-
+ Integer pid = execute(state -> {
+ int rootInstancePID = 0;
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
+ checkPid(instance);
+ if (instance.pid == 0) {
+ throw new IllegalStateException("Instance already stopped");
+ }
+ cleanShutdown(instance);
+ if (instance.pid > 0) {
+ if (!instance.root) {
+ Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
+ process.destroy();
+ } else {
+ //can't simply destroy root instance here
+ //as it will lose the update in instances.properties
+ //because of no chance to run the saveData
+ rootInstancePID = instance.pid;
}
- return rootInstancePID;
+ instance.pid = 0;
+
}
+ return rootInstancePID;
}, true);
- if (pid.intValue() != 0 && isInstanceRoot(name)) {
+ if (pid != 0 && isInstanceRoot(name)) {
Process process;
try {
- process = new ProcessBuilderFactoryImpl().newBuilder().attach(pid.intValue());
+ process = new ProcessBuilderFactoryImpl().newBuilder().attach(pid);
process.destroy();
} catch (IOException e) {
LOGGER.debug("Unable to cleanly shutdown root instance ", e);
}
-
}
}
public void destroyInstance(final String name) {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- if (instance.pid != 0) {
- throw new IllegalStateException("Instance not stopped");
- }
- deleteFile(new File(instance.loc));
- state.instances.remove(name);
- InstanceServiceImpl.this.proxies.remove(name);
- return null;
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
+ checkPid(instance);
+ if (instance.pid != 0) {
+ throw new IllegalStateException("Instance not stopped");
}
+ deleteFile(new File(instance.loc));
+ state.instances.remove(name);
+ InstanceServiceImpl.this.proxies.remove(name);
+ return null;
}, true);
}
public void renameInstance(final String oldName, final String newName, final boolean printOutput) throws Exception {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- if (state.instances.get(newName) != null) {
- throw new IllegalArgumentException("Instance " + newName + " already exists");
- }
- InstanceState instance = state.instances.get(oldName);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + oldName + " not found");
- }
- if (instance.root) {
- throw new IllegalArgumentException("Root instance cannot be renamed");
- }
- checkPid(instance);
- if (instance.pid != 0) {
- throw new IllegalStateException("Instance not stopped");
- }
+ execute(state -> {
+ if (state.instances.get(newName) != null) {
+ throw new IllegalArgumentException("Instance " + newName + " already exists");
+ }
+ InstanceState instance = state.instances.get(oldName);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + oldName + " not found");
+ }
+ if (instance.root) {
+ throw new IllegalArgumentException("Root instance cannot be renamed");
+ }
+ checkPid(instance);
+ if (instance.pid != 0) {
+ throw new IllegalStateException("Instance not stopped");
+ }
- println("Renaming instance "
- + SimpleAnsi.INTENSITY_BOLD + oldName + SimpleAnsi.INTENSITY_NORMAL
- + " to "
- + SimpleAnsi.INTENSITY_BOLD + newName + SimpleAnsi.INTENSITY_NORMAL);
- // rename directory
- String oldLocationPath = instance.loc;
- File oldLocation = new File(oldLocationPath);
- String basedir = oldLocation.getParent();
- File newLocation = new File(basedir, newName);
- oldLocation.renameTo(newLocation);
- // create the properties map including the instance name and instance location
- // TODO: replacing is bad, we should re-extract the needed files
- HashMap<String, String> props = new HashMap<String, String>();
- props.put(oldName, newName);
- props.put(oldLocationPath, newLocation.getPath());
- // replace all references to the "old" name by the new one in etc/system.properties
- // NB: it's replacement to avoid to override the user's changes
- filterResource(newLocation, "etc/system.properties", props);
- // replace all references to the "old" name by the new one in bin/karaf
- filterResource(newLocation, "bin/karaf", props);
- filterResource(newLocation, "bin/start", props);
- filterResource(newLocation, "bin/stop", props);
- filterResource(newLocation, "bin/karaf.bat", props);
- filterResource(newLocation, "bin/start.bat", props);
- filterResource(newLocation, "bin/stop.bat", props);
- // update instance
- instance.name = newName;
- instance.loc = newLocation.getPath();
- state.instances.put(newName, instance);
- state.instances.remove(oldName);
- InstanceImpl proxy = InstanceServiceImpl.this.proxies.remove(oldName);
- if (proxy == null) {
- proxy = new InstanceImpl(InstanceServiceImpl.this, newName);
- } else {
- proxy.doSetName(newName);
- }
- InstanceServiceImpl.this.proxies.put(newName, proxy);
- return null;
+ println("Renaming instance "
+ + SimpleAnsi.INTENSITY_BOLD + oldName + SimpleAnsi.INTENSITY_NORMAL
+ + " to "
+ + SimpleAnsi.INTENSITY_BOLD + newName + SimpleAnsi.INTENSITY_NORMAL);
+ // rename directory
+ String oldLocationPath = instance.loc;
+ File oldLocation = new File(oldLocationPath);
+ String basedir = oldLocation.getParent();
+ File newLocation = new File(basedir, newName);
+ oldLocation.renameTo(newLocation);
+ // create the properties map including the instance name and instance location
+ // TODO: replacing is bad, we should re-extract the needed files
+ HashMap<String, String> props = new HashMap<String, String>();
+ props.put(oldName, newName);
+ props.put(oldLocationPath, newLocation.getPath());
+ // replace all references to the "old" name by the new one in etc/system.properties
+ // NB: it's replacement to avoid to override the user's changes
+ filterResource(newLocation, "etc/system.properties", props);
+ // replace all references to the "old" name by the new one in bin/karaf
+ filterResource(newLocation, "bin/karaf", props);
+ filterResource(newLocation, "bin/start", props);
+ filterResource(newLocation, "bin/stop", props);
+ filterResource(newLocation, "bin/karaf.bat", props);
+ filterResource(newLocation, "bin/start.bat", props);
+ filterResource(newLocation, "bin/stop.bat", props);
+ // update instance
+ instance.name = newName;
+ instance.loc = newLocation.getPath();
+ state.instances.put(newName, instance);
+ state.instances.remove(oldName);
+ InstanceImpl proxy = InstanceServiceImpl.this.proxies.remove(oldName);
+ if (proxy == null) {
+ proxy = new InstanceImpl(InstanceServiceImpl.this, newName);
+ } else {
+ proxy.doSetName(newName);
}
+ InstanceServiceImpl.this.proxies.put(newName, proxy);
+ return null;
}, true);
}
@@ -742,65 +715,62 @@ public class InstanceServiceImpl implements InstanceService {
final int instanceSshPort = getInstanceSshPort(name);
final int instanceRmiRegistryPort = getInstanceRmiRegistryPort(name);
final int instanceRmiServerPort = getInstanceRmiServerPort(name);
+ return execute(state -> {
+ if (state.instances.get(cloneName) != null) {
+ throw new IllegalArgumentException("Instance " + cloneName + " already exists");
+ }
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
- return execute(new Task<Instance>() {
- public Instance call(State state) throws IOException {
- if (state.instances.get(cloneName) != null) {
- throw new IllegalArgumentException("Instance " + cloneName + " already exists");
- }
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
-
- // define the clone instance location
- String cloneLocationPath = settings.getLocation() != null ? settings.getLocation() : cloneName;
- File cloneLocation = new File(cloneLocationPath);
- if (!cloneLocation.isAbsolute()) {
- cloneLocation = new File(storageLocation, cloneLocationPath);
- }
- // copy instance directory
- String locationPath = instance.loc;
- File location = new File(locationPath);
- copy(location, cloneLocation);
- // create the properties map including the instance name, location, ssh and rmi port numbers
- // TODO: replacing stuff anywhere is not really good, we might end up replacing unwanted stuff
- // TODO: if no ports are overriden, shouldn't we choose new ports ?
- HashMap<String, String> props = new HashMap<String, String>();
- props.put(name, cloneName);
- props.put(locationPath, cloneLocationPath);
- if (settings.getSshPort() > 0)
- props.put(Integer.toString(instanceSshPort), Integer.toString(settings.getSshPort()));
- if (settings.getRmiRegistryPort() > 0)
- props.put(Integer.toString(instanceRmiRegistryPort), Integer.toString(settings.getRmiRegistryPort()));
- if (settings.getRmiServerPort() > 0)
- props.put(Integer.toString(instanceRmiServerPort), Integer.toString(settings.getRmiServerPort()));
-
- // filtering clone files
- filterResource(cloneLocation, "etc/custom.properties", props);
- filterResource(cloneLocation, "etc/org.apache.karaf.management.cfg", props);
- filterResource(cloneLocation, "etc/org.apache.karaf.shell.cfg", props);
- filterResource(cloneLocation, "etc/system.properties", props);
- filterResource(cloneLocation, "bin/karaf", props);
- filterResource(cloneLocation, "bin/start", props);
- filterResource(cloneLocation, "bin/stop", props);
- filterResource(cloneLocation, "bin/karaf.bat", props);
- filterResource(cloneLocation, "bin/start.bat", props);
- filterResource(cloneLocation, "bin/stop.bat", props);
- // create and add the clone instance in the registry
- String javaOpts = settings.getJavaOpts();
- if (javaOpts == null || javaOpts.length() == 0) {
- javaOpts = DEFAULT_JAVA_OPTS;
- }
- InstanceState is = new InstanceState();
- is.name = cloneName;
- is.loc = cloneLocation.toString();
- is.opts = javaOpts;
- state.instances.put(cloneName, is);
- InstanceImpl cloneInstance = new InstanceImpl(InstanceServiceImpl.this, cloneName);
- InstanceServiceImpl.this.proxies.put(cloneName, cloneInstance);
- return cloneInstance;
+ // define the clone instance location
+ String cloneLocationPath = settings.getLocation() != null ? settings.getLocation() : cloneName;
+ File cloneLocation = new File(cloneLocationPath);
+ if (!cloneLocation.isAbsolute()) {
+ cloneLocation = new File(storageLocation, cloneLocationPath);
+ }
+ // copy instance directory
+ String locationPath = instance.loc;
+ File location = new File(locationPath);
+ copy(location, cloneLocation);
+ // create the properties map including the instance name, location, ssh and rmi port numbers
+ // TODO: replacing stuff anywhere is not really good, we might end up replacing unwanted stuff
+ // TODO: if no ports are overriden, shouldn't we choose new ports ?
+ HashMap<String, String> props = new HashMap<String, String>();
+ props.put(name, cloneName);
+ props.put(locationPath, cloneLocationPath);
+ if (settings.getSshPort() > 0)
+ props.put(Integer.toString(instanceSshPort), Integer.toString(settings.getSshPort()));
+ if (settings.getRmiRegistryPort() > 0)
+ props.put(Integer.toString(instanceRmiRegistryPort), Integer.toString(settings.getRmiRegistryPort()));
+ if (settings.getRmiServerPort() > 0)
+ props.put(Integer.toString(instanceRmiServerPort), Integer.toString(settings.getRmiServerPort()));
+
+ // filtering clone files
+ filterResource(cloneLocation, "etc/custom.properties", props);
+ filterResource(cloneLocation, "etc/org.apache.karaf.management.cfg", props);
+ filterResource(cloneLocation, "etc/org.apache.karaf.shell.cfg", props);
+ filterResource(cloneLocation, "etc/system.properties", props);
+ filterResource(cloneLocation, "bin/karaf", props);
+ filterResource(cloneLocation, "bin/start", props);
+ filterResource(cloneLocation, "bin/stop", props);
+ filterResource(cloneLocation, "bin/karaf.bat", props);
+ filterResource(cloneLocation, "bin/start.bat", props);
+ filterResource(cloneLocation, "bin/stop.bat", props);
+ // create and add the clone instance in the registry
+ String javaOpts = settings.getJavaOpts();
+ if (javaOpts == null || javaOpts.length() == 0) {
+ javaOpts = DEFAULT_JAVA_OPTS;
}
+ InstanceState is = new InstanceState();
+ is.name = cloneName;
+ is.loc = cloneLocation.toString();
+ is.opts = javaOpts;
+ state.instances.put(cloneName, is);
+ InstanceImpl cloneInstance = new InstanceImpl(InstanceServiceImpl.this, cloneName);
+ InstanceServiceImpl.this.proxies.put(cloneName, cloneInstance);
+ return cloneInstance;
}, true);
}
@@ -816,17 +786,12 @@ public class InstanceServiceImpl implements InstanceService {
protected void cleanShutdown(InstanceState instance) {
try {
File file = new File(new File(instance.loc, "etc"), CONFIG_PROPERTIES_FILE_NAME);
- URL configPropURL = file.toURI().toURL();
- Properties props = loadPropertiesFile(configPropURL);
+ Properties props = PropertiesLoader.loadPropertiesFile(file.toURI().toURL(), false);
props.put("karaf.base", new File(instance.loc).getCanonicalPath());
props.put("karaf.home", System.getProperty("karaf.home"));
props.put("karaf.data", new File(new File(instance.loc), "data").getCanonicalPath());
props.put("karaf.etc", new File(new File(instance.loc), "etc").getCanonicalPath());
- for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) {
- String key = (String) e.nextElement();
- props.setProperty(key,
- substVars(props.getProperty(key), key, null, props));
- }
+ InterpolationHelper.performSubstitution(props, null, true, false, true);
int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
@@ -892,11 +857,7 @@ public class InstanceServiceImpl implements InstanceService {
}
private int getKarafPort(final String name, final String path, final String key) {
- return execute(new Task<Integer>() {
- public Integer call(State state) throws IOException {
- return InstanceServiceImpl.this.getKarafPort(state, name, path, key);
- }
- }, false);
+ return execute(state -> getKarafPort(state, name, path, key), false);
}
@@ -907,10 +868,9 @@ public class InstanceServiceImpl implements InstanceService {
}
File f = new File(instance.loc, path);
try {
- return FileLockUtils.execute(f, new FileLockUtils.CallableWithProperties<Integer>() {
- public Integer call(org.apache.felix.utils.properties.Properties properties) throws IOException {
- return Integer.parseInt(properties.get(key).toString());
- }
+ return FileLockUtils.execute(f, properties -> {
+ Object obj = properties.get(key);
+ return obj instanceof Number ? ((Number) obj).intValue() : Integer.parseInt(obj.toString());
}, false);
} catch (IOException e) {
return 0;
@@ -918,33 +878,25 @@ public class InstanceServiceImpl implements InstanceService {
}
private void setKarafPort(final String name, final String path, final String key, final int port) throws IOException {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- if (instance.pid != 0) {
- throw new IllegalStateException("Instance is not stopped");
- }
- File f = new File(instance.loc, path);
- FileLockUtils.execute(f, new FileLockUtils.RunnableWithProperties() {
- public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
- properties.put(key, Integer.toString(port));
- }
- }, true);
- return null;
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
+ checkPid(instance);
+ if (instance.pid != 0) {
+ throw new IllegalStateException("Instance is not stopped");
}
+ File f = new File(instance.loc, path);
+ FileLockUtils.execute(f, properties -> {
+ properties.put(key, port);
+ }, true);
+ return null;
}, true);
}
private String getKarafHost(final String name, final String path, final String key) {
- return execute(new Task<String>() {
- public String call(State state) throws IOException {
- return InstanceServiceImpl.this.getKarafHost(state, name, path, key);
- }
- }, false);
+ return execute(state -> InstanceServiceImpl.this.getKarafHost(state, name, path, key), false);
}
private String getKarafHost(State state, String name, String path, final String key) {
@@ -954,108 +906,92 @@ public class InstanceServiceImpl implements InstanceService {
}
File f = new File(instance.loc, path);
try {
- return FileLockUtils.execute(f, new FileLockUtils.CallableWithProperties<String>() {
- public String call(org.apache.felix.utils.properties.Properties properties) throws IOException {
- return properties.get(key).toString();
- }
- }, false);
+ return FileLockUtils.execute(f, (TypedProperties properties) -> properties.get(key).toString(), false);
} catch (IOException e) {
return "0.0.0.0";
}
}
boolean isInstanceRoot(final String name) {
- return execute(new Task<Boolean>() {
- public Boolean call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- return instance.root;
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ return instance.root;
}, false);
}
String getInstanceLocation(final String name) {
- return execute(new Task<String>() {
- public String call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- return instance.loc;
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ return instance.loc;
}, true);
}
int getInstancePid(final String name) {
boolean updateInstanceProperties = isInstancePidNeedUpdate(name);
- return execute(new Task<Integer>() {
- public Integer call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- return instance.pid;
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ checkPid(instance);
+ return instance.pid;
}, updateInstanceProperties);
}
String getInstanceJavaOpts(final String name) {
- return execute(new Task<String>() {
- public String call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- return instance.opts;
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ return instance.opts;
}, false);
}
void changeInstanceJavaOpts(final String name, final String opts) {
- execute(new Task<String>() {
- public String call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- instance.opts = opts;
- return null;
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ instance.opts = opts;
+ return null;
}, true);
}
String getInstanceState(final String name) {
boolean updateInstanceProperties = isInstancePidNeedUpdate(name);
- return execute(new Task<String>() {
- public String call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- int port = getKarafPort(state, name, "etc/org.apache.karaf.shell.cfg", "sshPort");
- String host = getKarafHost(state, name, "etc/org.apache.karaf.shell.cfg", "sshHost");
- if (host.equals("0.0.0.0")) {
- host = "localhost";
- }
- if (!new File(instance.loc).isDirectory() || port <= 0) {
- return Instance.ERROR;
- }
- checkPid(instance);
- if (instance.pid == 0) {
- return Instance.STOPPED;
- } else {
- try {
- Socket s = new Socket(host, port);
- s.close();
- return Instance.STARTED;
- } catch (Exception e) {
- // ignore
- }
- return Instance.STARTING;
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
+ }
+ int port = getKarafPort(state, name, "etc/org.apache.karaf.shell.cfg", "sshPort");
+ String host = getKarafHost(state, name, "etc/org.apache.karaf.shell.cfg", "sshHost");
+ if (host.equals("0.0.0.0")) {
+ host = "localhost";
+ }
+ if (!new File(instance.loc).isDirectory() || port <= 0) {
+ return Instance.ERROR;
+ }
+ checkPid(instance);
+ if (instance.pid == 0) {
+ return Instance.STOPPED;
+ } else {
+ try {
+ Socket s = new Socket(host, port);
+ s.close();
+ return Instance.STARTED;
+ } catch (Exception e) {
+ // ignore
}
+ return Instance.STARTING;
}
}, updateInstanceProperties);
}
@@ -1285,142 +1221,36 @@ public class InstanceServiceImpl implements InstanceService {
}
}
- private static final String DELIM_START = "${";
- private static final String DELIM_STOP = "}";
-
- protected static String substVars(String val, String currentKey,
- Map<String, String> cycleMap, Properties configProps)
- throws IllegalArgumentException {
- // If there is currently no cycle map, then create
- // one for detecting cycles for this invocation.
- if (cycleMap == null) {
- cycleMap = new HashMap<String, String>();
- }
-
- // Put the current key in the cycle map.
- cycleMap.put(currentKey, currentKey);
-
- // Assume we have a value that is something like:
- // "leading ${foo.${bar}} middle ${baz} trailing"
-
- // Find the first ending '}' variable delimiter, which
- // will correspond to the first deepest nested variable
- // placeholder.
- int stopDelim = val.indexOf(DELIM_STOP);
-
- // Find the matching starting "${" variable delimiter
- // by looping until we find a start delimiter that is
- // greater than the stop delimiter we have found.
- int startDelim = val.indexOf(DELIM_START);
- while (stopDelim >= 0) {
- int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
- if ((idx < 0) || (idx > stopDelim)) {
- break;
- } else if (idx < stopDelim) {
- startDelim = idx;
- }
- }
-
- // If we do not have a start or stop delimiter, then just
- // return the existing value.
- if ((startDelim < 0) && (stopDelim < 0)) {
- return val;
- }
- // At this point, we found a stop delimiter without a start,
- // so throw an exception.
- else if (((startDelim < 0) || (startDelim > stopDelim))
- && (stopDelim >= 0)) {
- throw new IllegalArgumentException(
- "stop delimiter with no start delimiter: "
- + val);
- }
-
- // At this point, we have found a variable placeholder so
- // we must perform a variable substitution on it.
- // Using the start and stop delimiter indices, extract
- // the first, deepest nested variable placeholder.
- String variable =
- val.substring(startDelim + DELIM_START.length(), stopDelim);
-
- // Verify that this is not a recursive variable reference.
- if (cycleMap.get(variable) != null) {
- throw new IllegalArgumentException(
- "recursive variable reference: " + variable);
- }
-
- // Get the value of the deepest nested variable placeholder.
- // Try to configuration properties first.
- String substValue = (configProps != null)
- ? configProps.getProperty(variable, null)
- : null;
- if (substValue == null) {
- // Ignore unknown property values.
- substValue = System.getProperty(variable, "");
- }
-
- // Remove the found variable from the cycle map, since
- // it may appear more than once in the value and we don't
- // want such situations to appear as a recursive reference.
- cycleMap.remove(variable);
-
- // Append the leading characters, the substituted value of
- // the variable, and the trailing characters to get the new
- // value.
- val = val.substring(0, startDelim)
- + substValue
- + val.substring(stopDelim + DELIM_STOP.length(), val.length());
-
- // Now perform substitution again, since there could still
- // be substitutions to make.
- val = substVars(val, currentKey, cycleMap, configProps);
-
- // Return the value.
- return val;
- }
-
public void changeInstanceSshHost(String name, String host) throws Exception {
setKarafHost(name, "etc/org.apache.karaf.shell.cfg", "sshHost", host);
}
private void setKarafHost(final String name, final String path, final String key, final String host) throws IOException {
- execute(new Task<Object>() {
- public Object call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- checkPid(instance);
- if (instance.pid != 0) {
- throw new IllegalStateException("Instance is not stopped");
- }
- File f = new File(instance.loc, path);
- FileLockUtils.execute(f, new FileLockUtils.RunnableWithProperties() {
- public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
- properties.put(key, host);
- }
- }, true);
- return null;
+ execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ checkPid(instance);
+ if (instance.pid != 0) {
+ throw new IllegalStateException("Instance is not stopped");
+ }
+ File f = new File(instance.loc, path);
+ FileLockUtils.execute(f, properties -> { properties.put(key, host); }, true);
+ return null;
}, true);
}
- private Boolean isInstancePidNeedUpdate(final String name) {
- return execute(new Task<Boolean>() {
- public Boolean call(State state) throws IOException {
- InstanceState instance = state.instances.get(name);
- if (instance == null) {
- throw new IllegalArgumentException("Instance " + name + " not found");
- }
- int origialPid = instance.pid;
- checkPid(instance);
- int newPid = instance.pid;
- if (origialPid == newPid) {
- return false;
- } else {
- return true;
- }
-
+ private boolean isInstancePidNeedUpdate(final String name) {
+ return execute(state -> {
+ InstanceState instance = state.instances.get(name);
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance " + name + " not found");
}
+ int originalPid = instance.pid;
+ checkPid(instance);
+ int newPid = instance.pid;
+ return originalPid != newPid;
}, false);
}
@@ -1451,11 +1281,9 @@ public class InstanceServiceImpl implements InstanceService {
Files.write(configFile, config.getValue());
}
}
- FileLockUtils.execute(new File(karafBase, FEATURES_CFG), new FileLockUtils.RunnableWithProperties() {
- public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
- appendToPropList(properties, "featuresBoot", effective.getFeatures());
- appendToPropList(properties, "featuresRepositories", effective.getRepositories());
- }
+ FileLockUtils.execute(new File(karafBase, FEATURES_CFG), properties -> {
+ appendToPropList(properties, "featuresBoot", effective.getFeatures());
+ appendToPropList(properties, "featuresRepositories", effective.getRepositories());
}, true);
bundleContext.ungetService(reference);
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
----------------------------------------------------------------------
diff --git a/main/src/main/java/org/apache/karaf/main/InstanceHelper.java b/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
index deeb739..afff572 100644
--- a/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
+++ b/main/src/main/java/org/apache/karaf/main/InstanceHelper.java
@@ -20,7 +20,6 @@ package org.apache.karaf.main;
import java.io.File;
import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.Writer;
@@ -32,7 +31,7 @@ import java.nio.channels.FileLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.felix.utils.properties.Properties;
+import org.apache.felix.utils.properties.TypedProperties;
import org.apache.karaf.util.locks.FileLockUtils;
import org.osgi.framework.launch.Framework;
@@ -62,48 +61,44 @@ public class InstanceHelper {
}
// don't instance.properties if we're stopping and can't acquire lock
if (!isStartingInstance) {
- RandomAccessFile raf = new RandomAccessFile(propertiesFile, "rw");
boolean proceed = true;
- try {
+ try (RandomAccessFile raf = new RandomAccessFile(propertiesFile, "rw")) {
FileLock lock = raf.getChannel().tryLock();
if (lock == null) {
proceed = false;
} else {
lock.release();
}
- } finally {
- // if proceed is true than we got the lock or OverlappingFileLockException
- // but we may proceed in either case
- raf.close();
}
+ // if proceed is true than we got the lock or OverlappingFileLockException
+ // but we may proceed in either case
+
if (!proceed) {
// we didn't acquire lock, it may mean that root container is holding the lock when
// stopping the child
return;
}
}
- FileLockUtils.execute(propertiesFile, new FileLockUtils.RunnableWithProperties() {
- public void run(Properties props) throws IOException {
- if (props.isEmpty()) {
- // it's the first instance running, so we consider as root
- props.setProperty("count", "1");
- props.setProperty("item.0.name", instanceName);
- props.setProperty("item.0.loc", karafBase.getAbsolutePath());
- props.setProperty("item.0.pid", pid);
- props.setProperty("item.0.root", "true");
- } else {
- int count = Integer.parseInt(props.getProperty("count"));
- for (int i = 0; i < count; i++) {
- String name = props.getProperty("item." + i + ".name");
- if (name.equals(instanceName)) {
- props.setProperty("item." + i + ".pid", pid);
- return;
- }
+ FileLockUtils.execute(propertiesFile, (TypedProperties props) -> {
+ if (props.isEmpty()) {
+ // it's the first instance running, so we consider as root
+ props.put("count", "1");
+ props.put("item.0.name", instanceName);
+ props.put("item.0.loc", karafBase.getAbsolutePath());
+ props.put("item.0.pid", pid);
+ props.put("item.0.root", "true");
+ } else {
+ int count = Integer.parseInt(props.get("count").toString());
+ for (int i = 0; i < count; i++) {
+ String name = props.get("item." + i + ".name").toString();
+ if (name.equals(instanceName)) {
+ props.put("item." + i + ".pid", pid);
+ return;
}
- // it's not found, let assume it's the root instance, so 0
- props.setProperty("item.0.name", instanceName);
- props.setProperty("item.0.pid", pid);
}
+ // it's not found, let assume it's the root instance, so 0
+ props.put("item.0.name", instanceName);
+ props.put("item.0.pid", pid);
}
}, true);
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
index f7d2c7a..9c4ce12 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/Activator.java
@@ -138,20 +138,20 @@ public class Activator extends BaseActivator implements ManagedService {
}
protected SshServer createSshServer(SessionFactory sessionFactory) {
- int sshPort = getInt("sshPort", 8181);
- String sshHost = getString("sshHost", "0.0.0.0");
- long sshIdleTimeout = getLong("sshIdleTimeout", 1800000);
- String sshRealm = getString("sshRealm", "karaf");
- String hostKey = getString("hostKey", System.getProperty("karaf.etc") + "/host.key");
- String hostKeyFormat = getString("hostKeyFormat", "simple");
- String authMethods = getString("authMethods", "keyboard-interactive,password,publickey");
- int keySize = getInt("keySize", 4096);
- String algorithm = getString("algorithm", "RSA");
- String macs = getString("macs", "hmac-sha2-512,hmac-sha2-256,hmac-sha1");
- String ciphers = getString("ciphers", "aes128-ctr,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc");
- String kexAlgorithms = getString("kexAlgorithms", "diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1");
- String welcomeBanner = getString("welcomeBanner", null);
- String moduliUrl = getString("moduli-url", null);
+ int sshPort = getInt("sshPort", 8181);
+ String sshHost = getString("sshHost", "0.0.0.0");
+ long sshIdleTimeout = getLong("sshIdleTimeout", 1800000);
+ String sshRealm = getString("sshRealm", "karaf");
+ String hostKey = getString("hostKey", System.getProperty("karaf.etc") + "/host.key");
+ String hostKeyFormat = getString("hostKeyFormat", "simple");
+ String[] authMethods = getStringArray("authMethods", "keyboard-interactive,password,publickey");
+ int keySize = getInt("keySize", 4096);
+ String algorithm = getString("algorithm", "RSA");
+ String[] macs = getStringArray("macs", "hmac-sha2-512,hmac-sha2-256,hmac-sha1");
+ String[] ciphers = getStringArray("ciphers", "aes128-ctr,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc");
+ String[] kexAlgorithms = getStringArray("kexAlgorithms", "diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1");
+ String welcomeBanner = getString("welcomeBanner", null);
+ String moduliUrl = getString("moduli-url", null);
AbstractGeneratorHostKeyProvider keyPairProvider;
if ("simple".equalsIgnoreCase(hostKeyFormat)) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
index 5b5330c..82c8e04 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshUtils.java
@@ -39,9 +39,9 @@ public class SshUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SshUtils.class);
public static <S> List<NamedFactory<S>> filter(Class<S> type,
- Collection<NamedFactory<S>> factories, String names) {
+ Collection<NamedFactory<S>> factories, String[] names) {
List<NamedFactory<S>> list = new ArrayList<NamedFactory<S>>();
- for (String name : names.split(",")) {
+ for (String name : names) {
name = name.trim();
boolean found = false;
for (NamedFactory<S> factory : factories) {
@@ -59,17 +59,17 @@ public class SshUtils {
return list;
}
- public static List<NamedFactory<Mac>> buildMacs(String names) {
+ public static List<NamedFactory<Mac>> buildMacs(String[] names) {
return filter(Mac.class, new ServerConfig().getMacFactories(), names);
}
- public static List<NamedFactory<Cipher>> buildCiphers(String names) {
+ public static List<NamedFactory<Cipher>> buildCiphers(String[] names) {
ServerConfig defaults = new ServerConfig();
List<NamedFactory<Cipher>> avail = defaults.getCipherFactories();
return filter(Cipher.class, avail, names);
}
- public static List<NamedFactory<KeyExchange>> buildKexAlgorithms(String names) {
+ public static List<NamedFactory<KeyExchange>> buildKexAlgorithms(String[] names) {
ServerConfig defaults = new ServerConfig();
List<NamedFactory<KeyExchange>> avail = defaults.getKeyExchangeFactories();
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/UserAuthFactoriesFactory.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/UserAuthFactoriesFactory.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/UserAuthFactoriesFactory.java
index 76e61a1..994121e 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/UserAuthFactoriesFactory.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/UserAuthFactoriesFactory.java
@@ -49,11 +49,10 @@ public class UserAuthFactoriesFactory {
private Set<String> methodSet;
private List<NamedFactory<UserAuth>> factories;
- public void setAuthMethods(String methods) {
+ public void setAuthMethods(String[] methods) {
this.methodSet = new HashSet<String>();
this.factories = new ArrayList<NamedFactory<UserAuth>>();
- String[] ams = methods.split(",");
- for (String am : ams) {
+ for (String am : methods) {
if (PASSWORD_METHOD.equals(am)) {
this.factories.add(new UserAuthPasswordFactory());
} else if (KEYBOARD_INTERACTIVE_METHOD.equals(am)) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/shell/ssh/src/test/java/org/apache/karaf/shell/ssh/SshUtilsTest.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/test/java/org/apache/karaf/shell/ssh/SshUtilsTest.java b/shell/ssh/src/test/java/org/apache/karaf/shell/ssh/SshUtilsTest.java
index 5ddf77c..eda708c 100644
--- a/shell/ssh/src/test/java/org/apache/karaf/shell/ssh/SshUtilsTest.java
+++ b/shell/ssh/src/test/java/org/apache/karaf/shell/ssh/SshUtilsTest.java
@@ -36,7 +36,7 @@ public class SshUtilsTest {
// verify our default configuration...
String ciphers = "aes128-ctr,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc";
- List<NamedFactory<Cipher>> list = SshUtils.buildCiphers(ciphers);
+ List<NamedFactory<Cipher>> list = SshUtils.buildCiphers(ciphers.split(","));
// verify that all configured ciphers are actually resolved...
for (String cipher : ciphers.split(",")) {
@@ -59,7 +59,7 @@ public class SshUtilsTest {
// verify our default configuration...
String macs = "hmac-sha2-512,hmac-sha2-256,hmac-sha1";
- List<NamedFactory<Mac>> list = SshUtils.buildMacs(macs);
+ List<NamedFactory<Mac>> list = SshUtils.buildMacs(macs.split(","));
// verify that all configured HMACs are actually resolved...
for (String mac : macs.split(",")) {
@@ -82,7 +82,7 @@ public class SshUtilsTest {
// verify our default configuration...
String kexAlgorithms = "diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1";
- List<NamedFactory<KeyExchange>> list = SshUtils.buildKexAlgorithms(kexAlgorithms);
+ List<NamedFactory<KeyExchange>> list = SshUtils.buildKexAlgorithms(kexAlgorithms.split(","));
// verify that all configured key exchange algorithms are actually resolved...
for (String kex : kexAlgorithms.split(",")) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java b/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java
index cf9a201..31f30fa 100644
--- a/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java
+++ b/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java
@@ -19,10 +19,8 @@
package org.apache.karaf.util.config;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
@@ -103,9 +101,7 @@ public class PropertiesLoader {
public static void loadSystemProperties(File file) throws IOException {
Properties props = new Properties(false);
try {
- InputStream is = new FileInputStream(file);
- props.load(is);
- is.close();
+ props.load(file);
} catch (Exception e1) {
// Ignore
}
@@ -146,11 +142,8 @@ public class PropertiesLoader {
public static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception {
Properties configProps = new Properties(null, false);
- InputStream is = null;
try {
- is = configPropURL.openConnection().getInputStream();
- configProps.load(is);
- is.close();
+ configProps.load(configPropURL);
} catch (FileNotFoundException ex) {
if (failIfNotFound) {
throw ex;
@@ -161,15 +154,6 @@ public class PropertiesLoader {
System.err.println("Error loading config properties from " + configPropURL);
System.err.println("Main: " + ex);
return configProps;
- } finally {
- try {
- if (is != null) {
- is.close();
- }
- }
- catch (IOException ex2) {
- // Nothing we can do.
- }
}
loadIncludes(INCLUDES_PROPERTY, true, configPropURL, configProps);
loadIncludes(OPTIONALS_PROPERTY, false, configPropURL, configProps);
@@ -178,8 +162,8 @@ public class PropertiesLoader {
}
private static void loadIncludes(String propertyName, boolean mandatory, URL configPropURL, Properties configProps)
- throws MalformedURLException, Exception {
- String includes = (String) configProps.get(propertyName);
+ throws Exception {
+ String includes = configProps.get(propertyName);
if (includes != null) {
StringTokenizer st = new StringTokenizer(includes, "\" ", true);
if (st.countTokens() > 0) {
@@ -216,24 +200,27 @@ public class PropertiesLoader {
boolean exit = false;
while ((st.hasMoreTokens()) && (!exit)) {
tok = st.nextToken(tokenList);
- if (tok.equals("\"")) {
- inQuote = !inQuote;
- if (inQuote) {
- tokenList = "\"";
- } else {
- tokenList = "\" ";
- }
-
- } else if (tok.equals(" ")) {
- if (tokStarted) {
- retVal = tokBuf.toString();
- tokStarted = false;
- tokBuf = new StringBuffer(10);
- exit = true;
- }
- } else {
- tokStarted = true;
- tokBuf.append(tok.trim());
+ switch (tok) {
+ case "\"":
+ inQuote = !inQuote;
+ if (inQuote) {
+ tokenList = "\"";
+ } else {
+ tokenList = "\" ";
+ }
+ break;
+ case " ":
+ if (tokStarted) {
+ retVal = tokBuf.toString();
+ tokStarted = false;
+ tokBuf = new StringBuffer(10);
+ exit = true;
+ }
+ break;
+ default:
+ tokStarted = true;
+ tokBuf.append(tok.trim());
+ break;
}
}
[4/4] karaf git commit: [KARAF-5074] Better support for typed configs
for built-in features and bin/client
Posted by gn...@apache.org.
[KARAF-5074] Better support for typed configs for built-in features and bin/client
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/02dede35
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/02dede35
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/02dede35
Branch: refs/heads/master
Commit: 02dede354f5322dc8b8992b471603bd6d1f444ca
Parents: b3572bf
Author: Guillaume Nodet <gn...@apache.org>
Authored: Mon Apr 10 16:30:22 2017 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Apr 11 12:17:52 2017 +0200
----------------------------------------------------------------------
.../standard/src/main/feature/feature.xml | 14 +-
client/pom.xml | 12 +
.../org/apache/karaf/client/ClientConfig.java | 120 +-
.../apache/karaf/client/ClientConfigTest.java | 2 +-
.../karaf/features/internal/osgi/Activator.java | 4 +-
.../internal/service/BootFeaturesInstaller.java | 6 +-
.../service/FeatureConfigInstaller.java | 2 +-
.../service/BootFeaturesInstallerTest.java | 8 +-
instance/pom.xml | 1 +
.../core/internal/InstanceServiceImpl.java | 1072 ++++++++----------
.../org/apache/karaf/main/InstanceHelper.java | 51 +-
.../org/apache/karaf/shell/ssh/Activator.java | 28 +-
.../org/apache/karaf/shell/ssh/SshUtils.java | 10 +-
.../shell/ssh/UserAuthFactoriesFactory.java | 5 +-
.../apache/karaf/shell/ssh/SshUtilsTest.java | 6 +-
.../karaf/util/config/PropertiesLoader.java | 63 +-
.../apache/karaf/util/locks/FileLockUtils.java | 90 +-
.../karaf/util/tracker/BaseActivator.java | 24 +
18 files changed, 658 insertions(+), 860 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/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 95ed262..0993c27 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -199,7 +199,7 @@
# 3: DEBUG
# 4: TRACE
#
- #logLevel=1
+ #logLevel = 1
#
# Specify an additional welcome banner to be displayed when a user logs into the server.
@@ -217,6 +217,7 @@
# This property define the default value when you use the Karaf shell console.
# You can change the completion mode directly in the shell console, using shell:completion command.
#
+ completionMode = GLOBAL
#
# Override allowed SSH cipher algorithms.
@@ -242,7 +243,6 @@
#
# moduli-url = external moduli-url users wanna use
- completionMode = GLOBAL
</config>
<bundle dependency="true" start-level="30">mvn:org.fusesource.jansi/jansi/${jansi.version}</bundle>
<bundle dependency="true" start-level="30">mvn:org.jline/jline/${jline.version}</bundle>
@@ -505,13 +505,13 @@
# of lines searched for exceptions using log:exception-display. You can override this value
# at runtime using -n in log:display.
#
- size = 500
+ size = I"500"
#
# The pattern used to format the log statement when using log:display. This pattern is according
# to the log4j layout. You can override this parameter at runtime using log:display with -p.
#
- pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
+ pattern = "%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n"
</config>
<bundle start-level="30" start="true">mvn:org.apache.karaf.log/org.apache.karaf.log.core/${project.version}</bundle>
</feature>
@@ -626,12 +626,6 @@
</feature>
<feature name="ssh" description="Provide a SSHd server on Karaf" version="${project.version}">
- <config name="org.apache.karaf.shell">
- sshPort=8101
- sshHost=0.0.0.0
- sshRealm=karaf
- hostKey=${karaf.etc}/host.key
- </config>
<feature>shell</feature>
<feature>jaas</feature>
<bundle start="true" start-level="30">mvn:org.apache.sshd/sshd-core/${sshd.version}</bundle>
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 742afba..a05a0d2 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -50,6 +50,16 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
@@ -72,6 +82,8 @@
<Private-Package>
org.apache.karaf.client;
org.slf4j.impl;
+ org.apache.felix.utils.properties;
+ org.apache.karaf.util.config;
META-INF;-split-package:=merge-first
</Private-Package>
<Include-Resource>
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/client/src/main/java/org/apache/karaf/client/ClientConfig.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/karaf/client/ClientConfig.java b/client/src/main/java/org/apache/karaf/client/ClientConfig.java
index cea1241..0bfb64b 100644
--- a/client/src/main/java/org/apache/karaf/client/ClientConfig.java
+++ b/client/src/main/java/org/apache/karaf/client/ClientConfig.java
@@ -16,16 +16,14 @@
*/
package org.apache.karaf.client;
+import org.apache.felix.utils.properties.Properties;
+import org.apache.felix.utils.properties.TypedProperties;
+import org.apache.karaf.util.config.PropertiesLoader;
+
import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
-import java.util.Properties;
import java.util.Set;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class ClientConfig {
@@ -46,31 +44,23 @@ public class ClientConfig {
private String command;
private boolean interactiveMode = false;
- public ClientConfig(String[] args) throws IOException {
- Properties shellCfg = loadProps(new File(System.getProperty("karaf.etc"), "org.apache.karaf.shell.cfg"), null);
- Properties customCfg = loadProps(new File(System.getProperty("karaf.etc"), "custom.properties"), null);
-
- host = shellCfg.getProperty("sshHost", "localhost");
- host = expandEnvVars(host);
- String portString = shellCfg.getProperty("sshPort", "8101");
- portString = expandEnvVars(portString);
-
- // if sshHost of sshPort properties contain a reference to another property (coming from
- // , we try to use the custom.properties value
- if (host.contains("${")) {
- host = replaceVariable(host, "localhost", customCfg);
- }
+ private TypedProperties configuration;
+
+ public ClientConfig(String[] args) throws Exception {
+ File karafEtc = new File(System.getProperty("karaf.etc"));
+ PropertiesLoader.loadSystemProperties(new File(karafEtc, "system.properties"));
+ Properties configProps = PropertiesLoader.loadConfigProperties(new File(karafEtc, "config.properties"));
+ configuration = loadProps(new File(karafEtc, "org.apache.karaf.shell.cfg"), configProps);
+
+ host = getString("sshHost", "localhost");
if (host.contains("0.0.0.0")) {
host = "localhost";
}
- if (portString.contains("${")) {
- portString = replaceVariable(portString, "8101", customCfg);
- }
- port = Integer.parseInt(portString);
- level = Integer.parseInt(shellCfg.getProperty("logLevel", "0"));
+ port = getInt("sshPort", 8101);
+ level = getInt("logLevel", 0);
retryAttempts = 0;
retryDelay = 2;
- idleTimeout = Long.parseLong(shellCfg.getProperty("sshIdleTimeout", "1800000"));
+ idleTimeout = getLong("sshIdleTimeout", 1800000L);
batch = false;
file = null;
user = null;
@@ -171,8 +161,7 @@ public class ClientConfig {
}
command = commandBuilder.toString();
- Map<String, String> usersCfg = new LinkedHashMap<>();
- loadProps(new File(System.getProperty("karaf.etc") + "/users.properties"), usersCfg);
+ Map<String, String> usersCfg = PropertiesLoader.loadPropertiesFile(new File(karafEtc,"users.properties").toURI().toURL(), false);
if (!usersCfg.isEmpty()) {
Set<String> users = new LinkedHashSet<>();
for (String user : usersCfg.keySet()) {
@@ -216,65 +205,50 @@ public class ClientConfig {
System.exit(0);
}
- // tries a very basic variable substitution
- private static String replaceVariable(String input, String defaultValue, Properties customCfg) {
+ private static TypedProperties loadProps(File file, Properties context) {
+ TypedProperties props = new TypedProperties((name, key, value) -> context.getProperty(value));
try {
- int indexOfDollar = input.indexOf('$');
- int indexOfClosingBrace = input.indexOf('}', indexOfDollar + 1);
- String varName = input.substring(indexOfDollar + 2, indexOfClosingBrace);
- String varValue = customCfg.getProperty(varName, defaultValue);
- return input.replace("${" + varName + "}", varValue);
+ props.load(file);
} catch (Exception e) {
- return input;
+ System.err.println("Warning: could not load properties from: " + file + ": " + e);
}
+ return props;
}
- private static Properties loadProps(File file, final Map<String, String> additionalStorage) {
- Properties props = new Properties() {
- @Override
- public synchronized Object put(Object key, Object value) {
- if (additionalStorage != null) {
- additionalStorage.put((String) key, (String) value);
- }
- return super.put(key, value);
+ protected int getInt(String key, int def) {
+ if (configuration != null) {
+ Object val = configuration.get(key);
+ if (val instanceof Number) {
+ return ((Number) val).intValue();
+ } else if (val != null) {
+ return Integer.parseInt(val.toString());
}
- };
- FileInputStream is = null;
- try {
- is = new FileInputStream(file);
- props.load(is);
+ }
+ return def;
+ }
- } catch (Exception e) {
- System.err.println("Warning: could not load properties from: " + file + ", Reason: " + e.getMessage());
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- // ignore
- }
+ protected long getLong(String key, long def) {
+ if (configuration != null) {
+ Object val = configuration.get(key);
+ if (val instanceof Number) {
+ return ((Number) val).longValue();
+ } else if (val != null) {
+ return Long.parseLong(val.toString());
}
}
- return props;
+ return def;
}
-
- private static String expandEnvVars(String text) {
- Map<String, String> envMap = System.getenv();
- String pattern = "\\$\\{([A-Za-z0-9]+)\\}";
- Pattern expr = Pattern.compile(pattern);
- Matcher matcher = expr.matcher(text);
- while (matcher.find()) {
- String envValue = envMap.get(matcher.group(1).toUpperCase());
- if (envValue != null) {
- envValue = envValue.replace("\\", "\\\\");
- Pattern subexpr = Pattern.compile(Pattern.quote(matcher.group(0)));
- text = subexpr.matcher(text).replaceAll(envValue);
+ protected String getString(String key, String def) {
+ if (configuration != null) {
+ Object val = configuration.get(key);
+ if (val != null) {
+ return val.toString();
}
}
- return text;
+ return def;
}
-
+
public String getHost() {
return host;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/client/src/test/java/org/apache/karaf/client/ClientConfigTest.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/karaf/client/ClientConfigTest.java b/client/src/test/java/org/apache/karaf/client/ClientConfigTest.java
index 0732e56..7a5c7ca 100644
--- a/client/src/test/java/org/apache/karaf/client/ClientConfigTest.java
+++ b/client/src/test/java/org/apache/karaf/client/ClientConfigTest.java
@@ -26,7 +26,7 @@ import static org.junit.Assert.assertThat;
public class ClientConfigTest {
@Test
- public void testDefaultUser() throws IOException {
+ public void testDefaultUser() throws Exception {
String etc = System.getProperty("karaf.etc");
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
index ea573bd..720cbfb 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
@@ -146,7 +146,7 @@ public class Activator extends BaseActivator {
register(ManagedService.class, featureFinder, props);
List<Repository> repositories = new ArrayList<>();
- String[] resourceRepositories = getString("resourceRepositories", "").split(",");
+ String[] resourceRepositories = getStringArray("resourceRepositories", "");
long repositoryExpiration = getLong("repositoryExpiration", FeaturesService.DEFAULT_REPOSITORY_EXPIRATION);
boolean repositoryIgnoreFailures = getBoolean("repositoryIgnoreFailures", true);
for (String url : resourceRepositories) {
@@ -259,7 +259,7 @@ public class Activator extends BaseActivator {
featuresServiceMBean.setFeaturesService(featuresService);
registerMBean(featuresServiceMBean, "type=feature");
- String featuresRepositories = getString("featuresRepositories", "");
+ String[] featuresRepositories = getStringArray("featuresRepositories", "");
String featuresBoot = getString("featuresBoot", "");
boolean featuresBootAsynchronous = getBoolean("featuresBootAsynchronous", false);
BootFeaturesInstaller bootFeaturesInstaller = new BootFeaturesInstaller(
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
index 47eae9f..c04192c 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
@@ -38,7 +38,7 @@ public class BootFeaturesInstaller {
private final FeaturesServiceImpl featuresService;
private final BundleContext bundleContext;
- private final String repositories;
+ private final String[] repositories;
private final String features;
private final boolean asynchronous;
@@ -59,7 +59,7 @@ public class BootFeaturesInstaller {
public BootFeaturesInstaller(BundleContext bundleContext,
FeaturesServiceImpl featuresService,
- String repositories,
+ String[] repositories,
String features,
boolean asynchronous) {
this.bundleContext = bundleContext;
@@ -90,7 +90,7 @@ public class BootFeaturesInstaller {
protected void installBootFeatures() {
try {
- for (String repo : repositories.split(",")) {
+ for (String repo : repositories) {
repo = repo.trim();
if (!repo.isEmpty()) {
repo = separatorsToUnix(repo);
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
index ad96b63..c95104c 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -103,7 +103,7 @@ public class FeatureConfigInstaller {
for (ConfigInfo config : feature.getConfigurations()) {
TypedProperties props = new TypedProperties();
// trim lines
- String val = config.getValue().replaceAll("\n\\s+", "\n");
+ String val = config.getValue();
props.load(new StringReader(val));
String[] pid = parsePid(config.getName());
Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
index 01553d3..8f9b002 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
@@ -44,7 +44,7 @@ public class BootFeaturesInstallerTest extends TestBase {
@Test
@SuppressWarnings("unchecked")
public void testParser() {
- BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, "", "", false);
+ BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, new String[0], "", false);
Assert.assertEquals(asList(setOf("test1", "test2"), setOf("test3")), installer.parseBootFeatures(" ( test1 , test2 ) , test3 "));
Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures(" test1 , test2, test3"));
Assert.assertEquals(asList(setOf("test1"), setOf("test2"), setOf("test3")), installer.parseBootFeatures("(test1), (test2), test3"));
@@ -62,7 +62,7 @@ public class BootFeaturesInstallerTest extends TestBase {
expectLastCall();
replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "", "config,standard,region", false);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, new String[0], "config,standard,region", false);
bootFeatures.installBootFeatures();
verify(impl);
@@ -85,7 +85,7 @@ public class BootFeaturesInstallerTest extends TestBase {
expectLastCall();
replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , "", "(transaction), ssh", false);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , new String[0], "(transaction), ssh", false);
bootFeatures.installBootFeatures();
verify(impl);
}
@@ -100,7 +100,7 @@ public class BootFeaturesInstallerTest extends TestBase {
expectLastCall();
replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "mvn:inexistent/features/1.0/xml/features", "", false);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, new String[] { "mvn:inexistent/features/1.0/xml/features" }, "", false);
bootFeatures.installBootFeatures();
verify(impl);
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/02dede35/instance/pom.xml
----------------------------------------------------------------------
diff --git a/instance/pom.xml b/instance/pom.xml
index ebfeabe..f776cfc 100644
--- a/instance/pom.xml
+++ b/instance/pom.xml
@@ -134,6 +134,7 @@
org.apache.karaf.instance.core.internal.osgi,
org.apache.felix.utils.properties;-split-package:=merge-first,
org.apache.karaf.util,
+ org.apache.karaf.util.config,
org.apache.karaf.util.locks,
</Private-Package>
</instructions>