You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2011/12/27 18:32:35 UTC

svn commit: r1224954 [1/2] - in /karaf/trunk: ./ assemblies/features/standard/src/main/feature/ deployer/kar/ deployer/kar/src/main/java/org/apache/karaf/deployer/kar/ deployer/kar/src/main/resources/OSGI-INF/blueprint/ deployer/kar/src/test/java/org/a...

Author: jbonofre
Date: Tue Dec 27 17:32:33 2011
New Revision: 1224954

URL: http://svn.apache.org/viewvc?rev=1224954&view=rev
Log:
[KARAF-460] Add KAR service, commands, management, and refactoring of the deployer

Added:
    karaf/trunk/kar/
    karaf/trunk/kar/command/
    karaf/trunk/kar/command/NOTICE
    karaf/trunk/kar/command/pom.xml
      - copied, changed from r1222681, karaf/trunk/deployer/kar/pom.xml
    karaf/trunk/kar/command/src/
    karaf/trunk/kar/command/src/main/
    karaf/trunk/kar/command/src/main/java/
    karaf/trunk/kar/command/src/main/java/org/
    karaf/trunk/kar/command/src/main/java/org/apache/
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/KarCommandSupport.java
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/
    karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
    karaf/trunk/kar/command/src/main/resources/
    karaf/trunk/kar/command/src/main/resources/OSGI-INF/
    karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/
    karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/kar-command.xml
    karaf/trunk/kar/command/src/main/resources/OSGI-INF/bundle.info
    karaf/trunk/kar/core/
    karaf/trunk/kar/core/NOTICE
    karaf/trunk/kar/core/pom.xml
      - copied, changed from r1222681, karaf/trunk/deployer/kar/pom.xml
    karaf/trunk/kar/core/src/
    karaf/trunk/kar/core/src/main/
    karaf/trunk/kar/core/src/main/java/
    karaf/trunk/kar/core/src/main/java/org/
    karaf/trunk/kar/core/src/main/java/org/apache/
    karaf/trunk/kar/core/src/main/java/org/apache/karaf/
    karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/
    karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/KarService.java
    karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/
    karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
    karaf/trunk/kar/core/src/main/resources/
    karaf/trunk/kar/core/src/main/resources/OSGI-INF/
    karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/
    karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/kar-core.xml
    karaf/trunk/kar/core/src/main/resources/OSGI-INF/bundle.info
    karaf/trunk/kar/management/
    karaf/trunk/kar/management/NOTICE
    karaf/trunk/kar/management/pom.xml
      - copied, changed from r1222681, karaf/trunk/deployer/kar/pom.xml
    karaf/trunk/kar/management/src/
    karaf/trunk/kar/management/src/main/
    karaf/trunk/kar/management/src/main/java/
    karaf/trunk/kar/management/src/main/java/org/
    karaf/trunk/kar/management/src/main/java/org/apache/
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/KarServiceMBean.java
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/
    karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/KarServiceMBeanImpl.java
    karaf/trunk/kar/management/src/main/resources/
    karaf/trunk/kar/management/src/main/resources/OSGI-INF/
    karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/
    karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/kar-management.xml
    karaf/trunk/kar/management/src/main/resources/OSGI-INF/bundle.info
    karaf/trunk/kar/pom.xml
Modified:
    karaf/trunk/assemblies/features/standard/src/main/feature/feature.xml
    karaf/trunk/deployer/kar/pom.xml
    karaf/trunk/deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarArtifactInstaller.java
    karaf/trunk/deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml
    karaf/trunk/deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarArtifactInstallerTest.java
    karaf/trunk/pom.xml
    karaf/trunk/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java

Modified: karaf/trunk/assemblies/features/standard/src/main/feature/feature.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/assemblies/features/standard/src/main/feature/feature.xml?rev=1224954&r1=1224953&r2=1224954&view=diff
==============================================================================
--- karaf/trunk/assemblies/features/standard/src/main/feature/feature.xml (original)
+++ karaf/trunk/assemblies/features/standard/src/main/feature/feature.xml Tue Dec 27 17:32:33 2011
@@ -103,13 +103,19 @@
         <bundle start-level="30">mvn:org.apache.karaf.web/org.apache.karaf.web.management/${project.version}</bundle>
     </feature>
 
-    <feature name="deployers" description="Provide KAR (Karaf Archive) artifacts support" version="${project.version}" resolver="(obr)">
+    <feature name="deployers" description="Provide Karaf deployer" version="${project.version}" resolver="(obr)">
         <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.blueprint/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.features/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.wrap/${project.version}</bundle>
     </feature>
 
+    <feature name="kar" description="Provide KAR (KARaf archive) support" version="${project.version}" resolver="(obr)">
+        <bundle start-level="30">mvn:org.apache.karaf.kar/org.apache.karaf.kar.core/${project.version}</bundle>
+        <bundle start-level="30">mvn:org.apache.karaf.kar/org.apache.karaf.kar.command/${project.version}</bundle>
+        <bundle start-level="30">mvn:org.apache.karaf.kar/org.apache.karaf.kar.management/${project.version}</bundle>
+        <bundle start-level="30">mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/${project.version}</bundle>
+    </feature>
+
     <feature name="webconsole-base" description="Base support of the Karaf WebConsole" version="${project.version}" resolver="(obr)">
         <config name="org.apache.karaf.webconsole">
             realm=karaf

Modified: karaf/trunk/deployer/kar/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/deployer/kar/pom.xml?rev=1224954&r1=1224953&r2=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/pom.xml (original)
+++ karaf/trunk/deployer/kar/pom.xml Tue Dec 27 17:32:33 2011
@@ -60,14 +60,16 @@
         </dependency>
 
         <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
+            <groupId>org.apache.karaf.kar</groupId>
+            <artifactId>org.apache.karaf.kar.core</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.fileinstall</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
             <groupId>org.apache.servicemix.bundles</groupId>
             <artifactId>org.apache.servicemix.bundles.junit</artifactId>

Modified: karaf/trunk/deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarArtifactInstaller.java
URL: http://svn.apache.org/viewvc/karaf/trunk/deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarArtifactInstaller.java?rev=1224954&r1=1224953&r2=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarArtifactInstaller.java (original)
+++ karaf/trunk/deployer/kar/src/main/java/org/apache/karaf/deployer/kar/KarArtifactInstaller.java Tue Dec 27 17:32:33 2011
@@ -18,330 +18,80 @@
  */
 package org.apache.karaf.deployer.kar;
 
-import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
 import org.apache.felix.fileinstall.ArtifactInstaller;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
