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 2015/03/04 21:25:41 UTC

karaf git commit: [KARAF-3574] Improve tooling support for karaf libraries

Repository: karaf
Updated Branches:
  refs/heads/master 08dc76762 -> ffd2df4f9


[KARAF-3574] Improve tooling support for karaf libraries

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ffd2df4f
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ffd2df4f
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ffd2df4f

Branch: refs/heads/master
Commit: ffd2df4f912e685bdf4188d61d53c1caf02a3310
Parents: 08dc767
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Mar 4 21:25:24 2015 +0100
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Wed Mar 4 21:25:24 2015 +0100

----------------------------------------------------------------------
 assemblies/apache-karaf/pom.xml                 |  13 ++
 assemblies/features/base/pom.xml                |  25 ----
 .../resources/etc/config.properties             |  43 +------
 assemblies/features/framework/pom.xml           |  35 -----
 .../framework/src/main/feature/feature.xml      |   4 +-
 .../standard/src/main/feature/feature.xml       |  17 +++
 .../java/org/apache/karaf/features/Feature.java |   1 +
 .../java/org/apache/karaf/features/Library.java |  34 +++++
 .../karaf/features/internal/model/Feature.java  |   9 ++
 .../karaf/features/internal/model/Library.java  |  71 +++++++++++
 .../features/internal/region/Subsystem.java     |  22 ++++
 .../features/internal/service/Deployer.java     |   8 +-
 .../service/FeatureConfigInstaller.java         |   1 +
 .../internal/service/FeaturesServiceImpl.java   |   3 +-
 .../karaf/features/karaf-features-1.3.0.xsd     |  25 ++++
 .../features/internal/service/DeployerTest.java |  10 +-
 .../service/FeaturesValidationTest.java         |   8 ++
 .../karaf/features/internal/service/f07.xml     |   1 +
 .../java/org/apache/karaf/kar/internal/Kar.java |   4 +-
 profile/pom.xml                                 |   1 +
 .../java/org/apache/karaf/profile/Profile.java  |   3 -
 .../assembly/AssemblyDeployCallback.java        |  26 +++-
 .../apache/karaf/profile/assembly/Builder.java  | 127 +++++++++++++++++--
 .../apache/karaf/profile/impl/ProfileImpl.java  |  18 ---
 .../karaf/tooling/features/InstallKarsMojo.java |   6 +
 .../karaf/tooling/features/MavenUtil.java       |  38 ------
 .../features/VerifyFeatureResolutionMojo.java   |   2 +-
 .../org/apache/karaf/util/maven/Parser.java     |  37 ++++++
 .../webconsole/features/ExtendedFeature.java    |   6 +
 29 files changed, 406 insertions(+), 192 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/apache-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/pom.xml b/assemblies/apache-karaf/pom.xml
index 3a28875..3e3f109 100644
--- a/assemblies/apache-karaf/pom.xml
+++ b/assemblies/apache-karaf/pom.xml
@@ -180,6 +180,19 @@
                         <feature>service</feature>
                         <feature>system</feature>
                     </bootFeatures>
+                    <libraries>
+                        <library>xerces-${xerces.version}.jar;url:="wrap:mvn:xerces/xercesImpl/${xerces.version}$Export-Package=org.apache.*;version=${xerces.version}";type:=endorsed;export:=true;delegate:=true</library>
+
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxp-api-1.4/${servicemix.specs.version};type:=endorsed;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxb-api-2.2/${servicemix.specs.version};type:=endorsed;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/${servicemix.specs.version};type:=endorsed;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.saaj-api-1.3/${servicemix.specs.version};type:=endorsed;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.activation-api-1.1/${servicemix.specs.version};type:=endorsed;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.2/${servicemix.specs.version};type:=endorsed;export:=true</library>
+
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.activator/${servicemix.specs.version};type:=default;export:=true</library>
+                        <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.locator/${servicemix.specs.version};type:=default;export:=true</library>
+                    </libraries>
                 </configuration>
             </plugin>
         </plugins>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/features/base/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/base/pom.xml b/assemblies/features/base/pom.xml
index 6df9795..120932f 100644
--- a/assemblies/features/base/pom.xml
+++ b/assemblies/features/base/pom.xml
@@ -130,21 +130,6 @@
                                     <outputDirectory>target/classes/resources/lib/boot</outputDirectory>
                                 </artifactItem>
                                 <artifactItem>
-                                    <groupId>org.apache.karaf.diagnostic</groupId>
-                                    <artifactId>org.apache.karaf.diagnostic.boot</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/boot</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.karaf.jaas</groupId>
-                                    <artifactId>org.apache.karaf.jaas.boot</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/boot</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.karaf.management</groupId>
-                                    <artifactId>org.apache.karaf.management.boot</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/boot</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
                                     <groupId>org.apache.karaf</groupId>
                                     <artifactId>org.apache.karaf.client</artifactId>
                                     <outputDirectory>target/classes/resources/system/org/apache/karaf/org.apache.karaf.client/${project.version}</outputDirectory>
@@ -155,16 +140,6 @@
                                     <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
                                 </artifactItem>
                                 <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.activator</artifactId>
-                                    <outputDirectory>target/classes/resources/lib</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.locator</artifactId>
-                                    <outputDirectory>target/classes/resources/lib</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
                                     <groupId>org.apache.felix</groupId>
                                     <artifactId>org.apache.felix.framework</artifactId>
                                     <outputDirectory>target/classes/resources/system/org/apache/felix/org.apache.felix.framework/${felix.framework.version}</outputDirectory>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/features/base/src/main/filtered-resources/resources/etc/config.properties
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/filtered-resources/resources/etc/config.properties b/assemblies/features/base/src/main/filtered-resources/resources/etc/config.properties
index 33425da..2eaf24b 100644
--- a/assemblies/features/base/src/main/filtered-resources/resources/etc/config.properties
+++ b/assemblies/features/base/src/main/filtered-resources/resources/etc/config.properties
@@ -77,10 +77,6 @@ org.osgi.framework.system.packages= \
  org.osgi.service.startlevel;version="1.1";uses:="org.osgi.framework",\
  org.osgi.service.url;version="1.0",\
  org.osgi.util.tracker;version="1.5.1";uses:="org.osgi.framework",\
