Index: server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java
===================================================================
--- server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java	(revision 1204152)
+++ server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryImpl.java	(working copy)
@@ -60,6 +60,19 @@
         }
     }
 
+    /* 
+     * For proxy Cave Repositories
+     */
+    public CaveRepositoryImpl(String name, String location, URL proxiedRepositoryUrl) throws Exception {
+        super();
+
+        this.setName(name);
+        this.setLocation(location);
+        this.setProxiedRepositoryUrl(proxiedRepositoryUrl);
+
+        this.createRepositoryDirectory();
+    }
+    
     /**
      * Check if the repository folder exists and create it if not.
      */
@@ -83,7 +96,7 @@
     private void generateRepositoryXml() throws Exception {
         File repositoryXml = this.getRepositoryXmlFile();
         OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(repositoryXml));
-        new DataModelHelperImpl().writeRepository(obrRepository, writer);
+        new CaveDataModelHelperImpl().writeRepository(obrRepository, this.getProxiedRepositoryUrl(), writer);
         writer.flush();
         writer.close();
     }
@@ -180,18 +193,21 @@
     /**
      * Proxy an URL (by adding repository.xml OBR information) in the Karaf Cave repository.
      *
-     * @param url the URL to proxyFilesystem. the URL to proxyFilesystem.
+     * @param url the remote URL to proxy
      * @throws Exception
      */