+import org.apache.karaf.kar.KarService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
 public class KarArtifactInstaller implements ArtifactInstaller {
-
+    
     public static final String FEATURE_CLASSIFIER = "features";
-    private final Logger logger = LoggerFactory.getLogger(KarArtifactInstaller.class);
-
-	private static final String KAR_SUFFIX = ".kar";
-	private static final String ZIP_SUFFIX = ".zip";
-
-    private String base = "./";
-	private String localRepoPath = "./target/local-repo";
-
-	private String timestampPath;
-
-	private DocumentBuilderFactory dbf;
-
-	private FeaturesService featuresService;
-
-	public void init() {
-		dbf = DocumentBuilderFactory.newInstance();
-		dbf.setNamespaceAware(true);
-
-		timestampPath = localRepoPath + File.separator + ".timestamps";
-		if (new File(timestampPath).mkdirs()) {
-			logger.warn("Unable to create directory for Karaf Archive timestamps. Results may vary...");
-		}
 
-        logger.info("Karaf archives will be extracted to {}", localRepoPath);
-		logger.info("Timestamps for Karaf archives will be extracted to {}", timestampPath);
-
-	}
-
-	public void destroy() {
-		logger.info("Karaf archive installer destroyed.");
-	}
+    private static final Logger LOGGER = LoggerFactory.getLogger(KarArtifactInstaller.class);
+    
+    private final static String KAR_SUFFIX = ".kar";
+    private final static String ZIP_SUFFIX = ".zip";
 
+	private KarService karService;
 
 	public void install(File file) throws Exception {
-		// Check to see if this file has already been extracted. For example, on restart of Karaf,
-		// we don't necessarily want to re-extract all the Karaf Archives!
-		//
-		if (alreadyExtracted(file)) {
-			logger.info("Ignoring '{}'; timestamp indicates it's already been deployed.", file);
-			return;
-		}
-
-		logger.info("Installing KAR file {}", file);
-
-		ZipFile zipFile = new ZipFile(file);
-
-        List<URI> featuresRepositoriesInKar = new ArrayList<URI>();
-
-        Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zipFile.entries();
-		while (entries.hasMoreElements()) {
-			ZipEntry entry = entries.nextElement();
-
-            String repoEntryName = getRepoEntryName(entry);
-
-			if (repoEntryName != null) {
-                File extract = extract(zipFile, entry, repoEntryName, localRepoPath);
-                if (isFeaturesRepository(extract)) {
-                    addToFeaturesRepositories(extract.toURI());
-                    featuresRepositoriesInKar.add(extract.toURI());
-                }
-			}
-            if (entry.getName().startsWith("resource")) {
-                String resourceEntryName = entry.getName().substring("resource/".length());
-                extract(zipFile, entry, resourceEntryName, base);
-            }
-		}
-
-        installFeatures(featuresRepositoriesInKar);
-
-		zipFile.close();
-
-		updateTimestamp(file);
+        // check if the KAR is not already installed
+        if (karService.list().contains(file.getName())) {
+            LOGGER.info("KAR {} is already installed. Please uninstall it first.", file.getName());
+            return;
+        }
+        
+        LOGGER.info("Installing KAR file {}", file);
+        
+        karService.install(file.toURI());
 	}
 
-    private void installFeatures(List<URI> featuresRepositories) {
-        for (Repository repository : featuresService.listRepositories()) {
-            for (URI karFeatureRepoUri : featuresRepositories) {
-                if (repository.getURI().equals(karFeatureRepoUri)) {
-                    try {
-                        for (Feature feature : repository.getFeatures()) {
-                            try {
-                                featuresService.installFeature(feature, EnumSet.noneOf(FeaturesService.Option.class));
-                            } catch (Exception e) {
-                                logger.warn("Unable to install Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
-                            }
-                        }
-                    } catch (Exception e) {
-                        logger.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
-                    }
-                }
-            }
-        }
-    }
-
-    private File extract(ZipFile zipFile, ZipEntry entry, String repoEntryName, String base) throws IOException {
-        File extract;
-        if (entry.isDirectory()) {
-            extract = new File(base + File.separator + repoEntryName);
-            logger.debug("Creating directory {}", extract.getName());
-            extract.mkdirs();
-        } else {
-            extract = new File(base + File.separator + repoEntryName);
-            extract.getParentFile().mkdirs();
-
-            InputStream in = zipFile.getInputStream(entry);
-            FileOutputStream out = new FileOutputStream(extract);
-
-            byte[] buffer = new byte[8192];
-            int count = in.read(buffer);
-            int totalBytes = 0;
-
-            while (count >= 0) {
-                out.write(buffer, 0, count);
-                totalBytes += count;
-                count = in.read(buffer);
-            }
-
-            logger.debug("Extracted {} bytes to {}", totalBytes, extract);
-
-            in.close();
-            out.flush();
-            out.close();
-        }
-        return extract;
-    }
-
-    private String getRepoEntryName(ZipEntry entry) {
-        String entryName = entry.getName();
-        if (entryName.startsWith("repository")) {
-            return entryName.substring("repository/".length());
-        }
-        if (entryName.startsWith("META-INF") || entryName.startsWith("resources")) {
-            return null;
-
-        }
-        return entryName;
-    }
-
     public void uninstall(File file) throws Exception {
-        File timestamp = getArchiveTimestampFile(file);
-        if (timestamp.exists()) {
-            logger.debug("Removing the timestamp file");
-            timestamp.delete();
-        }
-		logger.warn("Karaf archive '{}' has been removed; however, its feature URLs have not been deregistered, and its bundles are still available in '{}'.", file, localRepoPath);
+        LOGGER.info("Uninstalling KAR {}", file.getName());
+        karService.uninstall(file.getName());
+        LOGGER.warn("KAR {} has been removed; however, its feature URLs have not been deregistered, " +
+                "and its bundles are still available in the system repository.", file.getName());
 	}
 
 	public void update(File file) throws Exception {
-		logger.warn("Karaf archive {}' has been updated; redeploying.", file);
-		install(file);
-	}
-
-	protected void updateTimestamp(File karafArchive) throws Exception {
-		File timestamp = getArchiveTimestampFile(karafArchive);
-
-		if (timestamp.exists()) {
-		    logger.debug("Deleting old timestamp file '{}'", timestamp);
-
-			if (!timestamp.delete()) {
-				throw new Exception("Unable to delete archive timestamp '" + timestamp + "'");
-			}
-		}
-
-		logger.debug("Creating timestamp file '{}'", timestamp);
-		timestamp.createNewFile();
-	}
-
-	protected boolean alreadyExtracted(File karafArchive) {
-		File timestamp = getArchiveTimestampFile(karafArchive);
-		if (timestamp.exists()) {
-			return timestamp.lastModified() >= karafArchive.lastModified();
-		}
-		return false;
-	}
-
-	protected File getArchiveTimestampFile(File karafArchive) {
-        File timestampDir = new File(new File(localRepoPath), ".timestamps");
-        if (!timestampDir.exists()) {
-            timestampDir.mkdirs();
-        }
-		return new File(timestampDir, karafArchive.getName());
-	}
-
-	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) || uri.startsWith("http://karaf.apache.org/xmlns/features/v"))) {
-			        return true;
-			    }
-			}
-		} catch (Exception e) {
-		    logger.debug("File '{}' is not a features file.", artifact.getName(), e);
-		}
-		return false;
+        LOGGER.warn("Karaf archive {}' has been updated; redeploying.", file);
+        karService.uninstall(file.getName());
+        karService.install(file.toURI());
 	}
 