- org.apache.karaf.jaas.boot;version="${karaf.osgi.version}", \
- org.apache.karaf.jaas.boot.principal;version="${karaf.osgi.version}", \
- org.apache.karaf.management.boot;version="${karaf.osgi.version}", \
- org.apache.karaf.diagnostic.core;version="${karaf.osgi.version}", \
  org.apache.karaf.version;version="${karaf.osgi.version}", \
  ${jre-${java.specification.version}}
 
@@ -89,43 +85,6 @@ org.osgi.framework.system.packages= \
 #
 org.osgi.framework.system.packages.extra= \
  org.apache.karaf.branding, \
- org.apache.html.dom; version="2.11.0", \
- org.apache.wml.dom; version="2.11.0", \
- org.apache.wml; version="2.11.0", \
- org.apache.xerces.parsers; version="2.11.0", \
- org.apache.xerces.impl.dtd.models; version="2.11.0", \
- org.apache.xerces.xni.parser; version="2.11.0", \
- org.apache.xerces.impl.dv.xs; version="2.11.0", \
- org.apache.xerces.impl.xs.traversers; version="2.11.0", \
- org.apache.xerces.util; version="2.11.0", \
- org.apache.xerces.impl.dtd; version="2.11.0", \
- org.apache.xerces.jaxp.validation; version="2.11.0", \
- org.apache.xerces.dom3.as; version="2.11.0", \
- org.apache.xerces.impl.dv; version="2.11.0", \
- org.apache.xerces.jaxp; version="2.11.0", \
- org.apache.xerces.jaxp.datatype; version="2.11.0", \
- org.apache.xerces.impl.xpath.regex; version="2.11.0", \
- org.apache.xerces.xni; version="2.11.0", \
- org.apache.xerces.impl.msg; version="2.11.0", \
- org.apache.xerces.impl.dv.util; version="2.11.0", \
- org.apache.xerces.impl.xs.util; version="2.11.0", \
- org.apache.xerces.dom; version="2.11.0", \
- org.apache.xerces.dom.events; version="2.11.0", \
- org.apache.xerces.impl.xs.opti; version="2.11.0", \
- org.apache.xerces.impl; version="2.11.0", \
- org.apache.xerces.xs; version="2.11.0", \
- org.apache.xerces.impl.io; version="2.11.0", \
- org.apache.xerces.xpointer; version="2.11.0", \
- org.apache.xerces.impl.dv.dtd; version="2.11.0", \
- org.apache.xerces.xinclude; version="2.11.0", \
- org.apache.xerces.impl.xpath; version="2.11.0", \
- org.apache.xerces.xs.datatypes; version="2.11.0", \
- org.apache.xerces.impl.xs.identity; version="2.11.0", \
- org.apache.xerces.impl.xs.models; version="2.11.0", \
- org.apache.xerces.xni.grammars; version="2.11.0", \
- org.apache.xerces.impl.xs; version="2.11.0", \
- org.apache.xerces.impl.validation; version="2.11.0", \
- org.apache.xml.serialize; version="2.11.0", \
  sun.misc
 
 org.osgi.framework.system.capabilities= \
@@ -152,7 +111,7 @@ eecap-1.2= osgi.ee; osgi.ee="OSGi/Minimum"; version:List<Version>="1.0,1.1", \
 #
 # javax.transaction is needed to avoid class loader constraint violation when using javax.sql
 #
-org.osgi.framework.bootdelegation=org.apache.karaf.jaas.boot,org.apache.karaf.jaas.boot.principal,org.apache.karaf.management.boot,sun.*,com.sun.*,javax.transaction,javax.transaction.*,javax.xml.crypto,javax.xml.crypto.*,org.apache.xerces.jaxp.datatype,org.apache.xerces.stax,org.apache.xerces.parsers,org.apache.xerces.jaxp,org.apache.xerces.jaxp.validation,org.apache.xerces.dom
+org.osgi.framework.bootdelegation=sun.*,com.sun.*,javax.transaction,javax.transaction.*,javax.xml.crypto,javax.xml.crypto.*
 
 # jVisualVM support
 # in order to use Karaf with jvisualvm, the org.osgi.framework.bootdelegation property has to contain the org.netbeans.lib.profiler.server package

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/features/framework/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/pom.xml b/assemblies/features/framework/pom.xml
index a85f726..7de8e8e 100644
--- a/assemblies/features/framework/pom.xml
+++ b/assemblies/features/framework/pom.xml
@@ -236,41 +236,6 @@
                         <configuration>
                             <artifactItems>
                                 <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.jaxp-api-1.4</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.jaxb-api-2.2</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.jaxws-api-2.2</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.saaj-api-1.3</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.activation-api-1.1</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.apache.servicemix.specs</groupId>
-                                    <artifactId>org.apache.servicemix.specs.stax-api-1.2</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>xerces</groupId>
-                                    <artifactId>xercesImpl</artifactId>
-                                    <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory>
-                                </artifactItem>
-                                <artifactItem>
                                     <groupId>${equinox.groupId}</groupId>
                                     <artifactId>${equinox.artifactId}</artifactId>
                                     <outputDirectory>target/classes/resources/system/${equinox.path}/${equinox.artifactId}/${equinox.version}</outputDirectory>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/features/framework/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/src/main/feature/feature.xml b/assemblies/features/framework/src/main/feature/feature.xml
