Index: assembly/src/main/distribution/text/etc/org.ops4j.pax.url.mvn.cfg
===================================================================
--- assembly/src/main/distribution/text/etc/org.ops4j.pax.url.mvn.cfg (revision 998721)
+++ assembly/src/main/distribution/text/etc/org.ops4j.pax.url.mvn.cfg (working copy)
@@ -55,7 +55,8 @@
#
# The following property value will add the system folder as a repo.
#
-org.ops4j.pax.url.mvn.defaultRepositories=file:${karaf.home}/${karaf.default.repository}@snapshots
+org.ops4j.pax.url.mvn.defaultRepositories=file:${karaf.home}/${karaf.default.repository}@snapshots, \
+ file:${karaf.home}/local-repo@snapshots
#
# Comma separated list of repositories scanned when resolving an artifact.
Index: assembly/src/main/descriptors/windows-bin.xml
===================================================================
--- assembly/src/main/descriptors/windows-bin.xml (revision 998721)
+++ assembly/src/main/descriptors/windows-bin.xml (working copy)
@@ -199,6 +199,7 @@
org.apache.karaf.deployer:org.apache.karaf.deployer.spring
org.apache.karaf.deployer:org.apache.karaf.deployer.blueprint
org.apache.karaf.deployer:org.apache.karaf.deployer.features
+ org.apache.karaf.deployer:org.apache.karaf.deployer.kar
Index: assembly/src/main/descriptors/unix-bin.xml
===================================================================
--- assembly/src/main/descriptors/unix-bin.xml (revision 998721)
+++ assembly/src/main/descriptors/unix-bin.xml (working copy)
@@ -212,6 +212,7 @@
org.apache.karaf.deployer:org.apache.karaf.deployer.spring
org.apache.karaf.deployer:org.apache.karaf.deployer.blueprint
org.apache.karaf.deployer:org.apache.karaf.deployer.features
+ org.apache.karaf.deployer:org.apache.karaf.deployer.kar
Index: assembly/src/main/filtered-resources/etc/startup.properties
===================================================================
--- assembly/src/main/filtered-resources/etc/startup.properties (revision 998721)
+++ assembly/src/main/filtered-resources/etc/startup.properties (working copy)
@@ -62,3 +62,4 @@
org/apache/karaf/deployer/org.apache.karaf.deployer.spring/${project.version}/org.apache.karaf.deployer.spring-${project.version}.jar=30
org/apache/karaf/deployer/org.apache.karaf.deployer.blueprint/${project.version}/org.apache.karaf.deployer.blueprint-${project.version}.jar=30
org/apache/karaf/deployer/org.apache.karaf.deployer.features/${project.version}/org.apache.karaf.deployer.features-${project.version}.jar=30
+org/apache/karaf/deployer/org.apache.karaf.deployer.kar/${project.version}/org.apache.karaf.deployer.kar-${project.version}.jar=30
Index: assembly/src/main/filtered-resources/features.xml
===================================================================
--- assembly/src/main/filtered-resources/features.xml (revision 998721)
+++ assembly/src/main/filtered-resources/features.xml (working copy)
@@ -66,6 +66,9 @@
mvn:org.ops4j.pax.url/pax-url-war/${pax.url.version}
mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.war/${project.version}
+
+ mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}
+
http
Index: assembly/pom.xml
===================================================================
--- assembly/pom.xml (revision 998721)
+++ assembly/pom.xml (working copy)
@@ -74,6 +74,10 @@
org.apache.karaf.deployer
+ org.apache.karaf.deployer.kar
+
+
+ org.apache.karaf.deployer
org.apache.karaf.deployer.war
Index: deployer/pom.xml
===================================================================
--- deployer/pom.xml (revision 998721)
+++ deployer/pom.xml (working copy)
@@ -37,6 +37,7 @@
blueprint
features
war
+ kar
Index: deployer/kar/NOTICE
===================================================================
--- deployer/kar/NOTICE (revision 0)
+++ deployer/kar/NOTICE (revision 0)
@@ -0,0 +1,21 @@
+Apache Felix Karaf
+Copyright 2010 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+
+II. Used Software
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+
+III. License Summary
+- Apache License 2.0
Index: deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarDeploymentListenerTest.java
===================================================================
--- deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarDeploymentListenerTest.java (revision 0)
+++ deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarDeploymentListenerTest.java (revision 0)
@@ -0,0 +1,56 @@
+package org.apache.karaf.deployer.kar;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URI;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class KarDeploymentListenerTest {
+
+ private KarDeploymentListener karDeploymentListener;
+ private URI goodKarFile;
+ private URI zipFileWithKarafManifest;
+ private URI zipFileWithoutKarafManifest;
+ private URI badZipFile;
+
+ @Before
+ public void setUp() throws Exception {
+ karDeploymentListener = new KarDeploymentListener();
+ karDeploymentListener.init();
+
+ goodKarFile = getClass().getClassLoader().getResource("goodKarFile.kar").toURI();
+ zipFileWithKarafManifest = getClass().getClassLoader().getResource("karFileAsZip.zip").toURI();
+ zipFileWithoutKarafManifest = getClass().getClassLoader().getResource("karFileAsZipNoManifest.zip").toURI();
+ badZipFile = getClass().getClassLoader().getResource("badZipFile.zip").toURI();
+ }
+
+ @After
+ public void destroy() throws Exception {
+ karDeploymentListener.destroy();
+ }
+
+ @Test
+ public void shouldHandleKarFile() throws Exception {
+ assertTrue(karDeploymentListener.canHandle(new File(goodKarFile)));
+ }
+
+ @Test
+ public void shouldHandleZipFileWithKarafManifest() throws Exception {
+ assertTrue(karDeploymentListener.canHandle(new File(zipFileWithKarafManifest)));
+ }
+
+ @Test
+ public void shouldIgnoreZipFileWithoutKarafManifest() throws Exception {
+ assertFalse(karDeploymentListener.canHandle(new File(zipFileWithoutKarafManifest)));
+ }
+
+ @Test
+ public void shouldIgnoreBadZipFile() throws Exception {
+ assertFalse(karDeploymentListener.canHandle(new File(badZipFile)));
+ }
+}
\ No newline at end of file
Index: deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarURLHandlerTest.java
===================================================================
--- deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarURLHandlerTest.java (revision 0)
+++ deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarURLHandlerTest.java (revision 0)
@@ -0,0 +1,88 @@
+package org.apache.karaf.deployer.kar;
+
+import static org.easymock.EasyMock.createMock;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.karaf.features.FeaturesService;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class KarURLHandlerTest {
+
+ private KarURLHandler urlHandler;
+ private FeaturesService featuresService;
+
+ @Before
+ public void setUp() throws Exception {
+ urlHandler = new KarURLHandler();
+ featuresService = createMock(FeaturesService.class);
+ urlHandler.setFeaturesService(featuresService);
+ urlHandler.setLocalRepoPath("./target/local-repo");
+
+ urlHandler.init();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ urlHandler.destroy();
+ }
+
+ @Test (expected = MalformedURLException.class)
+ public void shouldThrowMalformedURLWhenPathIsEmpty() throws Exception{
+ urlHandler.openConnection(new URL("http", null, ""));
+ }
+
+ @Test
+ public void shouldRecognizeGoodFeaturesFile() throws Exception
+ {
+ URI goodFeaturesXml = getClass().getClassLoader().getResource("goodKarFile/org/foo/goodFeaturesXml.xml").toURI();
+ Assert.assertTrue(urlHandler.isFeaturesRepository(new File(goodFeaturesXml)));
+ }
+
+ @Test
+ public void shouldRejectBadFeaturesFile() throws Exception
+ {
+ URI goodFeaturesXml = getClass().getClassLoader().getResource("badFeaturesXml.xml").toURI();
+ Assert.assertFalse((urlHandler.isFeaturesRepository(new File(goodFeaturesXml))));
+ }
+
+ @Test
+ public void shouldExtractAndRegisterFeaturesFromKar() throws Exception {
+ // Setup expectations on the features service
+ featuresService.addRepository(EasyMock.anyObject(URI.class));
+ EasyMock.replay(featuresService);
+
+ // Test
+ //
+ getClass().getClassLoader().getResource("goodKarFile.kar").getFile();
+ urlHandler.extractKarafArchive(new URL("file", null, getClass().getClassLoader().getResource("goodKarFile.kar").getFile()));
+
+ // Verify expectations.
+ //
+ EasyMock.verify(featuresService);
+ }
+
+ @Test
+ public void shouldExtractAndRegisterFeaturesFromZip() throws Exception {
+ // Setup expectations on the features service
+ featuresService.addRepository(EasyMock.anyObject(URI.class));
+ EasyMock.replay(featuresService);
+
+ // Test
+ //
+ getClass().getClassLoader().getResource("karFileAsZip").getFile();
+ urlHandler.extractKarafArchive(new URL("file", null, getClass().getClassLoader().getResource("goodKarFile.kar").getFile()));
+
+ // Verify expectations.
+ //
+ EasyMock.verify(featuresService);
+ }
+
+}
Index: deployer/kar/src/test/resources/goodKarFile.kar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: deployer/kar/src/test/resources/goodKarFile.kar
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: deployer/kar/src/test/resources/karFileAsZip/META-INF/KARAF.MF
===================================================================
Index: deployer/kar/src/test/resources/karFileAsZip/org/foo/goodFeaturesXml.xml
===================================================================
--- deployer/kar/src/test/resources/karFileAsZip/org/foo/goodFeaturesXml.xml (revision 0)
+++ deployer/kar/src/test/resources/karFileAsZip/org/foo/goodFeaturesXml.xml (revision 0)
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
Index: deployer/kar/src/test/resources/badFeaturesXml.xml
===================================================================
--- deployer/kar/src/test/resources/badFeaturesXml.xml (revision 0)
+++ deployer/kar/src/test/resources/badFeaturesXml.xml (revision 0)
@@ -0,0 +1 @@
+This is not a features file!
\ No newline at end of file
Index: deployer/kar/src/test/resources/karFileAsZip.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: deployer/kar/src/test/resources/karFileAsZip.zip
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: deployer/kar/src/test/resources/goodKarFile/META-INF/KARAF.MF
===================================================================
Index: deployer/kar/src/test/resources/goodKarFile/org/foo/goodFeaturesXml.xml
===================================================================
--- deployer/kar/src/test/resources/goodKarFile/org/foo/goodFeaturesXml.xml (revision 0)
+++ deployer/kar/src/test/resources/goodKarFile/org/foo/goodFeaturesXml.xml (revision 0)
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
Index: deployer/kar/src/test/resources/goodKarFile/org/bar/hello.txt
===================================================================
Index: deployer/kar/src/test/resources/karFileAsZipNoManifest/org/foo/goodFeaturesXml.xml
===================================================================
--- deployer/kar/src/test/resources/karFileAsZipNoManifest/org/foo/goodFeaturesXml.xml (revision 0)
+++ deployer/kar/src/test/resources/karFileAsZipNoManifest/org/foo/goodFeaturesXml.xml (revision 0)
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
Index: deployer/kar/src/test/resources/karFileAsZipNoManifest.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: deployer/kar/src/test/resources/karFileAsZipNoManifest.zip
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: deployer/kar/src/test/resources/badZipFile.zip
===================================================================
--- deployer/kar/src/test/resources/badZipFile.zip (revision 0)
+++ deployer/kar/src/test/resources/badZipFile.zip (revision 0)
@@ -0,0 +1 @@
+This is *not* a well formed .kar file :(
\ No newline at end of file
Index: deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarDeploymentListener.java
===================================================================
--- deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarDeploymentListener.java (revision 0)
+++ deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarDeploymentListener.java (revision 0)
@@ -0,0 +1,73 @@
+/*
+ * 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.deployer.kar;
+
+import java.io.File;
+import java.net.URL;
+import java.util.zip.ZipFile;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.felix.fileinstall.ArtifactUrlTransformer;
+
+/**
+ * A deployment listener able to hot deploy a Karaf archive
+ */
+public class KarDeploymentListener implements ArtifactUrlTransformer {
+
+ private static final Log LOGGER = LogFactory
+ .getLog(KarDeploymentListener.class);
+
+ private static final String KAR_PREFIX = ".kar";
+ private static final String ZIP_PREFIX = ".zip";
+
+ public boolean canHandle(File artifact) {
+ // If the file ends with .kar, then we can handle it!
+ //
+ if (artifact.isFile() && artifact.getName().endsWith(KAR_PREFIX)) {
+ LOGGER.info("Found a .kar file to deploy.");
+ return true;
+ }
+ // Otherwise, check to see if it's a zip file containing a META-INF/KARAF.MF manifest.
+ //
+ else if (artifact.isFile() && artifact.getName().endsWith(ZIP_PREFIX)) {
+ LOGGER.debug("Found a .zip file to deploy; checking contents to see if it's a Karaf archive.");
+ try {
+ if (new ZipFile(artifact).getEntry("META-INF/KARAF.MF") != null) {
+ LOGGER.info("Found a Karaf archive with .zip prefix; will deploy.");
+ return true;
+ }
+ } catch (Exception e) {
+ LOGGER.warn("Problem extracting zip file '" + artifact.getName() + "'; ignoring.", e);
+ }
+ }
+
+ return false;
+ }
+
+ public URL transform(URL url) throws Exception {
+ return new URL("kar", null, url.toString());
+ }
+
+ public void init() {
+ LOGGER.debug("Initializing " + KarDeploymentListener.class.getName());
+ }
+
+ public void destroy() {
+ LOGGER.debug("Destroying " + KarDeploymentListener.class.getName());
+ }
+}
Index: deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarURLHandler.java
===================================================================
--- deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarURLHandler.java (revision 0)
+++ deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarURLHandler.java (revision 0)
@@ -0,0 +1,194 @@
+package org.apache.karaf.deployer.kar;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.karaf.features.FeaturesService;
+import org.osgi.service.url.AbstractURLStreamHandlerService;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class KarURLHandler extends AbstractURLStreamHandlerService {
+ private static Log logger = LogFactory.getLog(KarURLHandler.class);
+
+ private static String SYNTAX = "kar: kar-uri";
+
+ private String localRepoPath = "./local-repo";
+
+ private byte[] buffer = new byte[5 * 1024];
+
+ private DocumentBuilderFactory dbf;
+
+ private FeaturesService featuresService;
+
+ @Override
+ public synchronized URLConnection openConnection(URL url) throws IOException {
+ if (url.getPath() == null || url.getPath().trim().length() == 0) {
+ throw new MalformedURLException ("Path can not be null or empty. Syntax: " + SYNTAX );
+ }
+
+ if (logger.isInfoEnabled())
+ logger.info("Extracting Karaf Archive '" + url + "' to " + localRepoPath);
+
+ extractKarafArchive(new URL(url.getPath()));
+
+ return new Connection(url);
+ }
+
+ protected void extractKarafArchive(URL url) throws IOException {
+ ZipFile zipFile = null;
+ try {
+ zipFile = new ZipFile(url.getFile());
+ } catch (IOException e) {
+ logger.error("Unable to open file; details: " + e.getMessage());
+ throw e;
+ }
+ Enumeration entries = (Enumeration) zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+
+ if (! entry.getName().startsWith("META-INF")) {
+ if (entry.isDirectory()) {
+ java.io.File directory = new File(localRepoPath + File.separator + entry.getName());
+ if (logger.isDebugEnabled())
+ logger.debug("Creating directory '" + directory.getName());
+ directory.mkdirs();
+ } else {
+ File extract = new File(localRepoPath + File.separator + entry.getName());
+ BufferedOutputStream bos = new BufferedOutputStream(
+ new FileOutputStream(extract));
+
+ int count = 0;
+ int totalBytes = 0;
+ InputStream inputStream = zipFile.getInputStream(entry);
+ while ((count = inputStream.read(buffer)) > 0)
+ {
+ bos.write(buffer, 0, count);
+ totalBytes += count;
+ }
+
+ if (logger.isDebugEnabled())
+ logger.debug("Extracted " + totalBytes + " bytes to " + extract);
+
+ bos.close();
+ inputStream.close();
+
+ if (isFeaturesRepository(extract)) {
+ addToFeaturesRepositories(extract);
+ }
+ }
+ }
+ }
+
+ zipFile.close();
+
+ }
+
+ protected boolean isFeaturesRepository(File artifact) {
+ try {
+ if (artifact.isFile() && artifact.getName().endsWith(".xml")) {
+ Document doc = parse(artifact);
+ String name = doc.getDocumentElement().getLocalName();
+ String uri = doc.getDocumentElement().getNamespaceURI();
+ if ("features".equals(name) && (uri == null || "".equals(uri))) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ if (logger.isDebugEnabled())
+ logger.debug("File " + artifact.getName() + " is not a features file.", e);
+ }
+ return false;
+ }
+
+ protected Document parse(File artifact) throws Exception {
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ db.setErrorHandler(new ErrorHandler() {
+ public void warning(SAXParseException exception) throws SAXException {
+ }
+ public void error(SAXParseException exception) throws SAXException {
+ }
+ public void fatalError(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+ });
+ return db.parse(artifact);
+ }
+
+ private void addToFeaturesRepositories(File file) {
+ try {
+ featuresService.addRepository(file.toURI());
+ if (logger.isInfoEnabled())
+ logger.info("Added feature repository '" + file.toURI() + "'.");
+ } catch (Exception e) {
+ logger.error("Unable to add repository '" + file.getName() + "'", e);
+ }
+ }
+
+ public class Connection extends URLConnection {
+ public Connection(URL url) {
+ super(url);
+ }
+
+ @Override
+ public void connect() throws IOException {
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ try {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ // TODO: Adrian Trenaman 20/09/10
+ //
+ // Not sure if there really is a need to transform the URL into a 'bundle'
+ // Leaving this in commented-out just in case; can reintroduce later.
+ //
+ // KarURLTransformer.transform(url, os);
+ os.close();
+ return new ByteArrayInputStream(os.toByteArray());
+ } catch (Exception e) {
+ logger.error("Error opening kar url", e);
+ throw (IOException) new IOException("Error opening kar xml url").initCause(e);
+ }
+ }
+ }
+
+ public void init() {
+ dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+
+ if (logger.isInfoEnabled())
+ logger.debug("Initialising the Kar URL Handler; Karaf Archives will be extracted to " + localRepoPath);
+ }
+
+ public void destroy() {
+ logger.debug("Destroying the Kar URL Handler");
+ }
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public void setLocalRepoPath(String localRepoPath) {
+ this.localRepoPath = localRepoPath;
+ }
+
+}
Index: deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml
===================================================================
--- deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml (revision 0)
+++ deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml (revision 0)
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: deployer/kar/pom.xml
===================================================================
--- deployer/kar/pom.xml (revision 0)
+++ deployer/kar/pom.xml (revision 0)
@@ -0,0 +1,96 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.karaf.deployer
+ deployer
+ 2.1.99-SNAPSHOT
+
+
+ org.apache.karaf.deployer
+ org.apache.karaf.deployer.kar
+ bundle
+ 2.1.99-SNAPSHOT
+ Apache Karaf :: Karaf Archive (.kar) Deployer
+
+ This deployer can deploy .kar archives on the fly
+
+
+ ${basedir}/../../etc/appended-resources
+
+
+
+
+ org.apache.felix
+ org.osgi.core
+ provided
+
+
+ org.springframework.osgi
+ spring-osgi-core
+
+
+ org.apache.karaf.features
+ org.apache.karaf.features.core
+
+
+ commons-logging
+ commons-logging
+
+
+ org.apache.felix
+ org.apache.felix.fileinstall
+
+
+ org.apache.servicemix.bundles
+ org.apache.servicemix.bundles.junit
+
+
+ org.easymock
+ easymock
+ 3.0
+ jar
+ test
+
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+
+
+
+ ${project.artifactId};blueprint.graceperiod:=false
+ ${project.artifactId}*;version=${project.version}
+ !${project.artifactId}*,*
+ org.apache.karaf.deployer.features
+ <_versionpolicy>${bnd.version.policy}
+
+
+
+
+
+
+
Index: pom.xml
===================================================================
--- pom.xml (revision 998721)
+++ pom.xml (working copy)
@@ -244,6 +244,11 @@
${project.version}
+ org.apache.karaf.deployer
+ org.apache.karaf.deployer.kar
+ ${project.version}
+
+
org.apache.karaf
org.apache.karaf.management
${project.version}
Index: features/command/src/main/resources/OSGI-INF/blueprint/features-command.xml
===================================================================
--- features/command/src/main/resources/OSGI-INF/blueprint/features-command.xml (revision 998721)
+++ features/command/src/main/resources/OSGI-INF/blueprint/features-command.xml (working copy)
@@ -36,12 +36,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -96,7 +96,7 @@
-
+