-    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(URI uri) throws Exception {
-        //URI mvnUri = pathToMvnUri(path);
-		try {
-			featuresService.addRepository(uri);
-			logger.info("Added feature repository '{}'.", uri);
-		} catch (Exception e) {
-			logger.warn("Unable to add repository '{}'", uri, e);
-		}
-	}
-
-    static URI pathToMvnUri(String path) {
-        String[] bits = path.split("/");
-        String classifier = FEATURE_CLASSIFIER;
-        String artifactType = "xml";
-        String version = bits[bits.length - 2];
-        String artifactId = bits[bits.length - 3];
-        StringBuilder buf = new StringBuilder("mvn:");
-        for (int i = 0; i < bits.length - 3; i++) {
-            buf.append(bits[i]);
-            if (i < bits.length - 4) {
-                buf.append(".");
-            }
-        }
-        buf.append("/").append(artifactId).append("/").append(version).append("/").append(artifactType).append("/").append(classifier);
-        URI mvnUri = URI.create(buf.toString());
-        return mvnUri;
-    }
-
     public boolean canHandle(File file) {
 		// If the file ends with .kar, then we can handle it!
-		//
-		if (file.isFile() && file.getName().endsWith(KAR_SUFFIX)) {
-			logger.info("Found a .kar file to deploy.");
+        //
+        if (file.isFile() && file.getName().endsWith(KAR_SUFFIX)) {
+			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 (file.isFile() && file.getName().endsWith(ZIP_SUFFIX)) {
-			logger.debug("Found a .zip file to deploy; checking contents to see if it's a Karaf archive.");
-			try {
-				if (new ZipFile(file).getEntry("META-INF/KARAF.MF") != null) {
-					logger.info("Found a Karaf archive with .zip prefix; will deploy.");
-					return true;
-				}
+        //
+        else if (file.isFile() && file.getName().endsWith(ZIP_SUFFIX)) {
+			LOGGER.debug("Found a .zip file to deploy; checking contents to see if it's a Karaf archive.");
+            try {
+                if (new ZipFile(file).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 '{}'; ignoring.", file.getName(), e);
+				LOGGER.warn("Problem extracting zip file '{}'; ignoring.", file.getName(), e);
 			}
 		}
 
 		return false;
 	}
 
-	public boolean deleteLocalRepository() {
-		return deleteDirectory(new File(localRepoPath));
-	}
-
-	private boolean deleteDirectory(File path) {
-		if (path.exists()) {
-			File[] files = path.listFiles();
-			for (int i = 0; i < files.length; i++) {
-				if (files[i].isDirectory()) {
-					deleteDirectory(files[i]);
-				} else {
-					files[i].delete();
-				}
-			}
-		}
-		return (path.delete());
-	}
-
-    public void setBasePath(String base) {
-        this.base = base;
+    public KarService getKarService() {
+        return karService;
     }
 
-    public void setLocalRepoPath(String localRepoPath) {
-		this.localRepoPath = localRepoPath;
-	}
-
-	public void setFeaturesService(FeaturesService featuresService) {
-		this.featuresService = featuresService;
-	}
+    public void setKarService(KarService karService) {
+        this.karService = karService;
+    }
 
 }

Modified: karaf/trunk/deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml?rev=1224954&r1=1224953&r2=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml (original)
+++ karaf/trunk/deployer/kar/src/main/resources/OSGI-INF/blueprint/kar-deployer.xml Tue Dec 27 17:32:33 2011
@@ -21,12 +21,9 @@
 
 	<ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]" />
 	
-	<bean id="karArtifactInstaller" class="org.apache.karaf.deployer.kar.KarArtifactInstaller"
-		init-method="init" destroy-method="destroy" activation="lazy">
-			<property name="basePath" value="$[karaf.base]"/>
-			<property name="localRepoPath" value="$[karaf.base]/system"/>
-	        <property name="featuresService">
-	            <reference interface="org.apache.karaf.features.FeaturesService"/>
+	<bean id="karArtifactInstaller" class="org.apache.karaf.deployer.kar.KarArtifactInstaller" activation="lazy">
+	        <property name="karService">
+	            <reference interface="org.apache.karaf.kar.KarService"/>
 	        </property>
 	</bean>
 			

Modified: karaf/trunk/deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarArtifactInstallerTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarArtifactInstallerTest.java?rev=1224954&r1=1224953&r2=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarArtifactInstallerTest.java (original)
+++ karaf/trunk/deployer/kar/src/test/java/org/apache/karaf/deployer/kar/KarArtifactInstallerTest.java Tue Dec 27 17:32:33 2011
@@ -19,24 +19,19 @@
 package org.apache.karaf.deployer.kar;
 
 import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.net.URI;
 
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.easymock.EasyMock;
-import org.junit.After;
-import org.junit.Assert;
+import org.apache.karaf.kar.KarService;
 import org.junit.Before;
 import org.junit.Test;
 
 public class KarArtifactInstallerTest {
 	private KarArtifactInstaller karArtifactInstaller;
-	private FeaturesService featuresService;
+	private KarService karService;
 
 	private URI goodKarFile;
 	private URI zipFileWithKarafManifest;
@@ -45,30 +40,18 @@ public class KarArtifactInstallerTest {
 	
 	@Before
 	public void setUp() throws Exception {
-		featuresService = createMock(FeaturesService.class);
+		karService = createMock(KarService.class);
 
 		karArtifactInstaller = new KarArtifactInstaller();
 
-		karArtifactInstaller.setFeaturesService(featuresService);
-		karArtifactInstaller.setBasePath("./target");
-		karArtifactInstaller.setLocalRepoPath("./target/local-repo");
-
-		karArtifactInstaller.init();
+		karArtifactInstaller.setKarService(karService);
 		
 		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 { 
-		karArtifactInstaller.destroy();
-		karArtifactInstaller.deleteLocalRepository();
-	}
-	
-	
-	
+
 	@Test
 	public void shouldHandleKarFile() throws Exception {
 		assertTrue(karArtifactInstaller.canHandle(new File(goodKarFile)));
@@ -89,126 +72,4 @@ public class KarArtifactInstallerTest {
 		assertFalse(karArtifactInstaller.canHandle(new File(badZipFile)));
 	}
 
-	@Test 
-	public void shouldRecognizeGoodFeaturesFile() throws Exception
-	{
-		File goodFeaturesXml = new File(getClass().getClassLoader().getResource("goodKarFile/org/foo/goodFeaturesXml.xml").getFile());
-		Assert.assertTrue(karArtifactInstaller.isFeaturesRepository(goodFeaturesXml));
-	}
-	
-	@Test 
-	public void shouldRejectNonFeaturesXMLFile() throws Exception
-	{
-		File goodFeaturesXml = new File(getClass().getClassLoader().getResource("badFeaturesXml.xml").toURI());
-		Assert.assertFalse(karArtifactInstaller.isFeaturesRepository(goodFeaturesXml));
-	}
-	
-	
-	@Test 
-	public void shouldRejectMalformedXMLFile() throws Exception
-	{
-		File malformedXml = new File(getClass().getClassLoader().getResource("malformedXml.xml").toURI());
-		Assert.assertFalse(karArtifactInstaller.isFeaturesRepository(malformedXml));
-	}
-	
-	@Test
-	public void shouldExtractAndRegisterFeaturesFromKar() throws Exception { 
-		// Setup expectations on the features service
-        expect(featuresService.listRepositories()).andReturn(new Repository[0]);
-		featuresService.addRepository((URI)EasyMock.anyObject());
-		EasyMock.replay(featuresService);
-		
-		// Test
-		//
-		File goodKarFile = new File(getClass().getClassLoader().getResource("goodKarFile.kar").getFile());
-		karArtifactInstaller.install(goodKarFile);
-		
-		// Verify expectations.
-		//
-		EasyMock.verify(featuresService);
-	}
-	
-	@Test
-	public void shouldLogAndNotThrowExceptionIfCannotAddToFeaturesRepository() throws Exception { 
-		// Setup expectations on the features service
-        expect(featuresService.listRepositories()).andReturn(new Repository[0]);
-		featuresService.addRepository((URI)EasyMock.anyObject());
-		EasyMock.expectLastCall().andThrow(new Exception("Unable to add to repository."));
-		EasyMock.replay(featuresService);
-		
-		// Test
-		//
-		File goodKarFile = new File(getClass().getClassLoader().getResource("goodKarFile.kar").getFile());
-		karArtifactInstaller.install(goodKarFile);
-		
-		// Verify expectations.
-		//
-		EasyMock.verify(featuresService);
-	}	
-	
-	@Test
-	public void shouldIgnoreUpdateIfFileHasNotChanged() throws Exception { 
-		// Setup expectations on the features service: the addRepository 
-		// should only be added once, as the update command should be ignored! 
-		//
-        expect(featuresService.listRepositories()).andReturn(new Repository[0]);
-		featuresService.addRepository((URI)EasyMock.anyObject());
-		EasyMock.replay(featuresService);
-		
-		// Test
-		//
-		File goodKarFile = new File(getClass().getClassLoader().getResource("goodKarFile.kar").getFile());
-		karArtifactInstaller.install(goodKarFile);
-		karArtifactInstaller.update(goodKarFile);
-		
-		// Verify expectations.
-		//
-		EasyMock.verify(featuresService);
-	}		
-	
-	@Test
-	public void shouldExtractAndRegisterFeaturesFromZip() throws Exception { 
-		// Setup expectations on the features service
-        expect(featuresService.listRepositories()).andReturn(new Repository[0]);
-		featuresService.addRepository((URI)EasyMock.anyObject());
-		EasyMock.replay(featuresService);
-		
-		// Test
-		//
-		File karFileAsZip = new File(getClass().getClassLoader().getResource("karFileAsZip.zip").getFile());
-		karArtifactInstaller.install(karFileAsZip);
-		
-		// Verify expectations.
-		//
-		EasyMock.verify(featuresService);
-	}
-	
-	@Test (expected = java.io.IOException.class) 
-	public void shouldThrowExceptionIfFileDoesNotExist() throws Exception
-	{
-		File nonExistantFile = new File("DoesNotExist");
-		karArtifactInstaller.install(nonExistantFile);
-	}	
-	
-	@Test
-	public void uninstallShouldDoNothing() throws Exception
-	{
-		EasyMock.replay(featuresService);
-		
-		// Test
-		//
-		File karFileAsZip = new File(getClass().getClassLoader().getResource("karFileAsZip.zip").getFile());
-		karArtifactInstaller.uninstall(karFileAsZip);
-		
-		// Verify expectations.
-		//
-		EasyMock.verify(featuresService);
-	}
-
-    @Test
-    public void testPathToMvnUri() throws Exception {
-        URI uri = KarArtifactInstaller.pathToMvnUri("org/apache/geronimo/features/org.apache.geronimo.transaction.kar/3.1.1-SNAPSHOT/org.apache.geronimo.transaction.kar-3.1.1-SNAPSHOT-features.xml");
-        assert "mvn:org.apache.geronimo.features/org.apache.geronimo.transaction.kar/3.1.1-SNAPSHOT/xml/features".equals(uri.toString());
-    }
-			
 }

Added: karaf/trunk/kar/command/NOTICE
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/NOTICE?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/NOTICE (added)
+++ karaf/trunk/kar/command/NOTICE Tue Dec 27 17:32:33 2011
@@ -0,0 +1,48 @@
+Apache Karaf
+Copyright 2010-2011 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.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+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.
+
+This product uses software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0

Copied: karaf/trunk/kar/command/pom.xml (from r1222681, karaf/trunk/deployer/kar/pom.xml)
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/pom.xml?p2=karaf/trunk/kar/command/pom.xml&p1=karaf/trunk/deployer/kar/pom.xml&r1=1222681&r2=1224954&rev=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/pom.xml (original)
+++ karaf/trunk/kar/command/pom.xml Tue Dec 27 17:32:33 2011
@@ -22,16 +22,16 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>org.apache.karaf.deployer</groupId>
-        <artifactId>deployer</artifactId>
+        <groupId>org.apache.karaf.kar</groupId>
+        <artifactId>kar</artifactId>
         <version>3.0.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>org.apache.karaf.deployer.kar</artifactId>
+    <artifactId>org.apache.karaf.kar.command</artifactId>
     <packaging>bundle</packaging>
-    <name>Apache Karaf :: Deployer :: Karaf Archive (.kar)</name>
-    <description>This deployer can deploy .kar archives on the fly</description>
+    <name>Apache Karaf :: KAR :: Command</name>
+    <description>This bundle provides a set of Karaf shell commands to manipulate KAR files.</description>
 
     <properties>
         <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
@@ -39,39 +39,12 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
+            <groupId>org.apache.karaf.kar</groupId>
+            <artifactId>org.apache.karaf.kar.core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.osgi</groupId>
-            <artifactId>spring-osgi-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.fileinstall</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.servicemix.bundles</groupId>
-            <artifactId>org.apache.servicemix.bundles.junit</artifactId>
-            <scope>test</scope>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.console</artifactId>
         </dependency>
     </dependencies>
 
@@ -97,22 +70,17 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <!-- Set the blueprint.graceperiod flag to false to allow the bundle to start
-                             See the blueprint config file -->
-                        <Bundle-SymbolicName>${project.artifactId};blueprint.graceperiod:=false</Bundle-SymbolicName>
                         <Import-Package>
-                            !${project.artifactId}*,
-                            org.apache.felix.service.command;version=${felix.gogo.version};status=provisional;mandatory:=status,
-                            org.apache.aries.blueprint,
-                            org.osgi.service.blueprint.container,
-                            org.osgi.service.blueprint.reflect,
-                            *
+                            org.apache.karaf.kar;version=${project.version},
+                            org.apache.karaf.shell.commands;version=${project.version},
+                            org.apache.karaf.shell.console*;version=${project.version},
+                            org.osgi.service.blueprint
                         </Import-Package>
-                        <Private-Package>org.apache.karaf.deployer.features</Private-Package>
+                        <Private-Package>!*</Private-Package>
                     </instructions>
                 </configuration>
             </plugin>
         </plugins>
     </build>
 
-</project>
+</project>
\ No newline at end of file

Added: karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java (added)
+++ karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.kar.command;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+
+import java.net.URI;
+
+@Command(scope = "kar", name = "install", description = "Installs a KAR file.")
+public class InstallKarCommand extends KarCommandSupport {
+    
+    @Argument(index = 0, name = "url", description = "The URL of the KAR file to install.", required = true, multiValued = false)
+    private String url;
+    
+    public Object doExecute() throws Exception {
+        this.getKarService().install(new URI(url));
+        return null;
+    }
+    
+}

Added: karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/KarCommandSupport.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/KarCommandSupport.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/KarCommandSupport.java (added)
+++ karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/KarCommandSupport.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,36 @@
+/*
+ * 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.kar.command;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+
+public abstract class KarCommandSupport extends OsgiCommandSupport {
+
+    private KarService karService;
+    
+    public KarService getKarService() {
+        return this.karService;
+    }
+    
+    public void setKarService(KarService karService) {
+        this.karService = karService;
+    }
+    
+    public abstract Object doExecute() throws Exception;
+
+}

Added: karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java (added)
+++ karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,31 @@
+/*
+ * 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.kar.command;
+
+import org.apache.karaf.shell.commands.Command;
+
+@Command(scope = "kar", name = "list", description = "List the installed KAR files.")
+public class ListKarCommand extends KarCommandSupport {
+    
+    public Object doExecute() throws Exception {
+        for (String karName : this.getKarService().list()) {
+           System.out.println(karName);
+        }
+        return null;
+    }
+    
+}

Added: karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java (added)
+++ karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,38 @@
+/*
+ * 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.kar.command;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+
+@Command(scope = "kar", name = "uninstall", description = "Uninstall a KAR file.")
+public class UninstallKarCommand extends KarCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the KAR file to uninstall.", required = true, multiValued = false)
+    private String name;
+
+    @Option(name = "-c", aliases = { "--clean" }, description = "Cleanup the system repository from the KAR content", required = false, multiValued = false)
+    private boolean clean = false;
+    
+    public Object doExecute() throws Exception {
+        //TODO use the clean flag
+        this.getKarService().uninstall(name);
+        return null;
+    }
+    
+}

Added: karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java (added)
+++ karaf/trunk/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,52 @@
+/*
+ * 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.kar.command.completers;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer on all installed KAR files.
+ */
+public class KarCompleter implements Completer {
+    
+    private KarService karService;
+    
+    public int complete(String buffer, int cursor, List candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String karName : karService.list()) {
+                delegate.getStrings().add(karName);
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+    
+    public void setKarService(KarService karService) {
+        this.karService = karService;
+    }
+    
+    public KarService getKarService() {
+        return this.karService;
+    }
+    
+}

Added: karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/kar-command.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/kar-command.xml?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/kar-command.xml (added)
+++ karaf/trunk/kar/command/src/main/resources/OSGI-INF/blueprint/kar-command.xml Tue Dec 27 17:32:33 2011
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        Licensed to the Apache Software Foundation (ASF) under one or more
+        contributor license agreements. See the NOTICE file distributed with
+        this work for additional information regarding copyright ownership.
+        The ASF licenses this file to You under the Apache License, Version
+        2.0 (the "License"); you may not use this file except in compliance
+        with the License. You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+        applicable law or agreed to in writing, software distributed under the
+        License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+        CONDITIONS OF ANY KIND, either express or implied. See the License for
+        the specific language governing permissions and limitations under the
+        License.
+    -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+        <command>
+            <action class="org.apache.karaf.kar.command.ListKarCommand">
+                <property name="karService" ref="karService"/>
+            </action>
+        </command>
+        <command>
+            <action class="org.apache.karaf.kar.command.InstallKarCommand">
+                <property name="karService" ref="karService"/>
+            </action>
+        </command>
+        <command>
+            <action class="org.apache.karaf.kar.command.UninstallKarCommand">
+                <property name="karService" ref="karService"/>
+            </action>
+            <completers>
+                <ref component-id="karCompleter"/>
+            </completers>
+        </command>
+    </command-bundle>
+
+    <reference id="karService" interface="org.apache.karaf.kar.KarService"/>
+
+    <bean id="karCompleter" class="org.apache.karaf.kar.command.completers.KarCompleter">
+        <property name="karService" ref="karService"/>
+    </bean>
+
+</blueprint>
\ No newline at end of file

Added: karaf/trunk/kar/command/src/main/resources/OSGI-INF/bundle.info
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/command/src/main/resources/OSGI-INF/bundle.info?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/command/src/main/resources/OSGI-INF/bundle.info (added)
+++ karaf/trunk/kar/command/src/main/resources/OSGI-INF/bundle.info Tue Dec 27 17:32:33 2011
@@ -0,0 +1,22 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides the shell commands to manipulate the KAR artifacts.
+
+Especially, the following commands are available:
+
+* kar:list
+* kar:install
+* kar:uninstall
+
+h1. See also
+
+KAR - section of the Karaf User Guide
\ No newline at end of file

Added: karaf/trunk/kar/core/NOTICE
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/NOTICE?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/core/NOTICE (added)
+++ karaf/trunk/kar/core/NOTICE Tue Dec 27 17:32:33 2011
@@ -0,0 +1,48 @@
+Apache Karaf
+Copyright 2010-2011 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.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+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.
+
+This product uses software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0

Copied: karaf/trunk/kar/core/pom.xml (from r1222681, karaf/trunk/deployer/kar/pom.xml)
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/pom.xml?p2=karaf/trunk/kar/core/pom.xml&p1=karaf/trunk/deployer/kar/pom.xml&r1=1222681&r2=1224954&rev=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/pom.xml (original)
+++ karaf/trunk/kar/core/pom.xml Tue Dec 27 17:32:33 2011
@@ -22,16 +22,16 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>org.apache.karaf.deployer</groupId>
-        <artifactId>deployer</artifactId>
+        <groupId>org.apache.karaf.kar</groupId>
+        <artifactId>kar</artifactId>
         <version>3.0.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>org.apache.karaf.deployer.kar</artifactId>
+    <artifactId>org.apache.karaf.kar.core</artifactId>
     <packaging>bundle</packaging>
-    <name>Apache Karaf :: Deployer :: Karaf Archive (.kar)</name>
-    <description>This deployer can deploy .kar archives on the fly</description>
+    <name>Apache Karaf :: KAR :: Core</name>
+    <description>This bundle provides core implementation of the KAR management service.</description>
 
     <properties>
         <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
@@ -39,39 +39,14 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.osgi</groupId>
-            <artifactId>spring-osgi-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
             <groupId>org.apache.karaf.features</groupId>
             <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.fileinstall</artifactId>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.servicemix.bundles</groupId>
-            <artifactId>org.apache.servicemix.bundles.junit</artifactId>
-            <scope>test</scope>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
         </dependency>
     </dependencies>
 
@@ -97,22 +72,25 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <!-- Set the blueprint.graceperiod flag to false to allow the bundle to start
-                             See the blueprint config file -->
-                        <Bundle-SymbolicName>${project.artifactId};blueprint.graceperiod:=false</Bundle-SymbolicName>
+                        <Export-Package>
+                            org.apache.karaf.kar;version=${project.version}
+                        </Export-Package>
                         <Import-Package>
-                            !${project.artifactId}*,
-                            org.apache.felix.service.command;version=${felix.gogo.version};status=provisional;mandatory:=status,
-                            org.apache.aries.blueprint,
-                            org.osgi.service.blueprint.container,
-                            org.osgi.service.blueprint.reflect,
-                            *
+                            !org.apache.karaf.kar,
+                            javax.xml.parsers,
+                            org.apache.karaf.features;version=${project.version},
+                            org.slf4j;resolution:=optional,
+                            org.w3c.dom,
+                            org.xml.sax,
+                            org.osgi.service.blueprint
                         </Import-Package>
-                        <Private-Package>org.apache.karaf.deployer.features</Private-Package>
+                        <Private-Package>
+                            org.apache.karaf.kar.internal
+                        </Private-Package>
                     </instructions>
                 </configuration>
             </plugin>
         </plugins>
     </build>
 
-</project>
+</project>
\ No newline at end of file

Added: karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/KarService.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/KarService.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/KarService.java (added)
+++ karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/KarService.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.kar;
+
+import java.net.URI;
+import java.util.List;
+
+/**
+ * The service managing KAR.
+ */
+public interface KarService {
+
+    /**
+     * Install KAR from a given URL.
+     *
+     * @param url the KAR URL.
+     * @throws Exception in case of installation failure.
+     */
+    void install(URI url) throws Exception;
+
+    /**
+     * Uninstall the given KAR.
+     * NB: the system folder is not cleaned.
+     *
+     * @param name the name of the KAR.
+     * @throws Exception in case of uninstall failure.
+     */
+    void uninstall(String name) throws Exception;
+
+    /**
+     * Uninstall the given KAR and, eventually, cleanup the repository from the KAR content.
+     *
+     * @param name the name of the KAR.
+     * @param clean true to cleanup the repository folder, false else.
+     * @throws Exception in case of uninstall failure.
+     */
+    void uninstall(String name, boolean clean) throws Exception;
+
+    /**
+     * List the KAR stored in the data folder.
+     * 
+     * @return the list of KAR stored.
+     * @throws Exception in case of listing failure.
+     */
+    List<String> list() throws Exception;
+    
+}

Added: karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java (added)
+++ karaf/trunk/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,352 @@
+/*
+ * 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.kar.internal;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.kar.KarService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * Implementation of the KAR service.
+ */
+public class KarServiceImpl implements KarService {
+
+    public static final Logger LOGGER = LoggerFactory.getLogger(KarServiceImpl.class);
+
+    private String storage = "./target/data/kar"; // ${KARAF.DATA}/kar
+    private String base = "./";
+    private String localRepo = "./target/local-repo"; // ${KARAF.BASE}/system
+    private FeaturesService featuresService;
+    
+    private DocumentBuilderFactory dbf;
+
+    /**
+     * Init method.
+     *
+     * @throws Exception in case of init failure.
+     */
+    public void init() throws Exception {
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        
+        File karStorageDir = new File(storage);
+        if (!karStorageDir.exists()) {
+            LOGGER.debug("Create the KAR storage directory");
+            karStorageDir.mkdirs();
+        }
+        if (!karStorageDir.isDirectory()) {
+            throw new IllegalStateException("KAR storage " + storage + " is not a directory");
+        }
+    }
+    
+    public void install(URI url) throws Exception {
+        File file = new File(url.toURL().getFile());
+        String karName = file.getName();
+        
+        LOGGER.debug("Installing KAR {} from {}", karName, url);
+        
+        LOGGER.debug("Check if the KAR file already exists in the storage directory");
+        File karStorage = new File(storage);
+        File karFile = new File(karStorage, karName);
+        
+        if (karFile.exists()) {
+            LOGGER.warn("The KAR file " + karName + " is already installed. Override it.");
+        }
+        
+        LOGGER.debug("Copy the KAR file from {} to {}", url, karFile.getParent());
+        copy(url, karFile);
+        
+        LOGGER.debug("Uncompress the KAR file {} into the system repository", karName);
+        ZipFile zipFile = new ZipFile(karFile);
+        
+        List<URI> featuresRepositoriesInKar = new ArrayList<URI>();
+        
+        Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zipFile.entries();
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = entries.nextElement();
+
+            String repoEntryName = getRepoEntryName(entry);
+
+            if (repoEntryName != null) {
+                File extract = extract(zipFile, entry, repoEntryName, localRepo);
+                if (isFeaturesRepository(extract)) {
+                    addToFeaturesRepositories(extract.toURI());
+                    featuresRepositoriesInKar.add(extract.toURI());
+                }
+            }
+            if (entry.getName().startsWith("resource")) {
+                String resourceEntryName = entry.getName().substring("resource/".length());
+                extract(zipFile, entry, resourceEntryName, base);
+            }
+        }
+        
+        installFeatures(featuresRepositoriesInKar);
+        
+        zipFile.close();
+    }
+    
+    public void uninstall(String karName) throws Exception {
+        File karStorage = new File(storage);
+        File karFile = new File(karStorage, karName);
+        
+        if (!karFile.exists()) {
+            throw new IllegalArgumentException("The KAR " + karName + " is not installed");
+        }
+
+        karFile.delete();
+    }
+    
+    public void uninstall(String karName, boolean clean) throws Exception {
+        // TODO
+    }
+    
+    public List<String> list() throws Exception {
+        File karStorage = new File(storage);
+        List<String> kars = new ArrayList<String>();
+        for (File kar : karStorage.listFiles()) {
+            kars.add(kar.getName());
+        }
+        return kars;
+    }
+
+    /**
+     * Create a destination file using a source URL.
+     * 
+     * @param url the source URL. 
+     * @param file the destination file
+     * @throws Exception in case of copy failure
+     */
+    private void copy(URI url, File file) throws Exception {
+        InputStream is = null;
+        FileOutputStream fos = null;
+        try {
+            is = url.toURL().openStream();
+            fos = new FileOutputStream(file);
+            byte[] buffer = new byte[8192];
+            int count = is.read(buffer);
+            while (count >= 0) {
+                fos.write(buffer, 0, count);
+                count = is.read(buffer);
+            }
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+            if (fos != null) {
+                fos.flush();
+                fos.close();
+            }
+        }
+    }
+
+    /**
+     * Get the entry name filtering the repository  folder.
+     *
+     * @param entry the "normal" entry name.
+     * @return the entry with the repository folder filtered.
+     */
+    private String getRepoEntryName(ZipEntry entry) {
+        String entryName = entry.getName();
+        if (entryName.startsWith("repository")) {
+            return entryName.substring("repository/".length());
+        }
+        if (entryName.startsWith("META-INF") || entryName.startsWith("resources")) {
+            return null;
+        }
+        return entryName;
+    }
+
+    /**
+     * Extract an entry from a KAR file.
+     * 
+     * @param zipFile the KAR file (zip file).
+     * @param zipEntry the entry in the KAR file.
+     * @param repoEntryName the target extract name.
+     * @param base the base directory where to extract the file.
+     * @return the extracted file.
+     * @throws Exception in the extraction fails.
+     */
+    private File extract(ZipFile zipFile, ZipEntry zipEntry, String repoEntryName, String base) throws Exception {
+        File extract;
+        if (zipEntry.isDirectory()) {
+            extract = new File(base + File.separator + repoEntryName);
+            LOGGER.debug("Creating directory {}", extract.getName());
+            extract.mkdirs();
+        } else {
+            extract = new File(base + File.separator + repoEntryName);
+            extract.getParentFile().mkdirs();
+            
+            InputStream in = zipFile.getInputStream(zipEntry);
+            FileOutputStream out = new FileOutputStream(extract);
+            
+            byte[] buffer = new byte[8192];
+            int count = in.read(buffer);
+            int totalBytes = 0;
+            
+            while (count >= 0) {
+                out.write(buffer, 0, count);
+                totalBytes += count;
+                count = in.read(buffer);
+            }
+
+            LOGGER.debug("Extracted {} bytes to {}", totalBytes, extract);
+
+            in.close();
+            out.flush();
+            out.close();
+        }
+        return extract;
+    }
+
+    /**
+     * Check if a file is a features XML.
+     *
+     * @param artifact the file to check.
+     * @return true if the artifact is a features XML, false else.
+     */
+    private 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) || uri.startsWith("http://karaf.apache.org/xmlns/features/v"))) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.debug("File '{}' is not a features file.", artifact.getName(), e);
+        }
+        return false;
+    }
+
+    /**
+     * Parse a features XML.
+     *
+     * @param artifact the features XML to parse.
+     * @return the parsed document.
+     * @throws Exception in case of parsing failure.
+     */
+    private 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);
+    }
+
+    /**
+     * Add an URI to the list of features repositories.
+     *
+     * @param uri the URI to add.
+     * @throws Exception in case of add failure.
+     */
+    private void addToFeaturesRepositories(URI uri) throws Exception {
+        try {
+            featuresService.addRepository(uri);
+            LOGGER.info("Added feature repository '{}'", uri);
+        } catch (Exception e) {
+            LOGGER.warn("Unable to add repository '{}'", uri, e);
+        }
+    }
+
+    /**
+     * Install all features contained in the list of features XML.
+     *
+     * @param featuresRepositories the list of features XML.
+     */
+    private void installFeatures(List<URI> featuresRepositories) {
+        for (Repository repository : featuresService.listRepositories()) {
+            for (URI karFeatureRepoUri : featuresRepositories) {
+                if (repository.getURI().equals(karFeatureRepoUri)) {
+                    try {
+                        for (Feature feature : repository.getFeatures()) {
+                            try {
+                                featuresService.installFeature(feature, EnumSet.noneOf(FeaturesService.Option.class));
+                            } catch (Exception e) {
+                                LOGGER.warn("Unable to install Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
+                            }
+                        }
+                    } catch (Exception e) {
+                        LOGGER.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
+                    }
+                }
+            }
+        }
+    }
+
+    public FeaturesService getFeaturesService() {
+        return featuresService;
+    }
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public String getStorage() {
+        return storage;
+    }
+
+    public void setStorage(String storage) {
+        this.storage = storage;
+    }
+
+    public String getBase() {
+        return base;
+    }
+
+    public void setBase(String base) {
+        this.base = base;
+    }
+
+    public String getLocalRepo() {
+        return localRepo;
+    }
+
+    public void setLocalRepo(String localRepo) {
+        this.localRepo = localRepo;
+    }
+
+}

Added: karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/kar-core.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/kar-core.xml?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/kar-core.xml (added)
+++ karaf/trunk/kar/core/src/main/resources/OSGI-INF/blueprint/kar-core.xml Tue Dec 27 17:32:33 2011
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        Licensed to the Apache Software Foundation (ASF) under one or more
+        contributor license agreements. See the NOTICE file distributed with
+        this work for additional information regarding copyright ownership.
+        The ASF licenses this file to You under the Apache License, Version
+        2.0 (the "License"); you may not use this file except in compliance
+        with the License. You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+        applicable law or agreed to in writing, software distributed under the
+        License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+        CONDITIONS OF ANY KIND, either express or implied. See the License for
+        the specific language governing permissions and limitations under the
+        License.
+    -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+           default-activation="lazy">
+
+    <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]" />
+
+    <bean id="karService" class="org.apache.karaf.kar.internal.KarServiceImpl" init-method="init">
+        <property name="base" value="$[karaf.base]"/>
+        <property name="storage" value="$[karaf.data]/kar"/>
+        <property name="localRepo" value="$[karaf.base]/system"/>
+        <property name="featuresService">
+            <reference interface="org.apache.karaf.features.FeaturesService"/>
+        </property>
+    </bean>
+
+    <service ref="karService" interface="org.apache.karaf.kar.KarService"/>
+
+</blueprint>
\ No newline at end of file

