karaf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject [2/2] git commit: [KARAF-1718] Add support for support for conditional bundle and feature definition inside features
Date Mon, 21 Jul 2014 16:32:23 GMT
[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 <gnodet@gmail.com>
Authored: Mon Jul 21 18:31:31 2014 +0200
Committer: Guillaume Nodet <gnodet@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;
+    }
+
 }


Mime
View raw message