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 2014/07/21 18:32:23 UTC
[2/2] git commit: [KARAF-1718] Add support for support for
conditional bundle and feature definition inside features
[KARAF-1718] Add support for support for conditional bundle and feature definition inside features
Refactor the feature definitions a bit to leverage conditionals and make them transitively closed.
Trim down the startup.properties file to the minimum and let the FeaturesService install everything needed.
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/d380c4d0
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/d380c4d0
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/d380c4d0
Branch: refs/heads/karaf-2.x
Commit: d380c4d0cdb8857abeb006a507ba2b58978c7886
Parents: afb7ecf
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Mon Jul 21 18:31:31 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Mon Jul 21 18:31:53 2014 +0200
----------------------------------------------------------------------
.../etc/org.apache.karaf.features.cfg | 2 +-
.../filtered-resources/etc/startup.properties | 13 -
.../enterprise/src/main/resources/features.xml | 52 +++-
.../spring/src/main/resources/features.xml | 17 +-
.../standard/src/main/resources/features.xml | 197 ++++++++++----
.../features/command/InfoFeatureCommand.java | 147 ++++++++---
features/core/pom.xml | 10 +
.../org/apache/karaf/features/Conditional.java | 35 +++
.../java/org/apache/karaf/features/Feature.java | 3 +
.../karaf/features/FeaturesNamespaces.java | 4 +-
.../features/internal/ConditionalImpl.java | 61 +++++
.../karaf/features/internal/ContentImpl.java | 67 +++++
.../karaf/features/internal/FeatureImpl.java | 50 +---
.../internal/FeatureValidationUtil.java | 23 +-
.../features/internal/FeaturesServiceImpl.java | 101 +++++---
.../karaf/features/internal/RepositoryImpl.java | 154 ++++++-----
.../apache/karaf/features/osgi/Activator.java | 173 +++++++++++++
.../OSGI-INF/blueprint/gshell-features.xml | 62 -----
.../karaf/features/karaf-features-1.2.0.xsd | 254 +++++++++++++++++++
.../karaf/features/FeaturesServiceTest.java | 139 +++++++++-
.../java/org/apache/karaf/itests/JaasTest.java | 2 +-
.../webconsole/features/ExtendedFeature.java | 5 +
22 files changed, 1237 insertions(+), 334 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg b/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
index 5cd9e02..d4e4de9 100644
--- a/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
+++ b/assemblies/apache-karaf/src/main/filtered-resources/etc/org.apache.karaf.features.cfg
@@ -27,7 +27,7 @@ featuresRepositories = mvn:org.apache.karaf.assemblies.features/standard/${proje
#
# Comma separated list of features to install at startup
#
-featuresBoot = karaf-framework,config,ssh,management,kar
+featuresBoot = karaf-framework,service-security,admin,config,ssh,management,kar
#
# Defines if the boot features are started in asynchronous mode (in a dedicated thread)
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/assemblies/apache-karaf/src/main/filtered-resources/etc/startup.properties
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/src/main/filtered-resources/etc/startup.properties b/assemblies/apache-karaf/src/main/filtered-resources/etc/startup.properties
index 081e2db..8b9929e 100644
--- a/assemblies/apache-karaf/src/main/filtered-resources/etc/startup.properties
+++ b/assemblies/apache-karaf/src/main/filtered-resources/etc/startup.properties
@@ -32,20 +32,7 @@ org/ops4j/pax/url/pax-url-aether/${pax.url.version}/pax-url-aether-${pax.url.ver
org/ops4j/pax/url/pax-url-wrap/${pax.url.version}/pax-url-wrap-${pax.url.version}-uber.jar=5
org/ops4j/pax/logging/pax-logging-api/${pax.logging.version}/pax-logging-api-${pax.logging.version}.jar=8
org/ops4j/pax/logging/pax-logging-service/${pax.logging.version}/pax-logging-service-${pax.logging.version}.jar=8
-org/apache/karaf/service/org.apache.karaf.service.guard/${project.version}/org.apache.karaf.service.guard-${project.version}.jar=10
org/apache/felix/org.apache.felix.configadmin/${felix.configadmin.version}/org.apache.felix.configadmin-${felix.configadmin.version}.jar=10
org/apache/felix/org.apache.felix.fileinstall/${felix.fileinstall.version}/org.apache.felix.fileinstall-${felix.fileinstall.version}.jar=11
-
-#
-# The rest of the services..
-#
-org/ow2/asm/asm-all/${asm.version}/asm-all-${asm.version}.jar=20
-org/apache/aries/org.apache.aries.util/${aries.util.version}/org.apache.aries.util-${aries.util.version}.jar=20
-org/apache/aries/proxy/org.apache.aries.proxy.api/${aries.proxy.api.version}/org.apache.aries.proxy.api-${aries.proxy.api.version}.jar=20
-org/apache/aries/proxy/org.apache.aries.proxy.impl/${aries.proxy.version}/org.apache.aries.proxy.impl-${aries.proxy.version}.jar=20
-org/apache/aries/blueprint/org.apache.aries.blueprint.api/${aries.blueprint.api.version}/org.apache.aries.blueprint.api-${aries.blueprint.api.version}.jar=20
-org/apache/aries/blueprint/org.apache.aries.blueprint.core/${aries.blueprint.core.version}/org.apache.aries.blueprint.core-${aries.blueprint.core.version}.jar=20
-org/apache/aries/blueprint/org.apache.aries.blueprint.cm/${aries.blueprint.cm.version}/org.apache.aries.blueprint.cm-${aries.blueprint.cm.version}.jar=20
-
org/apache/karaf/features/org.apache.karaf.features.core/${project.version}/org.apache.karaf.features.core-${project.version}.jar=30
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/assemblies/features/enterprise/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/resources/features.xml b/assemblies/features/enterprise/src/main/resources/features.xml
index 76c0127..7df05e1 100644
--- a/assemblies/features/enterprise/src/main/resources/features.xml
+++ b/assemblies/features/enterprise/src/main/resources/features.xml
@@ -18,8 +18,9 @@
limitations under the License.
-->
-<features name="karaf-enterprise-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+<features name="karaf-enterprise-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.apache.karaf.assemblies.features/standard/${project.version}/xml/features</repository>
<repository>mvn:org.ops4j.pax.cdi/pax-cdi-features/${pax.cdi.version}/xml/features</repository>
<feature name="transaction" description="OSGi Transaction Manager" version="1.0.0" resolver="(obr)">
@@ -33,8 +34,12 @@
aries.transaction.howl.bufferSizeKBytes = 4
</config>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/${geronimo.jta-spec.version}</bundle>
- <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.0</bundle>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ </conditional>
</feature>
<feature name="transaction" description="OSGi Transaction Manager" version="1.1.0" resolver="(obr)">
@@ -48,8 +53,12 @@
aries.transaction.howl.bufferSizeKBytes = 4
</config>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/${geronimo.jta-spec.version}</bundle>
- <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.1.0</bundle>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ </conditional>
</feature>
<feature name="transaction" description="OSGi Transaction Manager" version="1.0.1" resolver="(obr)">
@@ -63,8 +72,12 @@
aries.transaction.howl.bufferSizeKBytes = 4
</config>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/${geronimo.jta-spec.version}</bundle>
- <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/${aries.transaction.blueprint.version}</bundle>
+ </conditional>
</feature>
<feature name="connector" description="OSGi support for JCA Connector 1.5" version="2.2.2" resolver="(obr)">
@@ -86,20 +99,28 @@
<details>JPA 2.0 implementation provided by Apache Aries JPA 1.0.1. NB: this feature doesn't provide the JPA engine, you have to install one by yourself (OpenJPA for instance)</details>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/${geronimo.jta-spec.version}</bundle>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jpa_2.0_spec/${geronimo.jpa-spec.version}</bundle>
+ <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.api/1.0.0</bundle>
- <bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.blueprint.aries/1.0.1</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container.context/1.0.1</bundle>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.blueprint.aries/1.0.1</bundle>
+ </conditional>
</feature>
<feature name="jpa" description="OSGi Persistence Container" version="${aries.jpa.version}" resolver="(obr)">
<details>JPA 2.1 implementation provided by Apache Aries JPA ${aries.jpa.version}. NB: this feature doesn't provide the JPA engine, you have to install one by yourself (OpenJPA for instance)</details>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/${geronimo.jta-spec.version}</bundle>
<bundle dependency="true" start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0.Final</bundle>
+ <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.api/${aries.jpa.api.version}</bundle>
- <bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.blueprint.aries/${aries.jpa.blueprint.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container/${aries.jpa.container.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container.context/${aries.jpa.container.context.version}</bundle>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.blueprint.aries/${aries.jpa.blueprint.version}</bundle>
+ </conditional>
</feature>
<feature name="openjpa" description="Apache OpenJPA 2.2.x persistent engine support" version="2.2.2" resolver="(obr)">
@@ -222,6 +243,7 @@
<feature name="jndi" description="OSGi Service Registry JNDI access" version="${aries.jndi.version}" resolver="(obr)">
<details>JNDI support provided by Apache Aries JNDI ${aries.jndi.version}</details>
+ <feature>management</feature>
<bundle start-level="30">mvn:org.apache.xbean/xbean-naming/${xbean.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.core/${project.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.api/${aries.jndi.api.version}</bundle>
@@ -229,24 +251,35 @@
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.rmi/${aries.jndi.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.url/${aries.jndi.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.legacy.support/${aries.jndi.version}</bundle>
- <bundle>mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.command/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle>mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.command/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="jdbc" description="JDBC service and commands" version="${project.version}" resolver="(obr)">
<details>JDBC support providing service, commands, and MBean</details>
<feature>transaction</feature>
+ <feature>management</feature>
<bundle>mvn:commons-pool/commons-pool/${commons-pool.version}</bundle>
<bundle>mvn:commons-dbcp/commons-dbcp/${commons-dbcp.version}</bundle>
<bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.core/${project.version}</bundle>
- <bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.command/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.command/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="jms" description="JMS service and commands" version="${project.version}" resolver="(obr)">
<details>JMS support provinding service, commands, and MBean.</details>
<feature>transaction</feature>
+ <feature>management</feature>
<bundle>mvn:org.apache.geronimo.specs/geronimo-jms_1.1_spec/${geronimo.jms-spec.version}</bundle>
<bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.core/${project.version}</bundle>
- <bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.command/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.command/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="openwebbeans" description="Apache OpenWebBeans CDI container support" version="${openwebbeans.version}" resolver="(obr)">
@@ -265,6 +298,7 @@
<feature name="application-without-isolation" description="Provide EBA archive support" version="${aries.application.version}">
<details>Support of the Aries EBA archives</details>
+ <feature>aries-blueprint</feature>
<feature version="${project.version}">obr</feature>
<!-- commom -->
<bundle start-level="30">mvn:org.apache.aries.application/org.apache.aries.application.resolver.obr/${aries.application.version}</bundle>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/assemblies/features/spring/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/spring/src/main/resources/features.xml b/assemblies/features/spring/src/main/resources/features.xml
index 788084a..518e94b 100644
--- a/assemblies/features/spring/src/main/resources/features.xml
+++ b/assemblies/features/spring/src/main/resources/features.xml
@@ -18,7 +18,7 @@
-->
<features name="spring-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.0.0 http://karaf.apache.org/xmlns/features/v1.0.0">
- <!-- NB: this file is not the one really used. This file is used by the karaf-maven-plugin to define the start-level of bundles in the generated feature.xml -->
+ <repository>mvn:org.apache.karaf.assemblies.features/standard/${project.version}/xml/features</repository>
<!-- Spring DM support -->
<feature name="spring-dm" description="Spring DM support" version="${spring.osgi.version}">
@@ -28,7 +28,6 @@
<bundle start-level="30">mvn:org.springframework.osgi/spring-osgi-core/${spring.osgi.version}</bundle>
<bundle start-level="30">mvn:org.springframework.osgi/spring-osgi-extender/${spring.osgi.version}</bundle>
<bundle start-level="30">mvn:org.springframework.osgi/spring-osgi-annotation/${spring.osgi.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
</feature>
<feature name="spring-dm-web" description="Spring DM Web support" version="${spring.osgi.version}">
@@ -49,7 +48,6 @@
<bundle start-level="30">mvn:org.springframework/spring-aop/${spring31.version}</bundle>
<bundle start-level="30">mvn:org.springframework/spring-context/${spring31.version}</bundle>
<bundle start-level="30">mvn:org.springframework/spring-context-support/${spring31.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
</feature>
<feature name="spring-aspects" description="Spring 3.1.x AOP support" version="${spring31.version}">
@@ -126,7 +124,6 @@
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-aop/${spring32.version}</bundle>
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-context/${spring32.version}</bundle>
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-context-support/${spring32.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
</feature>
<feature name="spring-aspects" description="Spring 3.2.x AOP support" version="${spring32.version}">
@@ -203,7 +200,6 @@
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-aop/${spring40.version}</bundle>
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-context/${spring40.version}</bundle>
<bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-context-support/${spring40.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
</feature>
<feature name="spring-aspects" description="Spring 4.0.x AOP support" version="${spring40.version}">
@@ -270,7 +266,7 @@
<feature name="spring-security" description="Spring Security 3.1.x support" version="${spring.security31.version}">
<feature>war</feature>
- <feature version="[3,4)">spring-web</feature>
+ <feature version="[3,4)">spring-web</feature>
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aspectj/${aspectj.bundle.version}</bundle>
<bundle start-level="30">mvn:org.springframework.security/spring-security-core/${spring.security31.version}</bundle>
<bundle start-level="30">mvn:org.springframework.security/spring-security-config/${spring.security31.version}</bundle>
@@ -279,13 +275,4 @@
<bundle start-level="30">mvn:org.springframework.security/spring-security-taglibs/${spring.security31.version}</bundle>
</feature>
- <!-- Gemini Blueprint support -->
-
- <feature name="gemini-blueprint" description="Gemini Blueprint Extender" version="${gemini.blueprint.version}">
- <feature version="[3,4)">spring</feature>
- <bundle start-level="30">mvn:org.eclipse.gemini/org.eclipse.gemini.blueprint.io/${gemini.blueprint.version}</bundle>
- <bundle start-level="30">mvn:org.eclipse.gemini/org.eclipse.gemini.blueprint.core/${gemini.blueprint.version}</bundle>
- <bundle start-level="30">mvn:org.eclipse.gemini/org.eclipse.gemini.blueprint.extender/${gemini.blueprint.version}</bundle>
- </feature>
-
</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/assemblies/features/standard/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/resources/features.xml b/assemblies/features/standard/src/main/resources/features.xml
index bc9427c..fb4afcc 100644
--- a/assemblies/features/standard/src/main/resources/features.xml
+++ b/assemblies/features/standard/src/main/resources/features.xml
@@ -16,53 +16,29 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<features name="karaf-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+<features name="karaf-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
<repository>mvn:org.ops4j.pax.web/pax-web-features/${pax.web.version}/xml/features</repository>
+ <!--
+ <feature name="framework-security" version="${project.version}" description="OSGi Security for Karaf">
+ <bundle start="false" start-level="1">mvn:org.apache.felix/org.apache.felix.framework.security/${felix.framework.security.version}</bundle>
+ </feature>
+ -->
+
+ <feature name="service-security" version="${project.version}" description="Services Security for Karaf">
+ <feature>aries-proxy</feature>
+ <bundle start="true" start-level="10">mvn:org.apache.karaf.service/org.apache.karaf.service.guard/${project.version}</bundle>
+ </feature>
+
<feature name="karaf-framework" description="Karaf core feature" version="${project.version}" resolver="(obr)">
<bundle start-level="5">mvn:org.ops4j.pax.url/pax-url-aether/${pax.url.version}</bundle>
<bundle start-level="5">mvn:org.ops4j.pax.url/pax-url-wrap/${pax.url.version}/jar/uber</bundle>
<bundle start-level="8">mvn:org.ops4j.pax.logging/pax-logging-api/${pax.logging.version}</bundle>
<bundle start-level="8">mvn:org.ops4j.pax.logging/pax-logging-service/${pax.logging.version}</bundle>
- <bundle start-level="10">mvn:org.apache.karaf.service/org.apache.karaf.service.guard/${project.version}</bundle>
<bundle start-level="10">mvn:org.apache.felix/org.apache.felix.configadmin/${felix.configadmin.version}</bundle>
<bundle start-level="11">mvn:org.apache.felix/org.apache.felix.fileinstall/${felix.fileinstall.version}</bundle>
- <bundle start-level="20">mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries.proxy/org.apache.aries.proxy.api/${aries.proxy.api.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries.proxy/org.apache.aries.proxy.impl/${aries.proxy.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.api/${aries.blueprint.api.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.core/${aries.blueprint.core.version}</bundle>
- <bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.cm/${aries.blueprint.cm.version}</bundle>
- <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.gogo.runtime/${felix.gogo.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.console/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.osgi/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.log/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.packages/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.dev/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.config/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.modules/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.command/${project.version}</bundle>
<bundle start-level="25">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.command/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.management/${project.version}</bundle>
-
- <bundle start-level="28">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
- <bundle start-level="28">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.blueprint/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.features/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.wrap/${project.version}</bundle>
-
- <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.management/${project.version}</bundle>
-
- <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.core/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.common/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.command/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.management/${project.version}</bundle>
</feature>
<feature name="aries-proxy" description="Aries Proxy" version="${project.version}">
@@ -76,11 +52,86 @@
<feature>aries-proxy</feature>
<bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.api/${aries.blueprint.api.version}</bundle>
<bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.cm/${aries.blueprint.cm.version}</bundle>
+ <!--
<bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.core.compatibility/${aries.blueprint.core.compatibility.version}</bundle>
+ -->
<bundle start-level="20">mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.core/${aries.blueprint.core.version}</bundle>
</feature>
+ <feature name="features" description="Karaf Features support" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <bundle start-level="25">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.command/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>management</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.management/${project.version}</bundle>
+ </conditional>
+ </feature>
+
+ <feature name="admin" description="Child instance administration" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <feature>shell</feature>
+ <feature>features</feature>
+ <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/${project.version}</bundle>
+ <conditional>
+ <condition>management</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.admin/org.apache.karaf.admin.management/${project.version}</bundle>
+ </conditional>
+ </feature>
+
+ <feature name="diagnostic" description="Diagnostic support" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.core/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.common/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.command/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>management</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.management/${project.version}</bundle>
+ </conditional>
+ </feature>
+
+ <feature name="shell" description="Karaf Shell" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <feature>jaas</feature>
+ <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.gogo.runtime/${felix.gogo.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.console/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.osgi/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.log/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.packages/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.dev/${project.version}</bundle>
+ </feature>
+
+ <feature name="deployer" description="Karaf Deployer" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <bundle start="true" start-level="26">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.features/${project.version}</bundle>
+ <conditional>
+ <condition>wrap</condition>
+ <bundle start="true" start-level="24">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.wrap/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>aries-blueprint</condition>
+ <bundle start="true" start-level="24">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.blueprint/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>spring</condition>
+ <bundle start="true" start-level="24">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>kar</condition>
+ <bundle start="true" start-level="24">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}</bundle>
+ </conditional>
+ </feature>
+
<feature name="wrapper" description="Provide OS integration" version="${project.version}">
+ <feature>shell</feature>
<bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/${project.version}</bundle>
</feature>
<feature name="service-wrapper" description="Provide OS integration (alias to wrapper feature)" version="${project.version}">
@@ -88,15 +139,20 @@
</feature>
<feature name="obr" description="Provide OSGi Bundle Repository (OBR) support" version="${project.version}">
+ <feature>shell</feature>
<bundle start-level="30">mvn:org.apache.felix/org.osgi.service.obr/${felix.obr.version}</bundle>
<bundle start-level="30">mvn:org.apache.felix/org.apache.felix.bundlerepository/${felix.bundlerepository.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/${project.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.obr/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.management.mbeans/org.apache.karaf.management.mbeans.obr/${project.version}</bundle>
<bundle start-level="30">mvn:org.ops4j.pax.url/pax-url-obr/${pax.url.version}/jar/uber</bundle>
+ <conditional>
+ <condition>management</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.management.mbeans/org.apache.karaf.management.mbeans.obr/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="config" description="Provide OSGi ConfigAdmin support" version="${project.version}">
+ <feature>shell</feature>
<bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.config/${project.version}</bundle>
</feature>
@@ -117,26 +173,51 @@
</feature>
<feature name="kar" description="Provide KAR (KARaf archive) support" version="${project.version}">
+ <feature>aries-blueprint</feature>
<bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}</bundle>
</feature>
- <feature name="webconsole-base" description="Base support of the Karaf WebConsole" version="${project.version}">
+ <feature name="webconsole" description="Karaf WebConsole for administration and monitoring" version="${project.version}">
<config name="org.apache.karaf.webconsole">
realm=karaf
role=${karaf.admin.role}
</config>
<feature>http</feature>
+ <feature>aries-blueprint</feature>
+ <feature>jaas</feature>
<bundle start-level="30">mvn:org.apache.felix/org.apache.felix.metatype/${felix.metatype.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/${project.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.console/${project.version}</bundle>
+ <conditional>
+ <condition>features</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>shell</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>eventadmin</condition>
+ <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/${felix.eventadmin.webconsole.plugin.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>scr</condition>
+ <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.webconsole.plugins.ds/${felix.scr.webconsole.plugin.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>instance</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/${project.version}</bundle>
+ </conditional>
</feature>
- <feature name="webconsole" description="Karaf WebConsole for administration and monitoring" version="${project.version}">
- <feature version="${project.version}">webconsole-base</feature>
- <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/${felix.eventadmin.webconsole.plugin.version}</bundle>
+ <feature name="jaas" description="Provide JAAS support" version="${project.version}">
+ <feature>aries-blueprint</feature>
+ <bundle start-level="30" start="true">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.config/${project.version}</bundle>
+ <bundle start-level="30" start="true">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.modules/${project.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle start-level="30" start="true">mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.command/${project.version}</bundle>
+ </conditional>
</feature>
<feature name="ssh" description="Provide a SSHd server on Karaf" version="${project.version}">
@@ -146,12 +227,16 @@
sshRealm=karaf
hostKey=${karaf.etc}/host.key
</config>
+ <feature>shell</feature>
+ <feature>jaas</feature>
<bundle start-level="30" dependency='true'>mvn:org.apache.mina/mina-core/${mina.version}</bundle>
<bundle start-level="30" dependency='true'>mvn:org.apache.sshd/sshd-core/${sshd.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/${project.version}</bundle>
</feature>
<feature name="management" description="Provide a JMX MBeanServer and a set of MBeans in Karaf" version="${project.version}">
+ <feature>jaas</feature>
+ <feature>aries-blueprint</feature>
<bundle start-level="30">mvn:org.apache.karaf.management/org.apache.karaf.management.server/${project.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jmx/org.apache.aries.jmx.api/${aries.jmx.api.version}</bundle>
<bundle start-level="30">mvn:org.apache.aries.jmx/org.apache.aries.jmx.core/${aries.jmx.core.version}</bundle>
@@ -171,6 +256,8 @@
</feature>
<feature name="jasypt-encryption" description="Advanced encryption support for Karaf security" version="${project.version}" resolver="(obr)">
+ <feature>aries-blueprint</feature>
+ <feature>jaas</feature>
<bundle dependency="true" start-level="30">mvn:commons-codec/commons-codec/${commons-codec.version}</bundle>
<bundle dependency='true' start-level="30">mvn:commons-lang/commons-lang/${commons-lang.version}</bundle>
<bundle dependency='true' start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/${jasypt.bundle.version}</bundle>
@@ -179,20 +266,26 @@
<feature name="blueprint-web" description="Provides an OSGi-aware Servlet ContextListener for bootstrapping blueprint inside web-bundle containers" version="${project.version}" resolver="(obr)">
<feature>war</feature>
+ <feature>aries-blueprint</feature>
<bundle>mvn:org.apache.aries.blueprint/org.apache.aries.blueprint.webosgi/${aries.blueprint.web.version}</bundle>
</feature>
<feature name="scr" description="Declarative Service support" version="${project.version}" resolver="(obr)">
<feature>eventadmin</feature>
<bundle dependency="true" start-level="30">mvn:org.apache.felix/org.apache.felix.metatype/${felix.metatype.version}</bundle>
- <bundle dependency="true" start-level="30">mvn:org.apache.felix/org.apache.felix.scr/${felix.scr.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.scr/${project.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.management.mbeans/org.apache.karaf.management.mbeans.scr/${project.version}</bundle>
- </feature>
- <feature name="webconsole-scr" description="WebConsole SCR plugin support" version="${project.version}" resolver="(obr)">
- <feature>scr</feature>
- <feature>webconsole</feature>
- <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.webconsole.plugins.ds/${felix.scr.webconsole.plugin.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.scr/${felix.scr.version}</bundle>
+ <conditional>
+ <condition>shell</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.scr/${project.version}</bundle>
+ </conditional>
+ <conditional>
+ <condition>management</condition>
+ <bundle start-level="30">mvn:org.apache.karaf.management.mbeans/org.apache.karaf.management.mbeans.scr/${project.version}</bundle>
+ </conditional>
+ </feature>
+
+ <feature name="wrap" description="Wrap URL handler">
+ <bundle start="true" start-level="5">mvn:org.ops4j.pax.url/pax-url-wrap/${pax.url.version}/jar/uber</bundle>
</feature>
</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
index 6b2f74d..1f6b32d 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
@@ -16,6 +16,8 @@
*/
package org.apache.karaf.features.command;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -23,6 +25,7 @@ import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
import org.apache.karaf.features.ConfigFileInfo;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
@@ -33,7 +36,11 @@ import org.apache.karaf.features.FeaturesService;
@Command(scope = "features", name = "info", description = "Shows information about selected feature.")
public class InfoFeatureCommand extends FeaturesCommandSupport {
- @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
+ private static final String INDENT = " ";
+ private static final String FEATURE_CONTENT = "Feature";
+ private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
+
+ @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
private String name;
@Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
@@ -48,6 +55,9 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
@Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
private boolean bundle;
+ @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
+ private boolean conditional;
+
@Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
private boolean tree;
@@ -66,10 +76,11 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
}
// default behavior
- if (!config && !dependency && !bundle) {
+ if (!config && !dependency && !bundle && !conditional) {
config = true;
dependency = true;
bundle = true;
+ conditional = true;
}
System.out.println("Description of " + feature.getName() + " " + feature.getVersion() + " feature");
@@ -82,16 +93,20 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
System.out.println("----------------------------------------------------------------");
}
if (config) {
- displayConfigInformation(feature);
- displayConfigFileInformation(feature);
+ displayConfigInformation(feature, FEATURE_CONTENT);
+ displayConfigFileInformation(feature, FEATURE_CONTENT);
}
if (dependency) {
- displayDependencyInformation(feature);
+ displayDependencyInformation(feature, FEATURE_CONTENT);
}
if (bundle) {
- displayBundleInformation(feature);
+ displayBundleInformation(feature, FEATURE_CONTENT);
+ }
+
+ if(conditional) {
+ displayConditionalInfo(feature);
}
if (tree) {
@@ -99,7 +114,7 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
System.out.println("\nFeature tree");
}
- int unresolved = displayFeatureTree(admin, feature, 0, false);
+ int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
if (unresolved > 0) {
System.out.println("Tree contains " + unresolved + " unresolved dependencies");
System.out.println(" * means that node declares dependency but the dependant feature is not available.");
@@ -107,12 +122,12 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
}
}
- private void displayBundleInformation(Feature feature) {
+ private void displayBundleInformation(Feature feature, String contentType) {
List<BundleInfo> bundleInfos = feature.getBundles();
if (bundleInfos.isEmpty()) {
- System.out.println("Feature has no bundles.");
+ System.out.println(contentType + " has no bundles.");
} else {
- System.out.println("Feature contains followed bundles:");
+ System.out.println(contentType + " contains followed bundles:");
for (BundleInfo featureBundle : bundleInfos) {
int startLevel = featureBundle.getStartLevel();
StringBuilder sb = new StringBuilder();
@@ -125,36 +140,36 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
}
}
- private void displayDependencyInformation(Feature feature) {
+ private void displayDependencyInformation(Feature feature, String contentType) {
List<Feature> dependencies = feature.getDependencies();
if (dependencies.isEmpty()) {
- System.out.println("Feature has no dependencies.");
+ System.out.println(contentType + " has no dependencies.");
} else {
- System.out.println("Feature depends on:");
+ System.out.println(contentType + " depends on:");
for (Feature featureDependency : dependencies) {
- System.out.println(" " + featureDependency.getName() + " " + featureDependency.getVersion());
+ System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
}
}
}
- private void displayConfigInformation(Feature feature) {
+ private void displayConfigInformation(Feature feature, String contentType) {
Map<String, Map<String, String>> configurations = feature.getConfigurations();
if (configurations.isEmpty()) {
- System.out.println("Feature has no configuration");
+ System.out.println(contentType + " has no configuration");
} else {
- System.out.println("Feature configuration:");
+ System.out.println(contentType + " configuration:");
for (String name : configurations.keySet()) {
System.out.println(" " + name);
}
}
}
- private void displayConfigFileInformation(Feature feature) {
+ private void displayConfigFileInformation(Feature feature, String contentType) {
List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
if (configurationFiles.isEmpty()) {
- System.out.println("Feature has no configuration files");
+ System.out.println(contentType + " has no configuration files");
} else {
- System.out.println("Feature configuration files: ");
+ System.out.println(contentType + " configuration files: ");
for (ConfigFileInfo configFileInfo : configurationFiles) {
System.out.println(" " + configFileInfo.getFinalname());
}
@@ -162,31 +177,54 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
}
- private int displayFeatureTree(FeaturesService admin, Feature feature, int level, boolean last) throws Exception {
+ private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
int unresolved = 0;
- String prefix = repeat(" ", level);
- Feature resolved = resolveFeature(admin, feature);
+ Feature resolved = admin.getFeature(featureName, featureVersion);
if (resolved != null) {
System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
} else {
- System.out.println(prefix + " " + feature.getName() + " " + feature.getVersion() + " *");
+ System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
unresolved++;
}
- if (bundle) {
- List<BundleInfo> bundles = resolved != null ? resolved.getBundles() : feature.getBundles();
- for (int i = 0, j = bundles.size(); i < j; i++) {
- System.out.println(prefix + " " + (i+1 == j ? "\\" : "+") + " " + bundles.get(i).getLocation());
+ if (resolved != null) {
+ if (bundle) {
+ List<String> bundleLocation = new LinkedList<String>();
+ List<BundleInfo> bundles = resolved.getBundles();
+ for (BundleInfo bundleInfo : bundles) {
+ bundleLocation.add(bundleInfo.getLocation());
+ }
+
+ if (conditional) {
+ for (Conditional cond : resolved.getConditional()) {
+ List<? extends Feature> condition = cond.getCondition();
+ List<BundleInfo> conditionalBundles = cond.getBundles();
+ for (BundleInfo bundleInfo : conditionalBundles) {
+ bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
+ }
+ }
+ }
+ for (int i = 0, j = bundleLocation.size(); i < j; i++) {
+ System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
+ }
}
- }
- List<Feature> dependencies = resolved != null ? resolved.getDependencies() : feature.getDependencies();
- for (int i = 0, j = dependencies.size(); i < j; i++) {
- Feature toDisplay = resolveFeature(admin, dependencies.get(i));
- if (toDisplay == null) {
- toDisplay = dependencies.get(i);
+ prefix += " ";
+ List<Feature> dependencies = resolved.getDependencies();
+ for (int i = 0, j = dependencies.size(); i < j; i++) {
+ Feature toDisplay = dependencies.get(i);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+ }
+
+ if (conditional) {
+ for (Conditional cond : resolved.getConditional()) {
+ List<Feature> conditionDependencies = cond.getDependencies();
+ for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
+ Feature toDisplay = dependencies.get(i);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+ }
+ }
}
- unresolved += displayFeatureTree(admin, toDisplay, level+1, i + 1 == j);
}
return unresolved;
@@ -207,4 +245,43 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
return string + repeat(string+string, times/2);
}
}
+
+ private void displayConditionalInfo(Feature feature) {
+ List<? extends Conditional> conditionals = feature.getConditional();
+ if (conditionals.isEmpty()) {
+ System.out.println("Feature has no conditionals.");
+ } else {
+ System.out.println("Feature contains followed conditionals:");
+ for (Conditional featureConditional : conditionals) {
+ String conditionDescription = getConditionDescription(featureConditional);
+ Feature wrappedConditional = featureConditional.asFeature(feature.getName(), feature.getVersion());
+ if (config) {
+ displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+
+ if (dependency) {
+ displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+
+ if (bundle) {
+ displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+ }
+ }
+ }
+
+ private String getConditionDescription(Conditional cond) {
+ StringBuffer sb = new StringBuffer();
+ Iterator<? extends Feature> di = cond.getCondition().iterator();
+ while (di.hasNext()) {
+ Feature dep = di.next();
+ sb.append(dep.getName()).append("/").append(dep.getVersion());
+ if (di.hasNext()) {
+ sb.append(" ");
+ }
+ }
+ return sb.toString();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/pom.xml
----------------------------------------------------------------------
diff --git a/features/core/pom.xml b/features/core/pom.xml
index 6aef1bc..2f71b54 100644
--- a/features/core/pom.xml
+++ b/features/core/pom.xml
@@ -117,10 +117,20 @@
</Import-Package>
<Private-Package>
org.apache.karaf.features.internal,
+ org.apache.karaf.features.osgi,
org.apache.felix.utils.version;-split-package:=merge-first,
org.apache.felix.utils.manifest;-split-package:=merge-first,
org.apache.karaf.util.collections;-split-package:=merge-first
</Private-Package>
+ <Bundle-Activator>
+ org.apache.karaf.features.osgi.Activator
+ </Bundle-Activator>
+ <Provide-Capability>
+ osgi.service;effective:=active;objectClass="org.apache.karaf.features.FeaturesService"
+ </Provide-Capability>
+ <Require-Capability>
+ osgi.service;effective:=active;filter:="(objectClass=org.osgi.service.cm.ConfigurationAdmin)"
+ </Require-Capability>
</instructions>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/Conditional.java
new file mode 100644
index 0000000..5a44e00
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Conditional.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features;
+
+import java.util.List;
+import java.util.Map;
+
+public interface Conditional {
+
+ List<Feature> getCondition();
+
+ List<Feature> getDependencies();
+
+ List<BundleInfo> getBundles();
+
+ Map<String, Map<String, String>> getConfigurations();
+
+ List<ConfigFileInfo> getConfigurationFiles();
+
+ Feature asFeature(String name, String version);
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Feature.java b/features/core/src/main/java/org/apache/karaf/features/Feature.java
index b87bc97..37829da 100644
--- a/features/core/src/main/java/org/apache/karaf/features/Feature.java
+++ b/features/core/src/main/java/org/apache/karaf/features/Feature.java
@@ -47,4 +47,7 @@ public interface Feature {
Map<String, Map<String, String>> getConfigurations();
List<ConfigFileInfo> getConfigurationFiles();
+
+ List<Conditional> getConditional();
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/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 1a1bae2..921c832 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
@@ -25,12 +25,14 @@ public interface FeaturesNamespaces {
String URI_0_0_0 = "";
String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0";
String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0";
+ String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0";
- String URI_CURRENT = URI_1_1_0;
+ String URI_CURRENT = URI_1_2_0;
QName FEATURES_0_0_0 = new QName("features");
QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features");
+ QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features");
QName FEATURES_CURRENT = FEATURES_1_1_0;
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/internal/ConditionalImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/ConditionalImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/ConditionalImpl.java
new file mode 100644
index 0000000..78637aa
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/ConditionalImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.Feature;
+
+public class ConditionalImpl extends ContentImpl implements Conditional {
+
+ private List<Feature> conditions = new ArrayList<Feature>();
+
+ public List<Feature> getCondition() {
+ return conditions;
+ }
+
+ public void addCondition(Feature condition) {
+ conditions.add(condition);
+ }
+
+ public Feature asFeature(String name, String version) {
+ String conditionName = name + "-condition-" + getConditionId().replaceAll("[^A-Za-z0-9 ]", "_");
+ FeatureImpl f = new FeatureImpl(conditionName, version);
+ f.getBundles().addAll(getBundles());
+ f.getConfigurations().putAll(getConfigurations());
+ f.getConfigurationFiles().addAll(getConfigurationFiles());
+ f.getDependencies().addAll(getDependencies());
+ return f;
+ }
+
+ private String getConditionId() {
+ StringBuilder sb = new StringBuilder();
+ Iterator<Feature> di = getCondition().iterator();
+ while (di.hasNext()) {
+ Feature dependency = di.next();
+ sb.append(dependency.getName()).append("_").append(dependency.getVersion());
+ if (di.hasNext()) {
+ sb.append("_");
+ }
+ }
+ return sb.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/internal/ContentImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/ContentImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/ContentImpl.java
new file mode 100644
index 0000000..ac0bb19
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/ContentImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Feature;
+
+public class ContentImpl {
+
+ private List<Feature> dependencies = new ArrayList<Feature>();
+ private List<BundleInfo> bundles = new ArrayList<BundleInfo>();
+ private Map<String, Map<String,String>> configs = new HashMap<String, Map<String,String>>();
+ private List<ConfigFileInfo> configurationFiles = new ArrayList<ConfigFileInfo>();
+
+ public List<Feature> getDependencies() {
+ return dependencies;
+ }
+
+ public List<BundleInfo> getBundles() {
+ return bundles;
+ }
+
+ public Map<String, Map<String, String>> getConfigurations() {
+ return configs;
+ }
+
+ public List<ConfigFileInfo> getConfigurationFiles() {
+ return configurationFiles;
+ }
+
+ public void addDependency(Feature dependency) {
+ dependencies.add(dependency);
+ }
+
+ public void addBundle(BundleInfo bundle) {
+ bundles.add(bundle);
+ }
+
+ public void addConfig(String name, Map<String,String> properties) {
+ configs.put(name, properties);
+ }
+
+ public void addConfigurationFile(ConfigFileInfo configurationFileInfo) {
+ configurationFiles.add(configurationFileInfo);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
index a4b4259..f0e9247 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
@@ -17,18 +17,19 @@
package org.apache.karaf.features.internal;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Conditional;
import org.apache.karaf.features.Feature;
/**
* A feature
*/
-public class FeatureImpl implements Feature {
+public class FeatureImpl extends ContentImpl implements Feature {
+
+ public static String SPLIT_FOR_NAME_AND_VERSION = "_split_for_name_and_version_";
+ public static String DEFAULT_VERSION = "0.0.0";
+ public static String VERSION_PREFIX = "version=";
private String id;
private String name;
@@ -37,13 +38,7 @@ public class FeatureImpl implements Feature {
private String version;
private String resolver;
private String install = DEFAULT_INSTALL_MODE;
- private List<Feature> dependencies = new ArrayList<Feature>();
- private List<BundleInfo> bundles = new ArrayList<BundleInfo>();
- private Map<String, Map<String,String>> configs = new HashMap<String, Map<String,String>>();
- private List<ConfigFileInfo> configurationFiles = new ArrayList<ConfigFileInfo>();
- public static String SPLIT_FOR_NAME_AND_VERSION = "_split_for_name_and_version_";
- public static String DEFAULT_VERSION = "0.0.0";
- public static String VERSION_PREFIX = "version=";
+ private List<Conditional> conditionals = new ArrayList<Conditional>();
public FeatureImpl() {
}
@@ -106,35 +101,12 @@ public class FeatureImpl implements Feature {
this.install = install;
}
- public List<Feature> getDependencies() {
- return dependencies;
- }
-
- public List<BundleInfo> getBundles() {
- return bundles;
+ public List<Conditional> getConditional() {
+ return conditionals;
}
- public Map<String, Map<String, String>> getConfigurations() {
- return configs;
- }
-
- public List<ConfigFileInfo> getConfigurationFiles() {
- return configurationFiles;
- }
- public void addDependency(Feature dependency) {
- dependencies.add(dependency);
- }
-
- public void addBundle(BundleInfo bundle) {
- bundles.add(bundle);
- }
-
- public void addConfig(String name, Map<String,String> properties) {
- configs.put(name, properties);
- }
-
- public void addConfigurationFile(ConfigFileInfo configurationFileInfo) {
- configurationFiles.add(configurationFileInfo);
+ public void addConditional(Conditional conditional) {
+ conditionals.add(conditional);
}
public String toString() {
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java
index dda1a87..09e6342 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeatureValidationUtil.java
@@ -15,12 +15,12 @@
*/
package org.apache.karaf.features.internal;
-import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URLConnection;
import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
@@ -28,7 +28,9 @@ import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
+import org.apache.karaf.features.FeaturesNamespaces;
import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
/**
* Utility class which fires XML Schema validation.
@@ -57,16 +59,29 @@ public class FeatureValidationUtil {
dFactory.setNamespaceAware(true);
Document doc = dFactory.newDocumentBuilder().parse(stream);
- if (doc.getDocumentElement().getNamespaceURI() == null) {
+ QName name = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName());
+ if (FeaturesNamespaces.FEATURES_0_0_0.equals(name)) {
return;
+ } else if (FeaturesNamespaces.FEATURES_1_0_0.equals(name)) {
+ validate(doc, "/org/apache/karaf/features/karaf-features-1.0.0.xsd");
+ } else if (FeaturesNamespaces.FEATURES_1_1_0.equals(name)) {
+ validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd");
+ } else if (FeaturesNamespaces.FEATURES_1_2_0.equals(name)) {
+ validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd");
}
+ else {
+ throw new IllegalArgumentException("Unrecognized root element: " + name);
+ }
+ }
+
+ private static void validate(Document doc, String schemaLocation) throws SAXException {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
/** FIXME should move to 1.1.0 ? */
// root element has namespace - we can use schema validation
Schema schema = factory.newSchema(new StreamSource(FeatureValidationUtil.class
- .getResourceAsStream("/org/apache/karaf/features/karaf-features-1.0.0.xsd")));
+ .getResourceAsStream(schemaLocation)));
// create schema by reading it from an XSD file:
Validator validator = schema.newValidator();
@@ -74,7 +89,7 @@ public class FeatureValidationUtil {
try {
validator.validate(new DOMSource(doc));
} catch (Exception e) {
- throw new IllegalArgumentException("Unable to validate " + uri, e);
+ throw new IllegalArgumentException("Unable to validate " + doc.getDocumentURI(), e);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/d380c4d0/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
index 7b1cf98..248d074 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
@@ -47,6 +47,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
@@ -58,6 +59,7 @@ import org.apache.felix.utils.manifest.Parser;
import org.apache.felix.utils.version.VersionRange;
import org.apache.felix.utils.version.VersionTable;
import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
import org.apache.karaf.features.ConfigFileInfo;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeatureEvent;
@@ -76,9 +78,10 @@ import org.osgi.framework.FrameworkListener;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
@@ -104,11 +107,9 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
private BundleContext bundleContext;
private ConfigurationAdmin configAdmin;
- private PackageAdmin packageAdmin;
- private StartLevel startLevel;
private boolean respectStartLvlDuringFeatureStartup;
private long resolverTimeout = 5000;
- private Set<URI> uris;
+ private Set<URI> uris = new HashSet<URI>();
private Map<URI, Repository> repositories = new ConcurrentHashMap<URI, Repository>();
private Map<String, Map<String, Feature>> features;
private Map<Feature, Set<Long>> installed = new HashMap<Feature, Set<Long>>();
@@ -140,26 +141,10 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
this.configAdmin = configAdmin;
}
- public PackageAdmin getPackageAdmin() {
- return packageAdmin;
- }
-
- public void setPackageAdmin(PackageAdmin packageAdmin) {
- this.packageAdmin = packageAdmin;
- }
-
- public StartLevel getStartLevel() {
- return startLevel;
- }
-
public void setRespectStartLvlDuringFeatureStartup(boolean respectStartLvlDuringFeatureStartup) {
this.respectStartLvlDuringFeatureStartup = respectStartLvlDuringFeatureStartup;
}
- public void setStartLevel(StartLevel startLevel) {
- this.startLevel = startLevel;
- }
-
public long getResolverTimeout() {
return resolverTimeout;
}
@@ -192,7 +177,6 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
public void setUrls(String uris) throws URISyntaxException {
String[] s = uris.split(",");
- this.uris = new HashSet<URI>();
for (String value : s) {
value = value.trim();
if (!value.isEmpty()) {
@@ -261,6 +245,7 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
RepositoryImpl repo = null;
repo = new RepositoryImpl(uri);
repositories.put(uri, repo);
+ uris.add(uri);
repo.load();
if (repo.getName() == null) {
LOGGER.warn("Feature repository doesn't have a name. The name will be mandatory in the next Karaf version.");
@@ -419,6 +404,15 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
InstallationState s = new InstallationState();
try {
doInstallFeature(s, f, verbose);
+ doInstallFeatureConditionals(s, f, verbose);
+ //Check if current feature satisfies the conditionals of existing features
+ for (Feature installedFeature : listInstalledFeatures()) {
+ doInstallFeatureConditionals(s, installedFeature, verbose);
+ }
+ for (Feature installedFeature : state.features.keySet()) {
+ doInstallFeatureConditionals(s, installedFeature, verbose);
+ }
+
state.bundleInfos.putAll(s.bundleInfos);
state.bundles.addAll(s.bundles);
state.features.putAll(s.features);
@@ -457,7 +451,7 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
}
if (refresh) {
LOGGER.debug("Refreshing bundles: {}", sb.toString());
- refreshPackages(bundlesToRefresh.toArray(new Bundle[bundlesToRefresh.size()]));
+ refreshPackages(bundlesToRefresh);
}
}
}
@@ -483,7 +477,7 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
// do not start bundles that are persistently stopped
if (state.installed.contains(b)
|| (b.getState() != Bundle.STARTING && b.getState() != Bundle.ACTIVE
- && getStartLevel().isBundlePersistentlyStarted(b))) {
+ && isBundlePersistentlyStarted(b))) {
// do no start bundles when user request it
Long bundleId = b.getBundleId();
BundleInfo bundleInfo = state.bundleInfos.get(bundleId);
@@ -553,7 +547,7 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
protected static class InstallationState {
final Set<Bundle> installed = new HashSet<Bundle>();
- final List<Bundle> bundles = new ArrayList<Bundle>();
+ final Set<Bundle> bundles = new TreeSet<Bundle>();
final Map<Long, BundleInfo> bundleInfos = new HashMap<Long, BundleInfo>();
final Map<Feature, Set<Long>> features = new HashMap<Feature, Set<Long>>();
}
@@ -637,6 +631,15 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
state.features.put(feature, bundles);
}
+ private void doInstallFeatureConditionals(InstallationState state, Feature feature, boolean verbose) throws Exception {
+ for (Conditional conditional : feature.getConditional()) {
+ if (dependenciesSatisfied(conditional.getCondition(), state)) {
+ doInstallFeature(state, conditional.asFeature(feature.getName(), feature.getVersion()), verbose);
+ }
+ }
+
+ }
+
private String createConfigurationKey(String pid, String factoryPid) {
return factoryPid == null ? pid : pid + "-" + factoryPid;
}
@@ -896,10 +899,14 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
private void startBundleIfNeeded(Bundle bundle, int startLevel) {
if (startLevel > 0) {
- getStartLevel().setBundleStartLevel(bundle, startLevel);
+ bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
}
}
+ private boolean isBundlePersistentlyStarted(Bundle bundle) {
+ return bundle.adapt(BundleStartLevel.class).isPersistentlyStarted();
+ }
+
public void installConfigurationFile(String fileLocation, String finalname, boolean override, boolean verbose) throws IOException {
LOGGER.debug("Checking configuration file " + fileLocation);
if (verbose) {
@@ -1007,6 +1014,12 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
// and remove all those who will still be in use.
// This gives this list of bundles to uninstall.
Set<Long> bundles = installed.remove(feature);
+
+ //Also remove bundles installed as conditionals
+ for (Conditional conditional : feature.getConditional()) {
+ bundles.addAll(installed.remove(conditional.asFeature(feature.getName(),feature.getVersion())));
+ }
+
for (Set<Long> b : installed.values()) {
bundles.removeAll(b);
}
@@ -1249,7 +1262,6 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
public void stop() throws Exception {
bundleContext.removeFrameworkListener(this);
- uris = new HashSet<URI>(repositories.keySet());
while (!repositories.isEmpty()) {
internalRemoveRepository(repositories.keySet().iterator().next());
}
@@ -1263,13 +1275,19 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
}
}
- protected void refreshPackages(Bundle[] bundles) throws InterruptedException {
- if (getPackageAdmin() != null) {
- synchronized (refreshLock) {
- getPackageAdmin().refreshPackages(bundles);
- refreshLock.wait(refreshTimeout);
+ protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ FrameworkWiring fw = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
+ fw.refreshBundles(bundles, new FrameworkListener() {
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.ERROR) {
+ LOGGER.error("Framework error", event.getThrowable());
+ }
+ latch.countDown();
}
- }
+ });
+ latch.await();
}
protected String[] parsePid(String pid) {
@@ -1529,4 +1547,23 @@ public class FeaturesServiceImpl implements FeaturesService, FrameworkListener {
}
return buffer.toString();
}
+
+ /**
+ * Estimates if the {@link List} of dependencies is satisfied.
+ * The method will look into {@link Feature}s that are already installed or now being installed (if {@link InstallationState} is provided (not null)).
+ * @param dependencies
+ * @param state
+ * @return
+ */
+ private boolean dependenciesSatisfied(List<Feature> dependencies, InstallationState state) throws Exception {
+ boolean satisfied = true;
+ for (Feature dep : dependencies) {
+ Feature f = getFeature(dep.getName(), dep.getVersion());
+ if (f != null && !isInstalled(f) && (state != null && !state.features.keySet().contains(f))) {
+ satisfied = false;
+ }
+ }
+ return satisfied;
+ }
+
}