Added: karaf/trunk/kar/core/src/main/resources/OSGI-INF/bundle.info
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/core/src/main/resources/OSGI-INF/bundle.info?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/core/src/main/resources/OSGI-INF/bundle.info (added)
+++ karaf/trunk/kar/core/src/main/resources/OSGI-INF/bundle.info Tue Dec 27 17:32:33 2011
@@ -0,0 +1,19 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the Karaf kar support.
+
+Karaf Archives (KAR) is an artifact (zip file) shipping a features XML and the associated bundles or configuration
+files.
+
+h1. See also
+
+KAR - section of the Karaf User Guide

Added: karaf/trunk/kar/management/NOTICE
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/NOTICE?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/management/NOTICE (added)
+++ karaf/trunk/kar/management/NOTICE Tue Dec 27 17:32:33 2011
@@ -0,0 +1,48 @@
+Apache Karaf
+Copyright 2010-2011 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.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+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.
+
+This product uses software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0

Copied: karaf/trunk/kar/management/pom.xml (from r1222681, karaf/trunk/deployer/kar/pom.xml)
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/pom.xml?p2=karaf/trunk/kar/management/pom.xml&p1=karaf/trunk/deployer/kar/pom.xml&r1=1222681&r2=1224954&rev=1224954&view=diff
==============================================================================
--- karaf/trunk/deployer/kar/pom.xml (original)
+++ karaf/trunk/kar/management/pom.xml Tue Dec 27 17:32:33 2011
@@ -22,16 +22,16 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>org.apache.karaf.deployer</groupId>
-        <artifactId>deployer</artifactId>
+        <groupId>org.apache.karaf.kar</groupId>
+        <artifactId>kar</artifactId>
         <version>3.0.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>org.apache.karaf.deployer.kar</artifactId>