index 127dca2..16c44c7 100644
--- a/assemblies/features/framework/src/main/feature/feature.xml
+++ b/assemblies/features/framework/src/main/feature/feature.xml
@@ -16,12 +16,12 @@
       See the License for the specific language governing permissions and
       limitations under the License.
 -->
-<features name="framework-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.1 http://karaf.apache.org/xmlns/features/v1.2.1">
+<features name="framework-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.3.0 http://karaf.apache.org/xmlns/features/v1.3.0">
 
     <!-- This file is not used in the assembly., This file is used by the karaf-maven-plugin to generate a "final" feature.xml
               including the correct start-level for the generation of the startup.propertie file -->
 
-    <feature version="${project.version}" description="Karaf core feature" name="framework">
+    <feature version="${project.version}" description="Karaf core feature" name="framework" hidden="true">
         <!-- mvn: and wrap: url handlers -->
         <bundle start="true" start-level="5">mvn:org.ops4j.pax.url/pax-url-aether/${pax.url.version}</bundle>
         <!-- logging -->

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 56020cf..01fdb3f 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -25,6 +25,7 @@
     </feature>
 
     <feature version="${project.version}" description="Services Security for Karaf" name="service-security">
+        <feature>jaas-boot</feature>
         <feature>aries-proxy</feature>
         <bundle start="true" start-level="10">mvn:org.apache.karaf.service/org.apache.karaf.service.guard/${project.version}</bundle>
     </feature>
@@ -83,7 +84,14 @@
         </conditional>
     </feature>
 
+    <feature name="jaas-boot" hidden="true">
+        <library export="true" delegate="true" type="boot">
+            mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.boot/${project.version}
+        </library>
+    </feature>
+
     <feature name="shell" description="Karaf Shell" version="${project.version}">
+        <feature>jaas-boot</feature>
         <config name="org.apache.karaf.command.acl.shell">
             #
             # This configuration file defines the ACLs for commands in the shell subshell
@@ -141,6 +149,7 @@
     </feature>
 
     <feature name="bundle" description="Provide Bundle support" version="${project.version}">
+        <feature>jaas-boot</feature>
         <bundle start-level="30" start="true">mvn:org.apache.karaf.bundle/org.apache.karaf.bundle.core/${project.version}</bundle>
         <conditional>
             <condition>management</condition>
@@ -272,6 +281,9 @@
 
     <feature name="diagnostic" description="Provide Diagnostic support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.core/${project.version}</bundle>
+        <library export="true" type="boot">
+            mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.boot/${project.version}
+        </library>
     </feature>
 
     <feature name="instance" description="Provide Instance support" version="${project.version}">
@@ -279,6 +291,7 @@
     </feature>
 
     <feature name="jaas" description="Provide JAAS support" version="${project.version}">
+        <feature>jaas-boot</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>
@@ -365,6 +378,7 @@
     </feature>
 
     <feature name="webconsole" description="Base support of the Karaf WebConsole" version="${project.version}">
+        <feature>jaas-boot</feature>
         <config name="org.apache.karaf.webconsole">
             realm=karaf
         </config>
@@ -478,6 +492,9 @@
             <bundle start-level="30">mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint.api/${aries.jmx.blueprint.api.version}</bundle>
             <bundle start-level="30">mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint.core/${aries.jmx.blueprint.core.version}</bundle>
         </conditional>
+        <library export="true" delegate="true" type="boot">
+            mvn:org.apache.karaf.management/org.apache.karaf.management.boot/${project.version}
+        </library>
     </feature>
 
     <feature name="scheduler" description="Provide a scheduler service in Karaf to fire events" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/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 1d563d5..523c9ff 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
@@ -65,4 +65,5 @@ public interface Feature {
 
     Scoping getScoping();
 
+    List<? extends Library> getLibraries();
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/Library.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Library.java b/features/core/src/main/java/org/apache/karaf/features/Library.java
new file mode 100644
index 0000000..7ed2147
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Library.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+public interface Library {
+
+    String TYPE_ENDORSED = "endorsed";
+    String TYPE_EXTENSION = "extension";
+    String TYPE_BOOT = "boot";
+    String TYPE_DEFAULT = "default";
+
+    String getLocation();
+
+    String getType();
+
+    boolean isExport();
+
+    boolean isDelegate();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
index 3c09ddc..64ad376 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
@@ -73,6 +73,7 @@ import org.apache.felix.utils.version.VersionCleaner;
         "conditional",
         "capability",
         "requirement",
+        "library",
         "scoping"
         })
 public class Feature extends Content implements org.apache.karaf.features.Feature {
@@ -100,6 +101,7 @@ public class Feature extends Content implements org.apache.karaf.features.Featur
     protected List<Capability> capability;
     protected List<Requirement> requirement;
     protected Scoping scoping;
+    protected List<Library> library;
 
     public Feature() {
     }
@@ -370,4 +372,11 @@ public class Feature extends Content implements org.apache.karaf.features.Featur
         }
     }
 