-    public void proxy(URL url) throws Exception {
-        if (url.getProtocol().equals("file")) {
+    public void proxyscan() throws Exception {
+        obrRepository = new RepositoryImpl();
+        obrRepository.setName(this.getName());
+        URL proxiedURL = this.getProxiedRepositoryUrl();
+        if (proxiedURL.getProtocol().equals("file")) {
             // filesystem proxyFilesystem (to another folder)
-            File proxyFolder = new File(url.toURI());
+            File proxyFolder = new File(proxiedURL.toURI());
             this.proxyFilesystem(proxyFolder);
         }
-        if (url.getProtocol().equals("http")) {
+        if (proxiedURL.getProtocol().equals("http")) {
             // HTTP proxyFilesystem
-            this.proxyHttp(url.toExternalForm());
+            this.proxyHttp(proxiedURL.toExternalForm());
         }
         this.generateRepositoryXml();
     }
Index: server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java
===================================================================
--- server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java	(revision 1204152)
+++ server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveRepositoryServiceImpl.java	(working copy)
@@ -21,6 +21,7 @@
 import org.apache.karaf.cave.server.api.CaveRepositoryService;
 
 import java.io.File;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -68,7 +69,7 @@
      *
      * @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.
+     * @param scan if true, the repository is scanned at creation time.
      * @return the Karaf Cave repository.
      * @throws Exception in case of creation failure.
      */
@@ -82,6 +83,26 @@
     }
 
     /**
+     * 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 repository is scanned at creation time.
+     * @return the Karaf Cave repository.
+     * @throws Exception in case of creation failure.
+     */
+    public synchronized CaveRepository proxyRepository(String name, URL url) throws Exception {
+        File location = new File(storageLocation, name);
+        if (repositories.get(name) != null) {
+            throw new IllegalArgumentException("Cave repository " + name + " already exists.");
+        }
+        CaveRepository repository = new CaveRepositoryImpl(name, location.getAbsolutePath(), url);
+        repository.proxyscan();
+        repositories.put(name, repository);
+        return repository;
+    }
+
+    /**
      * Remove a Karaf Cave repository from the repositories registry.
      *
      * @param name the name of Karaf Cave repository to remove.
Index: server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveDataModelHelperImpl.java
===================================================================
--- server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveDataModelHelperImpl.java	(revision 0)
+++ server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveDataModelHelperImpl.java	(revision 0)
@@ -0,0 +1,178 @@
+/*
+ * 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 java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
+import org.apache.felix.bundlerepository.impl.Referral;
+import org.apache.felix.bundlerepository.impl.RepositoryImpl;
+import org.apache.felix.bundlerepository.impl.RepositoryParser;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
+import org.apache.felix.bundlerepository.impl.XmlWriter;
+
+/**
+ * Override of Felix's DataModelHelperImpl adding an additional "proxiedUrl" attribute
+ * for Proxy Cave repositories.  This attribute is used when updating a proxy repository.  
+ */
+public class CaveDataModelHelperImpl extends DataModelHelperImpl {
+
+    /**
+     * Top-level writeRepository method that contains an optional proxiedurl attribute.
+     * It is used in creating the repository.xml file.
+     * 
+     * @param repository - Top-level repository element to serialize to a file. 
+     * @param proxiedURL - proxiedURL value (null for non-proxy repositories)
+     * @param writer - XMLWriter element used to create the file
+     * @throws IOException
+     */
+    public void writeRepository(RepositoryImpl repository, URL proxiedURL, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, repository, proxiedURL);
+    }
+
+    private static void toXml(XmlWriter w, RepositoryImpl repository, URL proxiedURL) throws IOException
+    {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss.SSS");
+        
+        if (proxiedURL == null) {
+            w.element(RepositoryParser.REPOSITORY)
+            .attribute(RepositoryParser.NAME, repository.getName())
+            .attribute(RepositoryParser.LASTMODIFIED, format.format(new Date(repository.getLastModified())));
+        } else {
+            w.element(RepositoryParser.REPOSITORY)
+            .attribute(RepositoryParser.NAME, repository.getName())
+            .attribute(RepositoryParser.LASTMODIFIED, format.format(new Date(repository.getLastModified())))
+            .attribute("proxiedurl", proxiedURL.toString());
+        }
+            
+        if (repository instanceof RepositoryImpl)
+        {
+            Referral[] referrals = ((RepositoryImpl) repository).getReferrals();
+            for (int i = 0; referrals != null && i < referrals.length; i++)
+            {
+                w.element(RepositoryParser.REFERRAL)
+                    .attribute(RepositoryParser.DEPTH, new Integer(referrals[i].getDepth()))
+                    .attribute(RepositoryParser.URL, referrals[i].getUrl())
+                    .end();
+            }
+        }
+
+        Resource[] resources = repository.getResources();
+        for (int i = 0; resources != null && i < resources.length; i++)
+        {
+            toXml(w, resources[i]);
+        }
+
+        w.end();
+    }
+    
+    private static void toXml(XmlWriter w, Resource resource) throws IOException
+    {
+        w.element(RepositoryParser.RESOURCE)
+            .attribute(Resource.ID, resource.getId())
+            .attribute(Resource.SYMBOLIC_NAME, resource.getSymbolicName())
+            .attribute(Resource.PRESENTATION_NAME, resource.getPresentationName())
+            .attribute(Resource.URI, getRelativeUri(resource, Resource.URI))
+            .attribute(Resource.VERSION, resource.getVersion().toString());
+
+        w.textElement(Resource.DESCRIPTION, resource.getProperties().get(Resource.DESCRIPTION))
+            .textElement(Resource.SIZE, resource.getProperties().get(Resource.SIZE))
+            .textElement(Resource.DOCUMENTATION_URI, getRelativeUri(resource, Resource.DOCUMENTATION_URI))
+            .textElement(Resource.SOURCE_URI, getRelativeUri(resource, Resource.SOURCE_URI))
+            .textElement(Resource.JAVADOC_URI, getRelativeUri(resource, Resource.JAVADOC_URI))
+            .textElement(Resource.LICENSE_URI, getRelativeUri(resource, Resource.LICENSE_URI));
+
+        String[] categories = resource.getCategories();
+        for (int i = 0; categories != null && i < categories.length; i++)
+        {
+            w.element(RepositoryParser.CATEGORY)
+                .attribute(RepositoryParser.ID, categories[i])
+                .end();
+        }
+        Capability[] capabilities = resource.getCapabilities();
+        for (int i = 0; capabilities != null && i < capabilities.length; i++)
+        {
+            toXml(w, capabilities[i]);
+        }
+        Requirement[] requirements = resource.getRequirements();
+        for (int i = 0; requirements != null && i < requirements.length; i++)
+        {
+            toXml(w, requirements[i]);
+        }
+        w.end();
+    }
+
+    private static String getRelativeUri(Resource resource, String name) 
+    {
+        String uri = (String) resource.getProperties().get(name);
+        if (resource instanceof ResourceImpl)
+        {
+            try
+            {
+                uri = URI.create(((ResourceImpl) resource).getRepository().getURI()).relativize(URI.create(uri)).toASCIIString();
+            }
+            catch (Throwable t)
+            {
+            }
+        }
+        return uri;
+    }
+
+    private static void toXml(XmlWriter w, Capability capability) throws IOException
+    {
+        w.element(RepositoryParser.CAPABILITY)
+            .attribute(RepositoryParser.NAME, capability.getName());
+        Property[] props = capability.getProperties();
+        for (int j = 0; props != null && j < props.length; j++)
+        {
+            toXml(w, props[j]);
+        }
+        w.end();
+    }
+
+    private static void toXml(XmlWriter w, Property property) throws IOException
+    {
+        w.element(RepositoryParser.P)
+            .attribute(RepositoryParser.N, property.getName())
+            .attribute(RepositoryParser.T, property.getType())
+            .attribute(RepositoryParser.V, property.getValue())
+            .end();
+    }
+
+    private static void toXml(XmlWriter w, Requirement requirement) throws IOException
+    {
+        w.element(RepositoryParser.REQUIRE)
+            .attribute(RepositoryParser.NAME, requirement.getName())
+            .attribute(RepositoryParser.FILTER, requirement.getFilter())
+            .attribute(RepositoryParser.EXTEND, Boolean.toString(requirement.isExtend()))
+            .attribute(RepositoryParser.MULTIPLE, Boolean.toString(requirement.isMultiple()))
+            .attribute(RepositoryParser.OPTIONAL, Boolean.toString(requirement.isOptional()))
+            .text(requirement.getComment().trim())
+            .end();
+    }
+}
Index: server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepositoryService.java
===================================================================
--- server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepositoryService.java	(revision 1204152)
+++ server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepositoryService.java	(working copy)
@@ -16,6 +16,8 @@
  */
 package org.apache.karaf.cave.server.api;
 
+import java.net.URL;
+
 import javax.ws.rs.*;
 
 /**
@@ -52,6 +54,19 @@
     CaveRepository createRepository(String name, String location, boolean scan) throws Exception;
 
     /**
+     * Proxy a new Karaf Cave repository.
+     *
+     * @param name the name of the new Karaf repository.
+     * @param proxiedUrl the URL (file or http) of the remote repository being proxied
+     * @return the Karaf Cave repository.
+     * @throws Exception in case of creation failure.
+     */
+    @POST
+    @Consumes("application/xml")
+    @Produces("application/xml")
+    CaveRepository proxyRepository(String name, URL proxiedUrl) throws Exception;
+
+    /**
      * Remove an existing Karaf Cave repository from the registry.
      * NB: the Karaf Cave repository storage is not removed.
      *
Index: server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepository.java
===================================================================
--- server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepository.java	(revision 1204152)
+++ server/api/src/main/java/org/apache/karaf/cave/server/api/CaveRepository.java	(working copy)
@@ -28,6 +28,7 @@
 
     private String name;
     private String location;
+    private URL proxiedRepositoryUrl;
 
     /**
      * Get the name of the repository.
@@ -66,6 +67,25 @@
     }
 
     /**
+     * Get the URL to the repository being proxied (for proxy Cave repositories only)
+     *
+     * @return the name of the repository
+     */
+    public URL getProxiedRepositoryUrl() {
+        return proxiedRepositoryUrl;
+    }
+
+    /**
+     * Set the URL of the repository to be proxied (for proxy Cave repositories only)
+     *
+     * @param proxiedRepositoryUrl the URL (file or http) of the remote repository to be proxied
+     */
+    public void setProxiedRepositoryUrl(URL proxiedRepositoryUrl) {
+        this.proxiedRepositoryUrl = proxiedRepositoryUrl;
+    }
+
+
+    /**
      * Upload an artifact from the given URL into the repository.
      *
      * @param url the URL of the artifact.
@@ -82,12 +102,12 @@
     public abstract void scan() throws Exception;
 
     /**
-     * Proxy an URL (for instance a Maven repository) and add OBR information.
+     * Add OBR information from a remote proxied URL
      *
      * @param url the URL to proxy.
      * @throws Exception
      */
-    public abstract void proxy(URL url) throws Exception;
+    public abstract void proxyscan() throws Exception;
 
     /**
      * Populate from a remote URL (for instance a Maven repository), and eventually update the OBR information.
Index: server/command/src/main/java/org/apache/karaf/cave/server/command/ProxyRepositoryCommand.java
===================================================================
--- server/command/src/main/java/org/apache/karaf/cave/server/command/ProxyRepositoryCommand.java	(revision 1204152)
+++ server/command/src/main/java/org/apache/karaf/cave/server/command/ProxyRepositoryCommand.java	(working copy)
@@ -29,19 +29,18 @@
 @Command(scope = "cave", name = "proxy-repository", description = "Proxy a given URL in the Karaf Cave repository")
 public class ProxyRepositoryCommand extends CaveRepositoryCommandSupport {
 
-    @Argument(index = 0, name = "name", description = "The Karaf Cave repository in which we want to proxy the URL", required = true, multiValued = false)
+    @Argument(index = 0, name = "name", description = "The new Karaf Cave repository in which we want to proxy the URL", required = true, multiValued = false)
     String name = null;
 
     @Argument(index = 1, name = "URL", description = "The URL to proxy in the Karaf Cave repository", required = true, multiValued = false)
     String url = null;
 
-    @Option(name = "-nu", aliases = { "--no-update", "--no-refresh", "--no-register" }, description = "No refresh of the OBR URLs", required = false, multiValued = false)
-    boolean noUpdate = false;
+    @Option(name = "-nr", aliases = {"--no-register"}, description = "Do not register the Cave repository within the OBR service", required = false, multiValued = false)
+    boolean noRegister = false;
 
     protected Object doExecute() throws Exception {
-        CaveRepository repository = getExistingRepository(name);
-        repository.proxy(new URL(url));
-        if (!noUpdate) {
+        getCaveRepositoryService().proxyRepository(name, new URL(url));
+        if (!noRegister) {
             getCaveRepositoryService().register(name);
         }
         return null;
Index: server/command/src/main/java/org/apache/karaf/cave/server/command/UpdateRepositoryCommand.java
===================================================================
--- server/command/src/main/java/org/apache/karaf/cave/server/command/UpdateRepositoryCommand.java	(revision 1204152)
+++ server/command/src/main/java/org/apache/karaf/cave/server/command/UpdateRepositoryCommand.java	(working copy)
@@ -31,7 +31,12 @@
 
     protected Object doExecute() throws Exception {
         CaveRepository caveRepository = getExistingRepository(name);
-        caveRepository.scan();
+        
+        if (caveRepository.getProxiedRepositoryUrl() != null) {
+            caveRepository.proxyscan();
+        } else {
+            caveRepository.scan();
+        }
         return null;
     }
 