+    <artifactId>org.apache.karaf.kar.management</artifactId>
     <packaging>bundle</packaging>
-    <name>Apache Karaf :: Deployer :: Karaf Archive (.kar)</name>
-    <description>This deployer can deploy .kar archives on the fly</description>
+    <name>Apache Karaf :: KAR :: Management</name>
+    <description>This bundle provides MBeans to manipulate KAR files via JMX.</description>
 
     <properties>
         <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
@@ -39,39 +39,8 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.osgi</groupId>
-            <artifactId>spring-osgi-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.fileinstall</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.servicemix.bundles</groupId>
-            <artifactId>org.apache.servicemix.bundles.junit</artifactId>
-            <scope>test</scope>
+            <groupId>org.apache.karaf.kar</groupId>
+            <artifactId>org.apache.karaf.kar.core</artifactId>
         </dependency>
     </dependencies>
 
@@ -97,22 +66,20 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <!-- Set the blueprint.graceperiod flag to false to allow the bundle to start
-                             See the blueprint config file -->
-                        <Bundle-SymbolicName>${project.artifactId};blueprint.graceperiod:=false</Bundle-SymbolicName>
                         <Import-Package>
-                            !${project.artifactId}*,
-                            org.apache.felix.service.command;version=${felix.gogo.version};status=provisional;mandatory:=status,
-                            org.apache.aries.blueprint,
-                            org.osgi.service.blueprint.container,
-                            org.osgi.service.blueprint.reflect,
-                            *
+                            !org.apache.karaf.kar.management*,
+                            javax.management,
+                            org.apache.karaf.kar;version=${project.version},
+                            org.apache.karaf.management;version=${project.version},
+                            org.osgi.service.blueprint
                         </Import-Package>