+    public List<Library> getLibraries() {
+        if (library == null) {
+            library = new ArrayList<>();
+        }
+        return this.library;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/model/Library.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Library.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Library.java
new file mode 100644
index 0000000..5264e09
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Library.java
@@ -0,0 +1,71 @@
+/*
+ * 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.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "library", propOrder = { "location" })
+public class Library implements org.apache.karaf.features.Library {
+
+    @XmlValue
+    private String location;
+    @XmlAttribute
+    private String type;
+    @XmlAttribute
+    private boolean export;
+    @XmlAttribute
+    private boolean delegate;
+
+    @Override
+    public String getLocation() {
+        return location != null ? location.trim() : null;
+    }
+
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public boolean isExport() {
+        return export;
+    }
+
+    public void setExport(boolean export) {
+        this.export = export;
+    }
+
+    public boolean isDelegate() {
+        return delegate;
+    }
+
+    public void setDelegate(boolean delegate) {
+        this.delegate = delegate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
index 575bac7..06d04ac 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
@@ -41,6 +41,7 @@ import org.apache.karaf.features.BundleInfo;
 import org.apache.karaf.features.Conditional;
 import org.apache.karaf.features.Dependency;
 import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Library;
 import org.apache.karaf.features.ScopeFilter;
 import org.apache.karaf.features.internal.download.DownloadCallback;
 import org.apache.karaf.features.internal.download.DownloadManager;
@@ -389,6 +390,20 @@ public class Subsystem extends ResourceImpl {
                 }
             });
         }
+        if (feature != null) {
+            for (Library library : feature.getLibraries()) {
+                if (library.isExport()) {
+                    final String loc = library.getLocation();
+                    downloader.download(loc, new DownloadCallback() {
+                        @Override
+                        public void downloaded(StreamProvider provider) throws Exception {
+                            ResourceImpl res = createResource(loc, getMetadata(provider));
+                            bundles.put(loc, res);
+                        }
+                    });
+                }
+            }
+        }
         downloader.await();
         Overrides.override(bundles, overrides);
         if (feature != null) {
@@ -420,6 +435,13 @@ public class Subsystem extends ResourceImpl {
                     addIdentityRequirement(res, resConds.get(cond), true);
                 }
             }
+            for (Library library : feature.getLibraries()) {
+                if (library.isExport()) {
+                    final String loc = library.getLocation();
+                    ResourceImpl res = bundles.get(loc);
+                    addDependency(res, false, false, 0);
+                }
+            }
         }
         for (Clause bundle : Parser.parseClauses(this.bundles.toArray(new String[this.bundles.size()]))) {
             final String loc = bundle.getName();

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java
index 9a0d6a3..ab91533 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java
@@ -109,7 +109,7 @@ public class Deployer {
 
         void saveState(State state);
         void persistResolveRequest(DeploymentRequest request) throws IOException;
-        void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException;
+        void installFeature(Feature feature) throws IOException, InvalidSyntaxException;
         void callListeners(FeatureEvent featureEvent);
 
         Bundle installBundle(String region, String uri, InputStream is) throws BundleException;
@@ -708,18 +708,18 @@ public class Deployer {
         callback.saveState(newState);
 
         //
-        // Install configurations
+        // Install configurations and libraries
         //
         if (!newFeatures.isEmpty()) {
             Set<String> featureIds = flatten(newFeatures);
             for (Feature feature : dstate.features.values()) {
                 if (featureIds.contains(feature.getId())) {
-                    callback.installFeatureConfigs(feature);
+                    callback.installFeature(feature);
                 }
                 for (Conditional cond : feature.getConditional()) {
                     Feature condFeature = cond.asFeature(feature.getName(), feature.getVersion());
                     if (featureIds.contains(condFeature.getId())) {
-                        callback.installFeatureConfigs(condFeature);
+                        callback.installFeature(condFeature);
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
index 1940868..b1f284f 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -157,6 +157,7 @@ public class FeatureConfigInstaller {
             LOGGER.info("Creating configuration file {}", finalname);
         }
 
+        // TODO: use download manager to download the configuration
         try (
                 InputStream is = new BufferedInputStream(new URL(fileLocation).openStream())
         ) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index d98049f..3fd8a39 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -1112,10 +1112,11 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
     }
 
     @Override
-    public void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
+    public void installFeature(Feature feature) throws IOException, InvalidSyntaxException {
         if (configInstaller != null) {
             configInstaller.installFeatureConfigs(feature);
         }
+        // TODO: install libraries
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
index f5a4120..4fc5141 100644
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
@@ -78,6 +78,7 @@ Definition of the Feature.
                 <xs:element name="conditional" type="tns:conditional" />
                 <xs:element name="requirement" type="tns:requirement" />
                 <xs:element name="capability" type="tns:capability" />
+                <xs:element name="library" type="tns:library" />
             </xs:choice>
             <xs:element name="scoping" minOccurs="0" maxOccurs="1" type="tns:scoping" />
         </xs:sequence>
@@ -247,6 +248,30 @@ Additional capability of this feature.
         </xs:simpleContent>
     </xs:complexType>
 
+    <xs:complexType name="library">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional capability of this feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="type" type="tns:libraryType" default="default"/>
+                <xs:attribute name="export" type="xs:boolean" default="false"/>
+                <xs:attribute name="delegate" type="xs:boolean" default="false"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="libraryType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="endorsed"/>
+            <xs:enumeration value="extension"/>
+            <xs:enumeration value="boot"/>
+        </xs:restriction>
+    </xs:simpleType>
+
     <xs:complexType name="scoping">
         <xs:annotation>
             <xs:documentation><![CDATA[

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
index 067f84f..1b451ae 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
@@ -73,7 +73,7 @@ public class DeployerTest {
         EasyMock.expectLastCall();
         callback.saveState(EasyMock.<State>anyObject());
         EasyMock.expectLastCall();
-        callback.installFeatureConfigs(f100);
+        callback.installFeature(f100);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
                                 EasyMock.<Map<Resource, List<Wire>>>anyObject(),
@@ -164,7 +164,7 @@ public class DeployerTest {
         EasyMock.expectLastCall();
         callback.saveState(EasyMock.<State>anyObject());
         EasyMock.expectLastCall();
-        callback.installFeatureConfigs(f101);
+        callback.installFeature(f101);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.eq(Collections.<Bundle>singleton(bundleA)),
                                 EasyMock.<Map<Resource, List<Wire>>>anyObject(),
@@ -232,7 +232,7 @@ public class DeployerTest {
         EasyMock.expectLastCall();
         callback.saveState(EasyMock.<State>anyObject());
         EasyMock.expectLastCall();
-        callback.installFeatureConfigs(f1);
+        callback.installFeature(f1);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
                                 EasyMock.<Map<Resource, List<Wire>>>anyObject(),
@@ -296,7 +296,7 @@ public class DeployerTest {
         EasyMock.expectLastCall();
         callback.saveState(EasyMock.<State>anyObject());
         EasyMock.expectLastCall();
-        callback.installFeatureConfigs(f1);
+        callback.installFeature(f1);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
                                 EasyMock.<Map<Resource, List<Wire>>>anyObject(),
@@ -348,7 +348,7 @@ public class DeployerTest {
         EasyMock.expectLastCall();
         callback.saveState(EasyMock.<State>anyObject());
         EasyMock.expectLastCall();
-        callback.installFeatureConfigs(f2);
+        callback.installFeature(f2);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
                                 EasyMock.<Map<Resource, List<Wire>>>anyObject(),

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
index e16f4a8..af3c2e1 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
@@ -18,11 +18,13 @@ package org.apache.karaf.features.internal.service;
 
 import java.net.URL;
 
+import org.apache.karaf.features.Library;
 import org.apache.karaf.features.internal.model.Features;
 import org.apache.karaf.features.internal.model.JaxbUtil;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -99,6 +101,12 @@ public class FeaturesValidationTest {
         assertNotNull(features);
         assertEquals("2.5.6.SEC02", features.getFeature().get(0).getVersion());
         assertTrue(features.getFeature().get(1).isHidden());
+        assertNotNull(features.getFeature().get(1).getLibraries());
+        assertEquals(1, features.getFeature().get(0).getLibraries().size());
+        assertEquals("my-library", features.getFeature().get(0).getLibraries().get(0).getLocation());
+        assertEquals(Library.TYPE_ENDORSED, features.getFeature().get(0).getLibraries().get(0).getType());
+        assertFalse(features.getFeature().get(0).getLibraries().get(0).isExport());
+        assertTrue(features.getFeature().get(0).getLibraries().get(0).isDelegate());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
index f32f938..62bb2ea 100644
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
@@ -31,6 +31,7 @@
         <capability>
             osgi.service;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
         </capability>
+        <library type="endorsed" delegate="true">my-library</library>
         <scoping>
             <export namespace="osgi.service">
                 (objectClass=org.apache.aries.proxy.ProxyManager)

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
index 027dc82..7fd2a10 100644
--- a/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
@@ -31,6 +31,7 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
 import org.apache.karaf.util.StreamUtils;
+import org.apache.karaf.util.maven.Parser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -117,7 +118,8 @@ public class Kar {
                     File destFile = new File(repoDir, path);
                     extract(zipIs, entry, destFile);
                     if (scanForRepos && featureDetector.isFeaturesRepository(destFile)) {
-                        featureRepos.add(destFile.toURI());
+                        String uri = Parser.pathToMaven(path);
+                        featureRepos.add(URI.create(uri));
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/profile/pom.xml
----------------------------------------------------------------------
diff --git a/profile/pom.xml b/profile/pom.xml
index c7927b0..8040432 100644
--- a/profile/pom.xml
+++ b/profile/pom.xml
@@ -184,6 +184,7 @@
                             org.apache.karaf.profile.impl.osgi,
                             org.apache.karaf.util.config,
                             org.apache.karaf.util.maven,
+                            org.apache.felix.utils.manifest,
                             org.apache.felix.utils.version,
                             org.apache.felix.utils.properties,
                         </Private-Package>

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/profile/src/main/java/org/apache/karaf/profile/Profile.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/Profile.java b/profile/src/main/java/org/apache/karaf/profile/Profile.java
index 6f4d9fd..aedd5d8 100644
--- a/profile/src/main/java/org/apache/karaf/profile/Profile.java
+++ b/profile/src/main/java/org/apache/karaf/profile/Profile.java
@@ -86,9 +86,6 @@ public interface Profile {
     List<String> getParentIds();
 
     List<String> getLibraries();
-    List<String> getEndorsedLibraries();
-    List<String> getExtensionLibraries();
-    List<String> getBootLibraries();
     List<String> getBundles();
     List<String> getFeatures();
     List<String> getRepositories();

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
index 826aa7e..22e4fcc 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
@@ -22,6 +22,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -32,8 +33,10 @@ import java.util.concurrent.atomic.AtomicLong;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 
+import org.apache.felix.utils.properties.Properties;
 import org.apache.karaf.features.FeatureEvent;
 import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.internal.model.Library;
 import org.apache.karaf.features.internal.download.DownloadCallback;
 import org.apache.karaf.features.internal.download.DownloadManager;
 import org.apache.karaf.features.internal.download.Downloader;
@@ -61,6 +64,7 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
     private static final Logger LOGGER = LoggerFactory.getLogger(Builder.class);
 
     private final DownloadManager manager;
+    private final Builder builder;
     private final Path homeDirectory;
     private final int defaultStartLevel;
     private final Path etcDirectory;
@@ -70,12 +74,13 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
 
     private final Map<String, Bundle> bundles = new HashMap<>();
 
-    public AssemblyDeployCallback(DownloadManager manager, Path homeDirectory, int defaultStartLevel, BundleRevision systemBundle, Collection<Features> repositories) throws Exception {
+    public AssemblyDeployCallback(DownloadManager manager, Builder builder, BundleRevision systemBundle, Collection<Features> repositories) throws Exception {
         this.manager = manager;
-        this.homeDirectory = homeDirectory;
+        this.builder = builder;
+        this.homeDirectory = builder.homeDirectory;
         this.etcDirectory = homeDirectory.resolve("etc");
         this.systemDirectory = homeDirectory.resolve("system");
-        this.defaultStartLevel = defaultStartLevel;
+        this.defaultStartLevel = builder.defaultStartLevel;
         dstate = new Deployer.DeploymentState();
         dstate.bundles = new HashMap<>();
         dstate.features = new HashMap<>();
@@ -122,7 +127,7 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
     }
 
     @Override
-    public void installFeatureConfigs(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
+    public void installFeature(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
         LOGGER.info("Installing feature config for " + feature.getId());
         for (Config config : ((Feature) feature).getConfig()) {
             Path configFile = etcDirectory.resolve(config.getName());
@@ -147,6 +152,19 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
                 }
             });
         }
+        List<String> libraries = new ArrayList<>();
+        for (Library library : ((Feature) feature).getLibraries()) {
+            String lib = library.getLocation() +
+                    ";type:=" + library.getType() +
+                    ";export:=" + library.isExport() +
+                    ";delegate:=" + library.isDelegate();
+            libraries.add(lib);
+        }
+        if (!libraries.isEmpty()) {
+            Path configPropertiesPath = etcDirectory.resolve("config.properties");
+            Properties configProperties = new Properties(configPropertiesPath.toFile());
+            builder.downloadLibraries(downloader, configProperties, libraries);
+        }
         try {
             downloader.await();
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index e0f3ce3..3364dfb 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -53,9 +53,11 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+import org.apache.felix.utils.manifest.Clause;
 import org.apache.felix.utils.properties.InterpolationHelper;
 import org.apache.felix.utils.properties.Properties;
 import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Library;
 import org.apache.karaf.features.internal.download.DownloadCallback;
 import org.apache.karaf.features.internal.download.DownloadManager;
 import org.apache.karaf.features.internal.download.Downloader;
@@ -95,6 +97,10 @@ public class Builder {
     private static final String FEATURES_REPOSITORIES = "featuresRepositories";
     private static final String FEATURES_BOOT = "featuresBoot";
 
+    private static final String LIBRARY_CLAUSE_TYPE = "type";
+    private static final String LIBRARY_CLAUSE_EXPORT = "export";
+    private static final String LIBRARY_CLAUSE_DELEGATE = "delegate";
+
     public static enum Stage {
         Startup, Boot, Installed
     }
@@ -116,6 +122,7 @@ public class Builder {
     Map<String, RepositoryInfo> repositories = new LinkedHashMap<>();
     Map<String, Stage> features = new LinkedHashMap<>();
     Map<String, Stage> bundles = new LinkedHashMap<>();
+    List<String> libraries = new ArrayList<>();
     String javase = "1.7";
     String environment = null;
     boolean useReferenceUrls;
@@ -149,6 +156,11 @@ public class Builder {
         return this;
     }
 
+    public Builder libraries(String... libraries) {
+        Collections.addAll(this.libraries, libraries);
+        return this;
+    }
+
     public Builder kars(String... kars) {
         return kars(defaultStage, defaultAddAll, kars);
     }
@@ -419,11 +431,13 @@ public class Builder {
         // TODO: handle karaf 2.x and 3.x libraries
         LOGGER.info("Downloading libraries");
         downloader = manager.createDownloader();
-        downloadLibraries(downloader, overallEffective.getLibraries(), "lib");
-        downloadLibraries(downloader, overallEffective.getEndorsedLibraries(), "lib/endorsed");
-        downloadLibraries(downloader, overallEffective.getExtensionLibraries(), "lib/ext");
-        downloadLibraries(downloader, overallEffective.getBootLibraries(), "lib/boot");
+        downloadLibraries(downloader, configProperties, overallEffective.getLibraries());
+        downloadLibraries(downloader, configProperties, libraries);
         downloader.await();
+        // Reformat clauses
+        reformatClauses(configProperties, "org.osgi.framework.system.packages.extra");
+        reformatClauses(configProperties, "org.osgi.framework.bootdelegation");
+        configProperties.save();
 
         //
         // Write all configuration files
@@ -450,15 +464,81 @@ public class Builder {
         installStage(installedProfile, allBootFeatures);
     }
 
-    private void downloadLibraries(Downloader downloader, List<String> libraries, final String path) throws MalformedURLException {
-        for (String library : libraries) {
+    private void reformatClauses(Properties config, String key) {
+        String val = config.getProperty(key);
+        if (val != null && !val.isEmpty()) {
+            List<String> comments = config.getComments(key);
+            Clause[] clauses = org.apache.felix.utils.manifest.Parser.parseHeader(val);
+            Set<String> strings = new TreeSet<>();
+            for (Clause clause : clauses) {
+                strings.add(clause.toString());
+            }
+            List<String> lines = new ArrayList<>();
+            lines.add("");
+            int index = 0;
+            for (String string : strings) {
+                String s = "    " + string;
+                if (index++ < strings.size() - 1) {
+                    s += ", ";
+                }
+                lines.add(s);
+            }
+            config.put(key, comments, lines);
+        }
+    }
+
+    protected void downloadLibraries(Downloader downloader, final Properties config, Collection<String> libraries) throws MalformedURLException {
+        Clause[] clauses = org.apache.felix.utils.manifest.Parser.parseClauses(libraries.toArray(new String[libraries.size()]));
+        for (final Clause clause : clauses) {
+            final String filename;
+            final String library;
+            if (clause.getDirective("url") != null) {
+                filename = clause.getName();
+                library = clause.getDirective("url");
+            } else {
+                filename = null;
+                library = clause.getName();
+            }
+            final String type = clause.getDirective(LIBRARY_CLAUSE_TYPE) != null
+                    ? clause.getDirective(LIBRARY_CLAUSE_TYPE) : Library.TYPE_DEFAULT;
+            final String path;
+            switch (type) {
+            case Library.TYPE_ENDORSED:  path = "lib/endorsed"; break;
+            case Library.TYPE_EXTENSION: path = "lib/ext"; break;
+            case Library.TYPE_BOOT:      path = "lib/boot"; break;
+            default:                     path = "lib"; break;
+            }
             downloader.download(library, new DownloadCallback() {
                 @Override
                 public void downloaded(final StreamProvider provider) throws Exception {
                     synchronized (provider) {
                         Path input = provider.getFile().toPath();
-                        Path output = homeDirectory.resolve(path).resolve(input.getFileName().toString());
-                        Files.copy(input, output);
+                        String name = filename != null ? filename : input.getFileName().toString();
+                        Path output = homeDirectory.resolve(path).resolve(name);
+                        Files.copy(input, output, StandardCopyOption.REPLACE_EXISTING);
+                    }
+                    boolean export = Boolean.parseBoolean(clause.getDirective(LIBRARY_CLAUSE_EXPORT));
+                    boolean delegate = Boolean.parseBoolean(clause.getDirective(LIBRARY_CLAUSE_DELEGATE));
+                    if (export || delegate) {
+                        Map<String, String> headers = getHeaders(provider);
+                        String packages = headers.get(Constants.EXPORT_PACKAGE);
+                        if (packages != null) {
+                            Clause[] clauses = org.apache.felix.utils.manifest.Parser.parseHeader(packages);
+                            if (export) {
+                                String val = config.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+                                for (Clause clause : clauses) {
+                                    val += "," + clause.toString();
+                                }
+                                config.setProperty(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, val);
+                            }
+                            if (delegate) {
+                                String val = config.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
+                                for (Clause clause : clauses) {
+                                    val += "," + clause.getName();
+                                }
+                                config.setProperty(Constants.FRAMEWORK_BOOTDELEGATION, val);
+                            }
+                        }
                     }
                 }
             });
@@ -466,13 +546,13 @@ public class Builder {
     }
 
     private void installStage(Profile installedProfile, Set<Feature> allBootFeatures) throws Exception {
-        Downloader downloader;//
+        //
         // Handle installed profiles
         //
         Profile installedOverlay = Profiles.getOverlay(installedProfile, allProfiles, environment);
         Profile installedEffective = Profiles.getEffective(installedOverlay, false);
 
-        downloader = manager.createDownloader();
+        Downloader downloader = manager.createDownloader();
 
         // Load startup repositories
         Map<String, Features> installedRepositories = loadRepositories(manager, installedEffective.getRepositories(), true);
@@ -603,6 +683,24 @@ public class Builder {
                     installArtifact(downloader, configFile.getLocation().trim());
                 }
             }
+            // Install libraries
+            List<String> libraries = new ArrayList<>();
+            for (Library library : feature.getLibraries()) {
+                String lib = library.getLocation() +
+                        ";type:=" + library.getType() +
+                        ";export:=" + library.isExport() +
+                        ";delegate:=" + library.isDelegate();
+                libraries.add(lib);
+            }
+            Path configPropertiesPath = etcDirectory.resolve("config.properties");
+            Properties configProperties = new Properties(configPropertiesPath.toFile());
+            downloader = manager.createDownloader();
+            downloadLibraries(downloader, configProperties, libraries);
+            downloader.await();
+            // Reformat clauses
+            reformatClauses(configProperties, "org.osgi.framework.system.packages.extra");
+            reformatClauses(configProperties, "org.osgi.framework.bootdelegation");
+            configProperties.save();
         }
 
         // If there are bundles to install, we can't use the boot features only
@@ -674,7 +772,8 @@ public class Builder {
             Properties featuresProperties = new Properties(featuresCfgFile.toFile());
             featuresProperties.put(FEATURES_REPOSITORIES, repos);
             featuresProperties.put(FEATURES_BOOT, boot);
-            // TODO: reformat to multiline values
+            reformatClauses(featuresProperties, FEATURES_REPOSITORIES);
+            reformatClauses(featuresProperties, FEATURES_BOOT);
             featuresProperties.save();
         }
         downloader.await();
@@ -803,7 +902,9 @@ public class Builder {
     private List<String> getStagedRepositories(Stage stage, Map<String, RepositoryInfo> data) {
         List<String> staged = new ArrayList<>();
         for (String s : data.keySet()) {
-            if (data.get(s).stage == stage) {
+            if (data.get(s).stage == stage ||
+                    data.get(s).stage == Stage.Startup && stage == Stage.Boot) {
+                // For boot stage, we also want the startup repositories
                 staged.add(s);
             }
         }
@@ -859,7 +960,7 @@ public class Builder {
                     Collection<String> overrides,
                     Collection<String> optionals) throws Exception {
         BundleRevision systemBundle = getSystemBundle();
-        AssemblyDeployCallback callback = new AssemblyDeployCallback(manager, homeDirectory, defaultStartLevel, systemBundle, repositories);
+        AssemblyDeployCallback callback = new AssemblyDeployCallback(manager, this, systemBundle, repositories);
         Deployer deployer = new Deployer(manager, callback);
 
         // Install framework

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java
index 48b064e..f23c3c4 100644
--- a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java
+++ b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java
@@ -116,21 +116,6 @@ final class ProfileImpl implements Profile {
     }
 
     @Override
-    public List<String> getEndorsedLibraries() {
-        return getContainerConfigList(ConfigListType.ENDORSED);
-    }
-
-    @Override
-    public List<String> getExtensionLibraries() {
-        return getContainerConfigList(ConfigListType.EXTENSIONS);
-    }
-
-    @Override
-    public List<String> getBootLibraries() {
-        return getContainerConfigList(ConfigListType.BOOT);
-    }
-
-    @Override
     public List<String> getBundles() {
         return getContainerConfigList(ConfigListType.BUNDLES);
     }
@@ -247,9 +232,6 @@ final class ProfileImpl implements Profile {
     enum ConfigListType {
         BUNDLES("bundle"),
         FEATURES("feature"),
-        ENDORSED("endorsed"),
-        EXTENSIONS("extension"),
-        BOOT("boot"),
         LIBRARIES("library"),
         OPTIONALS("optional"),
         OVERRIDES("override"),

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
index c4b451d..559a155 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
@@ -125,6 +125,9 @@ public class InstallKarsMojo extends MojoSupport {
     @Parameter
     protected List<String> featureRepositories;
 
+    @Parameter
+    protected List<String> libraries;
+
     /**
      * Use reference: style urls in startup.properties
      */
@@ -241,6 +244,9 @@ public class InstallKarsMojo extends MojoSupport {
         if (profilesUri != null) {
             builder.profilesUris(profilesUri);
         }
+        if (libraries != null) {
+            builder.libraries(libraries.toArray(new String[libraries.size()]));
+        }
         // Startup
         builder.defaultStage(Builder.Stage.Startup)
                .kars(toArray(startupKars))

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
index dd1e75d..52bfcec 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/MavenUtil.java
@@ -43,44 +43,6 @@ public class MavenUtil {
     private static final Pattern aetherPattern = Pattern.compile("([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)");
     private static final Pattern mvnPattern = Pattern.compile("(?:(?:wrap:)|(?:blueprint:))?mvn:([^/ ]+)/([^/ ]+)/([^/\\$ ]*)(/([^/\\$ ]+)(/([^/\\$ ]+))?)?(/\\$.+)?");
 
-
-    static String pathToMvn(String location) {
-        String[] p = location.split("/");
-        if (p.length >= 4 && p[p.length-1].startsWith(p[p.length-3] + "-" + p[p.length-2])) {
-            String artifactId = p[p.length-3];
-            String version = p[p.length-2];
-            String classifier;
-            String type;
-            String artifactIdVersion = artifactId + "-" + version;
-            StringBuilder sb = new StringBuilder();
-            if (p[p.length-1].charAt(artifactIdVersion.length()) == '-') {
-                classifier = p[p.length-1].substring(artifactIdVersion.length() + 1, p[p.length-1].lastIndexOf('.'));
-            } else {
-                classifier = null;
-            }
-            type = p[p.length-1].substring(p[p.length-1].lastIndexOf('.') + 1);
-            sb.append("mvn:");
-            for (int j = 0; j < p.length - 3; j++) {
-                if (j > 0) {
-                    sb.append('.');
-                }
-                sb.append(p[j]);
-            }
-            sb.append('/').append(artifactId).append('/').append(version);
-            if (!"jar".equals(type) || classifier != null) {
-                sb.append('/');
-                if (!"jar".equals(type)) {
-                    sb.append(type);
-                }
-                if (classifier != null) {
-                    sb.append('/').append(classifier);
-                }
-            }
-            return sb.toString();
-        }
-        return location;
-    }
-
     /**
      * Convert PAX URL mvn format to aether coordinate format.
      * N.B. we do not handle repository-url in mvn urls.

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java
index b3cb74a..9e23740 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java
@@ -675,7 +675,7 @@ public class VerifyFeatureResolutionMojo extends MojoSupport {
         }
 
         @Override
-        public void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
+        public void installFeature(Feature feature) throws IOException, InvalidSyntaxException {
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/util/src/main/java/org/apache/karaf/util/maven/Parser.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/maven/Parser.java b/util/src/main/java/org/apache/karaf/util/maven/Parser.java
index 8f6920f..f1e5704 100644
--- a/util/src/main/java/org/apache/karaf/util/maven/Parser.java
+++ b/util/src/main/java/org/apache/karaf/util/maven/Parser.java
@@ -162,6 +162,43 @@ public class Parser
         return new Parser(uri.substring("mvn:".length())).getArtifactPath();
     }
 
+    public static String pathToMaven(String location) {
+        String[] p = location.split("/");
+        if (p.length >= 4 && p[p.length-1].startsWith(p[p.length-3] + "-" + p[p.length-2])) {
+            String artifactId = p[p.length-3];
+            String version = p[p.length-2];
+            String classifier;
+            String type;
+            String artifactIdVersion = artifactId + "-" + version;
+            StringBuilder sb = new StringBuilder();
+            if (p[p.length-1].charAt(artifactIdVersion.length()) == '-') {
+                classifier = p[p.length-1].substring(artifactIdVersion.length() + 1, p[p.length-1].lastIndexOf('.'));
+            } else {
+                classifier = null;
+            }
+            type = p[p.length-1].substring(p[p.length-1].lastIndexOf('.') + 1);
+            sb.append("mvn:");
+            for (int j = 0; j < p.length - 3; j++) {
+                if (j > 0) {
+                    sb.append('.');
+                }
+                sb.append(p[j]);
+            }
+            sb.append('/').append(artifactId).append('/').append(version);
+            if (!"jar".equals(type) || classifier != null) {
+                sb.append('/');
+                if (!"jar".equals(type)) {
+                    sb.append(type);
+                }
+                if (classifier != null) {
+                    sb.append('/').append(classifier);
+                }
+            }
+            return sb.toString();
+        }
+        return location;
+    }
+
     /**
      * Parses the artifact part of the url ( without the repository).
      *

http://git-wip-us.apache.org/repos/asf/karaf/blob/ffd2df4f/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
----------------------------------------------------------------------
diff --git a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
index 695a10d..57fe07f 100644
--- a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
+++ b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
@@ -26,6 +26,7 @@ import org.apache.karaf.features.ConfigFileInfo;
 import org.apache.karaf.features.ConfigInfo;
 import org.apache.karaf.features.Dependency;
 import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Library;
 import org.apache.karaf.features.Requirement;
 import org.apache.karaf.features.Scoping;
 
@@ -149,4 +150,9 @@ public class ExtendedFeature implements Feature {
     public Scoping getScoping() {
         return feature.getScoping();
     }
+
+    @Override
+    public List<? extends Library> getLibraries() {
+        return feature.getLibraries();
+    }
 }