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 2013/12/18 09:19:23 UTC
[02/50] [abbrv] Refactoring of the Cave modules. Complete HTTP
service wrapper.
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/pom.xml
----------------------------------------------------------------------
diff --git a/server/storage/pom.xml b/server/storage/pom.xml
new file mode 100644
index 0000000..cf2b5c0
--- /dev/null
+++ b/server/storage/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.cave</groupId>
+ <artifactId>org.apache.karaf.cave.server</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.karaf.cave.server</groupId>
+ <artifactId>org.apache.karaf.cave.server.storage</artifactId>
+ <name>Apache Karaf :: Cave :: Server :: Storage</name>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.cave.server</groupId>
+ <artifactId>org.apache.karaf.cave.server.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.bundlerepository</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jsoup</groupId>
+ <artifactId>jsoup</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient-osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Import-Package>
+ org.apache.karaf.cave.server.api;version="${project.version}",
+ org.slf4j*;resolution:=optional,
+ org.apache.felix.bundlerepository*;version="[2,3)",
+ org.osgi.framework,
+ org.osgi.service.blueprint,
+ org.osgi.service.log,
+ org.osgi.service.url,
+ org.apache.http*;version="[4,5)",
+ org.jsoup*;version="[1.6,2)",
+ org.apache.commons.io*;version="[2,3)",
+ !org.apache.felix.shell,
+ !org.apache.felix.bundlerepository.impl.wrapper,
+ !org.osgi.service.obr,
+ !javax.xml.stream,
+ </Import-Package>
+ <Private-Package>
+ org.kxml2.io,
+ org.xmlpull.v1,
+ org.apache.felix.utils*,
+ org.apache.felix.bundlerepository.impl*
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java
new file mode 100644
index 0000000..7a26948
--- /dev/null
+++ b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java
@@ -0,0 +1,421 @@
+/*
+ * 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.cave.server.storage;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
+import org.apache.felix.bundlerepository.impl.RepositoryImpl;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.karaf.cave.server.api.CaveRepository;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+
+/**
+ * Default implementation of a Karaf Cave repository.
+ */
+public class CaveRepositoryImpl extends CaveRepository {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(CaveRepositoryImpl.class);
+
+ private RepositoryImpl obrRepository;
+
+ public CaveRepositoryImpl(String name, String location, boolean scan) throws Exception {
+ super();
+
+ this.setName(name);
+ this.setLocation(location);
+
+ this.createRepositoryDirectory();
+ if (scan) {
+ this.scan();
+ }
+ }
+
+ /**
+ * Check if the repository folder exists and create it if not.
+ */
+ private void createRepositoryDirectory() throws Exception {
+ LOGGER.debug("Create Karaf Cave repository {} folder.", this.getName());
+ File locationFile = new File(this.getLocation());
+ if (!locationFile.exists()) {
+ locationFile.mkdirs();
+ LOGGER.debug("Karaf Cave repository {} location has been created.", this.getName());
+ LOGGER.debug(locationFile.getAbsolutePath());
+ }
+ File repositoryXml = new File(locationFile, "repository.xml");
+ if (repositoryXml.exists()) {
+ obrRepository = (RepositoryImpl) new DataModelHelperImpl().repository(repositoryXml.toURI().toURL());
+ } else {
+ obrRepository = new RepositoryImpl();
+ obrRepository.setName(this.getName());
+ }
+ }
+
+ /**
+ * Generate the repository.xml with the artifact at the given URL.
+ *
+ * @throws Exception in case of repository.xml update failure.
+ */
+ private void generateRepositoryXml() throws Exception {
+ File repositoryXml = this.getRepositoryXmlFile();
+ OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(repositoryXml));
+ new DataModelHelperImpl().writeRepository(obrRepository, writer);
+ writer.flush();
+ writer.close();
+ }
+
+ /**
+ * Add a resource in the OBR repository.
+ *
+ * @param resource the resource to add.
+ * @throws Exception in case of failure.
+ */
+ private void addResource(ResourceImpl resource) throws Exception {
+ if (resource != null) {
+ this.useResourceRelativeUri(resource);
+ obrRepository.addResource(resource);
+ obrRepository.setLastModified(System.currentTimeMillis());
+ }
+ }
+
+ /**
+ * Upload an artifact from the given URL.
+ *
+ * @param url the URL of the artifact.
+ * @throws Exception in case of upload failure.
+ */
+ public void upload(URL url) throws Exception {
+ LOGGER.debug("Upload new artifact from {}", url);
+ String artifactName = "artifact-" + System.currentTimeMillis();
+ File temp = new File(new File(this.getLocation()), artifactName);
+ FileUtils.copyURLToFile(url, temp);
+ // update the repository.xml
+ ResourceImpl resource = (ResourceImpl) new DataModelHelperImpl().createResource(temp.toURI().toURL());
+ if (resource == null) {
+ temp.delete();
+ LOGGER.warn("The {} artifact source is not a valid OSGi bundle", url);
+ return;
+ }
+ File destination = new File(new File(this.getLocation()), resource.getSymbolicName() + "-" + resource.getVersion() + ".jar");
+ FileUtils.moveFile(temp, destination);
+ resource = (ResourceImpl) new DataModelHelperImpl().createResource(destination.toURI().toURL());
+ this.addResource(resource);
+ this.generateRepositoryXml();
+ }
+
+ /**
+ * Scan the content of the whole repository to update the repository.xml.
+ *
+ * @throws Exception in case of scan failure.
+ */
+ public void scan() throws Exception {
+ this.scan(new File(this.getLocation()));
+ this.generateRepositoryXml();
+ }
+
+ /**
+ * Recursive method to traverse all files in the repository.
+ *
+ * @param entry the
+ * @throws Exception
+ */
+ private void scan(File entry) throws Exception {
+ if (entry.isDirectory()) {
+ File[] children = entry.listFiles();
+ for (int i = 0; i < children.length; i++) {
+ scan(children[i]);
+ }
+ } else {
+ // populate the repository
+ try {
+ ResourceImpl resource = (ResourceImpl) new DataModelHelperImpl().createResource(entry.toURI().toURL());
+ this.addResource(resource);
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Proxy an URL (by adding repository.xml OBR information) in the Karaf Cave repository.
+ *
+ * @param url the URL to proxyFilesystem. the URL to proxyFilesystem.
+ * @throws Exception
+ */
+ public void proxy(URL url) throws Exception {
+ if (url.getProtocol().equals("file")) {
+ // filesystem proxyFilesystem (to another folder)
+ File proxyFolder = new File(url.toURI());
+ this.proxyFilesystem(proxyFolder);
+ }
+ if (url.getProtocol().equals("http")) {
+ // HTTP proxyFilesystem
+ this.proxyHttp(url.toExternalForm());
+ }
+ this.generateRepositoryXml();
+ }
+
+ /**
+ * Proxy a local filesystem (folder).
+ * @param entry the filesystem to proxyFilesystem.
+ * @throws Exception in case of proxyFilesystem failure
+ */
+ private void proxyFilesystem(File entry) throws Exception {
+ LOGGER.debug("Proxying filesystem {}", entry.getAbsolutePath());
+ if (entry.isDirectory()) {
+ File[] children = entry.listFiles();
+ for (int i = 0; i < children.length; i++) {
+ proxyFilesystem(children[i]);
+ }
+ } else {
+ try {
+ Resource resource = new DataModelHelperImpl().createResource(entry.toURI().toURL());
+ if (resource != null) {
+ obrRepository.addResource(resource);
+ obrRepository.setLastModified(System.currentTimeMillis());
+ }
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Proxy a HTTP URL locally.
+ *
+ * @param url the HTTP URL to proxy.
+ * @throws Exception in case of proxy failure.
+ */
+ private void proxyHttp(String url) throws Exception {
+ LOGGER.debug("Proxying HTTP URL {}", url);
+ HttpClient httpClient = new DefaultHttpClient();
+
+ HttpGet httpGet = new HttpGet(url);
+ HttpResponse response = httpClient.execute(httpGet);
+ HttpEntity entity = response.getEntity();
+
+ if (entity != null) {
+ if (entity.getContentType().getValue().equals("application/java-archive")
+ || entity.getContentType().getValue().equals("application/octet-stream")) {
+ // I have a jar/binary, potentially a resource
+ try {
+ Resource resource = new DataModelHelperImpl().createResource(new URL(url));
+ if (resource != null) {
+ obrRepository.addResource(resource);
+ obrRepository.setLastModified(System.currentTimeMillis());
+ }
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ } else {
+ // try to find link to "browse"
+ Document document = Jsoup.connect(url).get();
+
+ Elements links = document.select("a");
+ if (links.size() > 1) {
+ for (int i = 1; i < links.size(); i++) {
+ Element link = links.get(i);
+ String absoluteHref = link.attr("abs:href");
+ this.proxyHttp(absoluteHref);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Populate an URL into the Karaf Cave repository, and eventually update the OBR information.
+ *
+ * @param url the URL to copy.
+ * @param update if true the OBR information is updated, false else.
+ * @throws Exception in case of populate failure.
+ */
+ public void populate(URL url, boolean update) throws Exception {
+ if (url.getProtocol().equals("file")) {
+ // populate the Karaf Cave repository from a filesystem folder
+ File populateFolder = new File(url.toURI());
+ this.populateFromFilesystem(populateFolder, update);
+ }
+ if (url.getProtocol().equals("http")) {
+ // populate the Karaf Cave repository from a HTTP URL
+ this.populateFromHttp(url.toExternalForm(), update);
+ }
+ if (update) {
+ this.generateRepositoryXml();
+ }
+ }
+
+ /**
+ * Populate the Karaf Cave repository using a filesystem directory.
+ *
+ * @param filesystem the "source" directory.
+ * @param update if true, the resources are added into the OBR metadata, false else.
+ * @throws Exception in case of populate failure.
+ */
+ private void populateFromFilesystem(File filesystem, boolean update) throws Exception {
+ LOGGER.debug("Populating from filesystem {}", filesystem.getAbsolutePath());
+ if (filesystem.isDirectory()) {
+ File[] children = filesystem.listFiles();
+ for (int i = 0; i < children.length; i++) {
+ populateFromFilesystem(children[i], update);
+ }
+ } else {
+ try {
+ ResourceImpl resource = (ResourceImpl) new DataModelHelperImpl().createResource(filesystem.toURI().toURL());
+ if (resource != null) {
+ // copy the resource
+ File destination = new File(new File(this.getLocation()), filesystem.getName());
+ LOGGER.debug("Copy from {} to {}", filesystem.getAbsolutePath(), destination.getAbsolutePath());
+ FileUtils.copyFile(filesystem, destination);
+ if (update) {
+ resource = (ResourceImpl) new DataModelHelperImpl().createResource(destination.toURI().toURL());
+ LOGGER.debug("Update the OBR metadata with {}", resource.getId());
+ this.addResource(resource);
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Populate the Karaf Cave repository using the given URL.
+ *
+ * @param url the "source" HTTP URL.
+ * @param update true if the OBR metadata should be updated, false else.
+ * @throws Exception in case of populate failure.
+ */
+ private void populateFromHttp(String url, boolean update) throws Exception {
+ LOGGER.debug("Populating from HTTP URL {}", url);
+ HttpClient httpClient = new DefaultHttpClient();
+
+ HttpGet httpGet = new HttpGet(url);
+ HttpResponse response = httpClient.execute(httpGet);
+ HttpEntity entity = response.getEntity();
+
+ if (entity != null) {
+ if (entity.getContentType().getValue().equals("application/java-archive")
+ || entity.getContentType().getValue().equals("application/octet-stream")) {
+ // I have a jar/binary, potentially a resource
+ try {
+ ResourceImpl resource = (ResourceImpl) new DataModelHelperImpl().createResource(new URL(url));
+ if (resource != null) {
+ LOGGER.debug("Copy {} into the Karaf Cave repository storage", url);
+ int index = url.lastIndexOf("/");
+ if (index > 0) {
+ url = url.substring(index);
+ }
+ File destination = new File(new File(this.getLocation()), url);
+ FileOutputStream outputStream = new FileOutputStream(destination);
+ entity.writeTo(outputStream);
+ outputStream.flush();
+ outputStream.close();
+ if (update) {
+ resource = (ResourceImpl) new DataModelHelperImpl().createResource(destination.toURI().toURL());
+ LOGGER.debug("Update OBR metadata with {}", resource.getId());
+ this.addResource(resource);
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ } else {
+ // try to find link to "browse"
+ Document document = Jsoup.connect(url).get();
+
+ Elements links = document.select("a");
+ if (links.size() > 1) {
+ for (int i = 1; i < links.size(); i++) {
+ Element link = links.get(i);
+ String absoluteHref = link.attr("abs:href");
+ this.populateFromHttp(absoluteHref, update);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert the Resource absolute URI to an URI relative to the repository one.
+ *
+ * @param resource the Resource to manipulate.
+ * @throws Exception in cave of URI convertion failure.
+ */
+ private void useResourceRelativeUri(ResourceImpl resource) throws Exception {
+ String resourceURI = resource.getURI();
+ String locationURI = "file:" + this.getLocation();
+ LOGGER.debug("Converting resource URI {} relatively to repository URI {}", resourceURI, locationURI);
+ if (resourceURI.startsWith(locationURI)) {
+ resourceURI = resourceURI.substring(locationURI.length() + 1);
+ LOGGER.debug("Resource URI converted to " + resourceURI);
+ resource.put(Resource.URI, resourceURI);
+ }
+
+ }
+
+ /**
+ * Get the File object of the OBR repository.xml file.
+ *
+ * @return the File corresponding to the OBR repository.xml.
+ * @throws Exception
+ */
+ private File getRepositoryXmlFile() throws Exception {
+ return new File(new File(this.getLocation()), "repository.xml");
+ }
+
+ public void getResourceByUri(String uri) {
+ // construct the file starting from the repository URI
+
+ }
+
+ /**
+ * Return the OBR repository.xml corresponding to this Karaf Cave repository.
+ *
+ * @return the URL of the OBR repository.xml.
+ * @throws Exception in case of lookup failure.
+ */
+ public URL getRepositoryXml() throws Exception {
+ File repositoryXml = this.getRepositoryXmlFile();
+ return repositoryXml.toURI().toURL();
+ }
+
+ /**
+ * Delete the repository storage folder.
+ *
+ * @throws Exception in case of destroy failure.
+ */
+ public void cleanup() throws Exception {
+ FileUtils.deleteDirectory(new File(this.getLocation()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java
new file mode 100644
index 0000000..fdeee1c
--- /dev/null
+++ b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java
@@ -0,0 +1,128 @@
+/*
+ * 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.cave.server.storage;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.cave.server.api.CaveRepository;
+import org.apache.karaf.cave.server.api.CaveRepositoryService;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Default implementation of the Cave Repository Service.
+ */
+public class CaveRepositoryServiceImpl implements CaveRepositoryService {
+
+ private File storageLocation;
+ private RepositoryAdmin repositoryAdmin;
+
+ private Map<String, CaveRepository> repositories = new HashMap<String, CaveRepository>();
+
+ public File getStorageLocation() {
+ return this.storageLocation;
+ }
+
+ public void setStorageLocation(File storageLocation) {
+ this.storageLocation = storageLocation;
+ }
+
+ public RepositoryAdmin getRepositoryAdmin() {
+ return this.repositoryAdmin;
+ }
+
+ public void setRepositoryAdmin(RepositoryAdmin repositoryAdmin) {
+ this.repositoryAdmin = repositoryAdmin;
+ }
+
+ /**
+ * Create a new Karaf Cave repository.
+ *
+ * @param name the name of the repository
+ * @param scan if true, the repository is scanned at creation time.
+ * @return the Karaf Cave repository.
+ * @throws Exception in case of creation failure.
+ */
+ public synchronized CaveRepository createRepository(String name, boolean scan) throws Exception {
+ File location = new File(storageLocation, name);
+ return this.createRepository(name, location.getAbsolutePath(), scan);
+ }
+
+ /**
+ * Create a new Karaf Cave repository.
+ *
+ * @param name the name of the repository.
+ * @param location the storage location of the repository.
+ * @param scan if true, the repostory is scanned at creation time.
+ * @return the Karaf Cave repository.
+ * @throws Exception in case of creation failure.
+ */
+ public synchronized CaveRepository createRepository(String name, String location, boolean scan) throws Exception {
+ if (repositories.get(name) != null) {
+ throw new IllegalArgumentException("Cave repository " + name + " already exists.");
+ }
+ CaveRepository repository = new CaveRepositoryImpl(name, location, scan);
+ repositories.put(name, repository);
+ return repository;
+ }
+
+ /**
+ * Destroy a Karaf Cave repository.
+ *
+ * @param name the name of Karaf Cave repository to destroy.
+ * @throws Exception in case of destroy failure.
+ */
+ public synchronized void destroy(String name) throws Exception {
+ CaveRepository repository = this.getRepository(name);
+ if (repository != null) {
+ repository.cleanup();
+ repositories.remove(name);
+ }
+ }
+
+ /**
+ * Register a Karaf Cave repository in the OBR service.
+ *
+ * @param name the name of the Karaf Cave repository.
+ * @throws Exception in case of registration failure.
+ */
+ public synchronized void register(String name) throws Exception {
+ CaveRepository caveRepository = this.getRepository(name);
+ repositoryAdmin.addRepository(caveRepository.getRepositoryXml());
+ }
+
+ /**
+ * Get the list of all Karaf Cave repositories.
+ *
+ * @return the list of all Karaf Cave repositories.
+ */
+ public synchronized CaveRepository[] getRepositories() {
+ return repositories.values().toArray(new CaveRepository[0]);
+ }
+
+ /**
+ * Get the Karaf Cave repository identified by name.
+ *
+ * @param name the name of the Karaf Cave repository to look for.
+ * @return the corresponding Karaf Cave repository.
+ */
+ public synchronized CaveRepository getRepository(String name) {
+ return repositories.get(name);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/src/main/resources/OSGI-INF/blueprint/cave-storage.xml
----------------------------------------------------------------------
diff --git a/server/storage/src/main/resources/OSGI-INF/blueprint/cave-storage.xml b/server/storage/src/main/resources/OSGI-INF/blueprint/cave-storage.xml
new file mode 100644
index 0000000..f5dab07
--- /dev/null
+++ b/server/storage/src/main/resources/OSGI-INF/blueprint/cave-storage.xml
@@ -0,0 +1,55 @@
+<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+ xmlns:cxf="http://cxf.apache.org/blueprint/core"
+ xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
+ xsi:schemaLocation="
+ http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
+ http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
+ http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
+ "
+ default-activation="lazy">
+
+ <bean id="caveRepositoryService" class="org.apache.karaf.cave.server.storage.CaveRepositoryServiceImpl">
+ <property name="storageLocation" value="${storage.location}"/>
+ <property name="repositoryAdmin" ref="repositoryAdmin"/>
+ </bean>
+
+ <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin"/>
+
+ <service ref="caveRepositoryService" interface="org.apache.karaf.cave.server.api.CaveRepositoryService"/>
+
+ <!-- use the cm of Cave filesystem backend -->
+ <cm:property-placeholder persistent-id="org.apache.karaf.cave.server.storage" update-strategy="reload">
+ <cm:default-properties>
+ <cm:property name="storage.location" value="cave"/>
+ </cm:default-properties>
+ </cm:property-placeholder>
+
+ <!-- start the JAX-RS server -->
+ <jaxrs:server id="caveRepositoryJaxRsServer" address="/cave">
+ <jaxrs:serviceBeans>
+ <ref component-id="caveRepositoryService"/>
+ </jaxrs:serviceBeans>
+ </jaxrs:server>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveRepositoryImplTest.java
----------------------------------------------------------------------
diff --git a/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveRepositoryImplTest.java b/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveRepositoryImplTest.java
new file mode 100644
index 0000000..b04cb7e
--- /dev/null
+++ b/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveRepositoryImplTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.cave.server.storage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.net.URL;
+
+/**
+ * Unit test of the Cave Repository Implementation.
+ */
+@RunWith(JUnit4.class)
+public class CaveRepositoryImplTest {
+
+ private CaveRepositoryImpl repository;
+
+ @Before
+ public void setUp() throws Exception {
+ repository = new CaveRepositoryImpl("test", "target/test-repository", false);
+ }
+
+ @Test
+ public void testUploadBundleFromURL() throws Exception {
+ repository.upload(new URL("http://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.commons-beanutils/1.8.2_2/org.apache.servicemix.bundles.commons-beanutils-1.8.2_2.jar"));
+ repository.upload(new URL("http://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.commons-lang/2.4_5/org.apache.servicemix.bundles.commons-lang-2.4_5.jar"));
+ }
+
+ @Test
+ public void testUploadNonBundleFromURL() throws Exception {
+ repository.upload(new URL("http://repo1.maven.org/maven2/commons-vfs/commons-vfs/1.0/commons-vfs-1.0.jar"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf-cave/blob/94949ca7/server/storage/src/test/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/server/storage/src/test/resources/log4j.xml b/server/storage/src/test/resources/log4j.xml
new file mode 100644
index 0000000..a3140de
--- /dev/null
+++ b/server/storage/src/test/resources/log4j.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="threshold" value="DEBUG"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p - %-30c{1} - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="DEBUG"/>
+ <appender-ref ref="CONSOLE"/>
+ </root>
+
+</log4j:configuration>
\ No newline at end of file