-                        <Private-Package>org.apache.karaf.deployer.features</Private-Package>
+                        <Private-Package>
+                            org.apache.karaf.kar.management.internal
+                        </Private-Package>
                     </instructions>
                 </configuration>
             </plugin>
         </plugins>
     </build>
 
-</project>
+</project>
\ No newline at end of file

Added: karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/KarServiceMBean.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/KarServiceMBean.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/KarServiceMBean.java (added)
+++ karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/KarServiceMBean.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,56 @@
+/*
+ * 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.kar.management;
+
+import java.util.List;
+
+public interface KarServiceMBean {
+
+    /**
+     * List the installed KAR files.
+     *
+     * @return the list of KAR files.
+     * @throws Exception in case of listing failure.
+     */
+    List<String> getKars() throws Exception;
+
+    /**
+     * Install a KAR file from the given URL.
+     *
+     * @param url the JAR URL.
+     * @throws Exception in case of installation failure.
+     */
+    void install(String url) throws Exception;
+
+    /**
+     * Uninstall a KAR file.
+     * 
+     * @param name the name of the KAR file.
+     * @throws Exception in case of uninstall failure.
+     */
+    void uninstall(String name) throws Exception;
+
+    /**
+     * Uninstall a KAR file and clean the system repository with the KAR content.
+     *
+     * @param name the KAR name.
+     * @param clean true to cleanup the system repository, false else.
+     * @throws Exception in case of uninstall failure.
+     */
+    void uninstall(String name, boolean clean) throws Exception;
+
+}

Added: karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/KarServiceMBeanImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/KarServiceMBeanImpl.java?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/KarServiceMBeanImpl.java (added)
+++ karaf/trunk/kar/management/src/main/java/org/apache/karaf/kar/management/internal/KarServiceMBeanImpl.java Tue Dec 27 17:32:33 2011
@@ -0,0 +1,59 @@
+/*
+ * 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.kar.management.internal;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.kar.management.KarServiceMBean;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.net.URI;
+import java.util.List;
+
+public class KarServiceMBeanImpl extends StandardMBean implements KarServiceMBean {
+    
+    private KarService karService;
+    
+    public KarServiceMBeanImpl() throws NotCompliantMBeanException {
+        super(KarServiceMBean.class);
+    }
+    
+    public List<String> getKars() throws Exception {
+        return karService.list();
+    }
+    
+    public void install(String url) throws Exception {
+        karService.install(new URI(url));
+    }
+    
+    public void uninstall(String name) throws Exception {
+        karService.uninstall(name);
+    }
+    
+    public void uninstall(String name, boolean clean) throws Exception {
+        karService.uninstall(name, clean);
+    }
+
+    public KarService getKarService() {
+        return karService;
+    }
+
+    public void setKarService(KarService karService) {
+        this.karService = karService;
+    }
+    
+}

Added: karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/kar-management.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/kar-management.xml?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/kar-management.xml (added)
+++ karaf/trunk/kar/management/src/main/resources/OSGI-INF/blueprint/kar-management.xml Tue Dec 27 17:32:33 2011
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="eager">
+
+    <reference id="karService" interface="org.apache.karaf.kar.KarService"/>
+
+    <reference id="mbeanServer" interface="javax.management.MBeanServer">
+        <reference-listener ref="mbeanRegister" bind-method="registerMBeanServer" unbind-method="unregisterMBeanServer" />
+    </reference>
+
+    <bean id="mbeanImpl" class="org.apache.karaf.kar.management.internal.KarServiceMBeanImpl">
+        <property name="karService" ref="karService"/>
+    </bean>
+
+    <bean id="mbeanRegister" class="org.apache.karaf.management.MBeanRegistrer">
+        <property name="mbeans">
+            <map>
+                <entry value="org.apache.karaf:type=kar,name=${karaf.name}" key-ref="mbeanImpl" />
+            </map>
+        </property>
+    </bean>
+
+</blueprint>

Added: karaf/trunk/kar/management/src/main/resources/OSGI-INF/bundle.info
URL: http://svn.apache.org/viewvc/karaf/trunk/kar/management/src/main/resources/OSGI-INF/bundle.info?rev=1224954&view=auto
==============================================================================
--- karaf/trunk/kar/management/src/main/resources/OSGI-INF/bundle.info (added)
+++ karaf/trunk/kar/management/src/main/resources/OSGI-INF/bundle.info Tue Dec 27 17:32:33 2011
@@ -0,0 +1,22 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides MBean to manipulate Karaf KAR files via JMX.
+
+It provides the KarServiceMBean supporting the following operations:
+* getKars() - Gets the list of installed KAR files.
+* install(url) - Install the KAR file at the given URL.
+* uninstall(name) - Uninstall the KAR.
+* uninstall(name, clean) - Uninstall the KAR and eventually cleanup the local system repository.
+
+h1. See also
+
+KAR - and Remote Management via JMX - sections of the Karaf User Guide