You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2013/10/10 16:11:14 UTC

svn commit: r1530984 [1/5] - in /ace/trunk: org.apache.ace.agent.itest/ org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ org.apache.ace.agent.update.itest/ org.apache.ace.agent.update.itest/conf/ org.apache.ace.agent.update.itest/src/org/apac...

Author: jawi
Date: Thu Oct 10 14:11:13 2013
New Revision: 1530984

URL: http://svn.apache.org/r1530984
Log:
ACE-330 - limit number of deployment versions per target:

- introduced a new concept to configure repositories: 
  RepositoryConfiguration, which can be used to make fiddle settings of
  repositories, and is used, for example, to limit the number of 
  deployment versions;
- moved the OBR url setting needed in the artifact repository, that was
  scattered throughout the code to RepositoryConfiguration, simplifying
  some of the calling code;
- fixed some concurrency issues in the base repository implementation;
- made the integration tests no longer dependent on port 8080 for servlet
  communication, we could run itests on any port we want.


Added:
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java   (with props)
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/repository/RepositoryConfiguration.java   (with props)
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/repository/RepositoryConstants.java   (with props)
Removed:
    ace/trunk/org.apache.ace.agent.update.itest/conf/
Modified:
    ace/trunk/org.apache.ace.agent.itest/bnd.bnd
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
    ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java
    ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/AuthenticationTestBase.java
    ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/ObrAuthenticationTest.java
    ace/trunk/org.apache.ace.client.repository.itest/bnd.bnd
    ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/BaseRepositoryAdminTest.java
    ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/RepositoryAdminTest.java
    ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/TemplateProcessorTest.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/RepositoryAdminLoginContext.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ArtifactRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierManager.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentArtifactImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionObjectImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryObjectImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositorySerializer.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositorySet.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/TargetPropertyResolver.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/TargetRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/repository/ArtifactRepository.java
    ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/stateful/impl/StatefulTargetRepositoryImpl.java
    ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/impl/ArtifactTest.java
    ace/trunk/org.apache.ace.client.repository/test/org/apache/ace/client/repository/impl/ModelTest.java
    ace/trunk/org.apache.ace.client.rest.itest/bnd.bnd
    ace/trunk/org.apache.ace.client.rest.itest/src/org/apache/ace/client/rest/itest/RESTClientTest.java
    ace/trunk/org.apache.ace.client.rest/src/org/apache/ace/client/rest/RESTClientServlet.java
    ace/trunk/org.apache.ace.client.rest/src/org/apache/ace/client/rest/Workspace.java
    ace/trunk/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
    ace/trunk/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
    ace/trunk/org.apache.ace.deployment.rp.autoconf.itest/bnd.bnd
    ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java

Modified: ace/trunk/org.apache.ace.agent.itest/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/bnd.bnd?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.itest/bnd.bnd Thu Oct 10 14:11:13 2013
@@ -1,8 +1,10 @@
 Test-Cases: ${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
--runbundles: org.mockito.mockito-all,\
+-runbundles: \
+	org.mockito.mockito-all,\
 	org.apache.ace.agent;version=latest,\
 	org.apache.ace.test;version=latest,\
 	org.apache.ace.builder;version=latest,\
+	org.apache.felix.configadmin,\
 	org.apache.felix.dependencymanager,\
 	org.apache.felix.dependencymanager.shell,\
 	org.apache.felix.gogo.command,\
@@ -59,10 +61,9 @@ Private-Package: aQute.bnd.annotation.co
 	junit.osgi,\
 	org.mockito.mockito-all	
 -runsystempackages: sun.reflect
--runproperties: org.apache.felix.log.storeDebug=true,\
+-runproperties: \
 	org.apache.felix.eventadmin.Timeout=0,\
-	org.apache.ace.server.port=8080,\
-	org.osgi.service.http.port=8080,\
+	org.apache.felix.log.storeDebug=true,\
 	org.apache.felix.log.maxSize=1000
 Import-Package: org.apache.ace.agent,\
 	!org.osgi.service.component.annotations,\

Modified: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java Thu Oct 10 14:11:13 2013
@@ -41,6 +41,7 @@ import org.apache.ace.agent.Configuratio
 import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.EventListener;
 import org.apache.ace.agent.LoggingHandler.Levels;
+import org.apache.ace.test.constants.TestConstants;
 import org.apache.felix.dm.Component;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
@@ -419,10 +420,13 @@ public class AgentDeploymentTest extends
     public void testGetSizeEstimateForDeploymentPackage() throws Exception {
         AgentControl control = getService(AgentControl.class);
 
-        Map<String, String> props = createAgentConfiguration(false /* useStreaming */, 10 /* secs */);
+        Map<String, String> props = createAgentConfiguration(false /* useStreaming */, 1000 /* secs */);
 
         ConfigurationHandler configurationHandler = control.getConfigurationHandler();
         configurationHandler.putAll(props);
+        
+        // Allow configuration to propagate...
+        Thread.sleep(100L);
 
         synchronized (m_servlet) {
             m_servlet.reset();
@@ -650,6 +654,7 @@ public class AgentDeploymentTest extends
 
     private Map<String, String> createAgentConfiguration(boolean useStreaming, int syncInterval) {
         Map<String, String> props = new HashMap<String, String>();
+        props.put(AgentConstants.CONFIG_DISCOVERY_SERVERURLS, String.format("http://localhost:%d/", TestConstants.PORT));
         props.put(AgentConstants.CONFIG_IDENTIFICATION_AGENTID, AGENT_ID);
         props.put(AgentConstants.CONFIG_LOGGING_LEVEL, LOGLEVEL.name());
         props.put(AgentConstants.CONFIG_CONTROLLER_STREAMING, Boolean.toString(useStreaming));

Modified: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java Thu Oct 10 14:11:13 2013
@@ -40,7 +40,6 @@ import org.osgi.framework.ServiceRegistr
 public class AgentExtensionTest extends BaseAgentTest {
 
     public void testLifecycle() throws Exception {
-
         AgentControl agentControl = getService(AgentControl.class);
         assertNotNull(agentControl);
 

Modified: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java Thu Oct 10 14:11:13 2013
@@ -85,11 +85,11 @@ public abstract class BaseAgentTest exte
         Bundle agentBundle = getAgentBundle();
         File dataDir = agentBundle.getBundleContext().getDataFile("");
 
-//        System.out.println("BaseAgentTest: Stopping agent bundle");
+        // System.out.println("BaseAgentTest: Stopping agent bundle");
         agentBundle.stop();
-//        System.out.println("BaseAgentTest: Cleaning bundle data dir (" + dataDir + ")");
+        // System.out.println("BaseAgentTest: Cleaning bundle data dir (" + dataDir + ")");
         cleanDir(dataDir);
-//        System.out.println("BaseAgentTest: Cleaning system properties");
+        // System.out.println("BaseAgentTest: Cleaning system properties");
         Set<String> keysBeRemoved = new HashSet<String>();
         for (Object key : System.getProperties().keySet()) {
             if (key instanceof String && ((String) key).startsWith(AgentConstants.CONFIG_KEY_NAMESPACE)) {
@@ -99,7 +99,7 @@ public abstract class BaseAgentTest exte
         for (String removeKey : keysBeRemoved) {
             System.clearProperty(removeKey);
         }
-//        System.out.println("BaseAgentTest: Starting agent bundle");
+        // System.out.println("BaseAgentTest: Starting agent bundle");
         agentBundle.start();
     }
 

Modified: ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd Thu Oct 10 14:11:13 2013
@@ -2,7 +2,8 @@
 # it updates the agent bundle. This causes problems if other tests try to wire to
 # the the api package after the fact.
 Test-Cases: ${classes;CONCRETE;EXTENDS;junit.framework.TestCase}
--runbundles: org.mockito.mockito-all,\
+-runbundles: \
+	org.mockito.mockito-all,\
 	org.apache.ace.agent;version=latest,\
 	org.apache.ace.test;version=latest,\
 	org.apache.felix.dependencymanager,\
@@ -14,11 +15,7 @@ Test-Cases: ${classes;CONCRETE;EXTENDS;j
 	org.apache.ace.authentication.api;version=latest,\
 	org.apache.ace.connectionfactory;version=latest,\
 	org.apache.ace.deployment.provider.api;version=latest,\
-	org.apache.felix.gogo.command,\
-	org.apache.felix.gogo.runtime,\
-	org.apache.felix.gogo.shell,\
-	org.apache.felix.dependencymanager.shell,\
-	org.apache.ace.configurator.impl;version=latest,\
+	org.apache.ace.deployment.provider.filebased;version=latest,\
 	org.apache.felix.configadmin,\
 	org.apache.ace.http.listener;version=latest,\
 	biz.aQute.bnd,\
@@ -37,12 +34,10 @@ Private-Package: org.apache.ace.agent.it
 	junit.osgi,\
 	org.mockito.mockito-all	
 -runsystempackages: sun.reflect
--runproperties: org.apache.felix.log.storeDebug=true,\
+-runproperties: \
 	org.apache.felix.eventadmin.Timeout=0,\
-	org.apache.ace.server.port=8080,\
-	org.osgi.service.http.port=8080,\
-	org.apache.felix.log.maxSize=1000,\
-	org.apache.ace.configurator.CONFIG_DIR=../org.apache.ace.agent.update.itest/conf
+	org.apache.felix.log.storeDebug=true,\
+	org.apache.felix.log.maxSize=1000
 Import-Package: org.apache.ace.agent,\
 	!org.osgi.service.component.annotations,\
 	*

Modified: ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java (original)
+++ ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java Thu Oct 10 14:11:13 2013
@@ -24,6 +24,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.jar.Attributes;
@@ -37,7 +39,10 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.ace.agent.AgentConstants;
+import org.apache.ace.agent.AgentControl;
 import org.apache.ace.it.IntegrationTestBase;
+import org.apache.ace.test.constants.TestConstants;
 import org.apache.felix.dm.Component;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Version;
@@ -54,70 +59,32 @@ import org.osgi.service.http.HttpService
  * </ul>
  */
 public class AgentUpdateTest extends IntegrationTestBase {
-    private volatile HttpService m_http;
-    private volatile AgentUpdateOBRServlet m_servlet;
-
-    private enum Phase {
-        CORRUPT_STREAM, BUNDLE_DOES_NOT_RESOLVE, BUNDLE_DOES_NOT_START, BUNDLE_WORKS
-    }
-
-    @Override
-    protected Component[] getDependencies() {
-        return new Component[] {
-            createComponent()
-                .setImplementation(this)
-                .add(createServiceDependency().setService(HttpService.class).setRequired(true))
-        };
-    }
-
-    @Override
-    public void configureAdditionalServices() throws Exception {
-        Thread.sleep(200);
-        m_servlet = new AgentUpdateOBRServlet();
-        m_http.registerServlet("/obr", m_servlet, null, null);
-    }
-
-    @Override
-    public void doTearDown() throws Exception {
-        m_http.unregister("/obr");
-    }
-
-    public void testAgentUpdate() throws Exception {
-        final int defaultTimeout = 15;
-
-        CountDownLatch latch;
-
-        latch = m_servlet.setPhase(Phase.CORRUPT_STREAM, new CountDownLatch(1));
-        assertTrue("Timed out while recovering from update with broken stream.", latch.await(defaultTimeout, TimeUnit.SECONDS));
-
-        latch = m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_RESOLVE, new CountDownLatch(1));
-        assertTrue("Timed out while recovering from update with agent that does not resolve.", latch.await(defaultTimeout, TimeUnit.SECONDS));
-
-        latch = m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_START, new CountDownLatch(1));
-        assertTrue("Timed out while recovering from update with agent that does not start.", latch.await(defaultTimeout, TimeUnit.SECONDS));
-
-        latch = m_servlet.setPhase(Phase.BUNDLE_WORKS, new CountDownLatch(1));
-        assertTrue("Timed out while starting working bundle?!", latch.await(defaultTimeout, TimeUnit.SECONDS));
-
-        int timeout = defaultTimeout;
-        while (timeout-- > 0) {
-            Thread.sleep(200);
-            for (Bundle b : m_bundleContext.getBundles()) {
-                if ("org.apache.ace.agent".equals(b.getSymbolicName())) {
-                    if (b.getVersion().equals(new Version("2.0.0"))) {
-                        return;
-                    }
-                }
+    private static class DummyAuditLogServlet extends HttpServlet {
+        private static final long serialVersionUID = 1L;
+        
+        @Override
+        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            String pathInfo = req.getPathInfo();
+            if ("/send".equals(pathInfo)) {
+                resp.setStatus(HttpServletResponse.SC_OK);
+            } else {
+                resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
             }
         }
-        fail("Timed out waiting for update with new agent.");
     }
-
+    
     private static class AgentUpdateOBRServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
         private Phase m_phase;
         private CountDownLatch m_latch;
 
+        public synchronized CountDownLatch setPhase(Phase phase, CountDownLatch latch) {
+            m_phase = phase;
+            m_latch = latch;
+            System.out.println("Updating in phase: " + phase);
+            return latch;
+        }
+
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             String path = req.getPathInfo();
@@ -141,13 +108,6 @@ public class AgentUpdateTest extends Int
             }
         }
 
-        public synchronized CountDownLatch setPhase(Phase phase, CountDownLatch latch) {
-            m_phase = phase;
-            m_latch = latch;
-            System.out.println("Updating in phase: " + phase);
-            return latch;
-        }
-
         private InputStream getBundle() throws IOException {
             return new FileInputStream(new File("../org.apache.ace.agent/generated/org.apache.ace.agent.jar"));
         }
@@ -188,7 +148,84 @@ public class AgentUpdateTest extends Int
         }
     }
 
+    private enum Phase {
+        CORRUPT_STREAM, BUNDLE_DOES_NOT_RESOLVE, BUNDLE_DOES_NOT_START, BUNDLE_WORKS
+    }
+
     private static String createResource(String bsn, String version) {
         return "<resource id='" + bsn + "/" + version + "' symbolicname='" + bsn + "' version='" + version + "' uri='" + bsn + "-" + version + ".jar'></resource>";
     }
+
+    private volatile HttpService m_http;
+    private volatile AgentUpdateOBRServlet m_servlet;
+
+    public void testAgentUpdate() throws Exception {
+        final int defaultTimeout = 150;
+
+        CountDownLatch latch;
+
+        latch = m_servlet.setPhase(Phase.CORRUPT_STREAM, new CountDownLatch(1));
+        assertTrue("Timed out while recovering from update with broken stream.", latch.await(defaultTimeout, TimeUnit.SECONDS));
+
+        latch = m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_RESOLVE, new CountDownLatch(1));
+        assertTrue("Timed out while recovering from update with agent that does not resolve.", latch.await(defaultTimeout, TimeUnit.SECONDS));
+
+        latch = m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_START, new CountDownLatch(1));
+        assertTrue("Timed out while recovering from update with agent that does not start.", latch.await(defaultTimeout, TimeUnit.SECONDS));
+
+        latch = m_servlet.setPhase(Phase.BUNDLE_WORKS, new CountDownLatch(1));
+        assertTrue("Timed out while starting working bundle?!", latch.await(defaultTimeout, TimeUnit.SECONDS));
+
+        int timeout = defaultTimeout;
+        while (timeout-- > 0) {
+            Thread.sleep(200);
+            for (Bundle b : m_bundleContext.getBundles()) {
+                if ("org.apache.ace.agent".equals(b.getSymbolicName())) {
+                    if (b.getVersion().equals(new Version("2.0.0"))) {
+                        return;
+                    }
+                }
+            }
+        }
+        fail("Timed out waiting for update with new agent.");
+    }
+
+    @Override
+    protected void configureProvisionedServices() throws Exception {
+        String serverURL = String.format("http://localhost:%d/", TestConstants.PORT);
+        String obrURL = serverURL.concat("obr/");
+        configure("org.apache.ace.deployment.servlet.agent",
+            "org.apache.ace.server.servlet.endpoint", "/agent",
+            "obr.url", obrURL,
+            "authentication.enabled", "false");
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put(AgentConstants.CONFIG_DISCOVERY_SERVERURLS, serverURL);
+
+        AgentControl agentControl = getService(AgentControl.class);
+        agentControl.getConfigurationHandler().putAll(props);
+    }
+
+    @Override
+    protected void configureAdditionalServices() throws Exception {
+        m_servlet = new AgentUpdateOBRServlet();
+        m_http.registerServlet("/obr", m_servlet, null, null);
+        
+        m_http.registerServlet("/auditlog", new DummyAuditLogServlet(), null, null);
+    }
+
+    @Override
+    protected void doTearDown() throws Exception {
+        m_http.unregister("/obr");
+        m_http.unregister("/auditlog");
+    }
+
+    @Override
+    protected Component[] getDependencies() {
+        return new Component[] {
+            createComponent()
+                .setImplementation(this)
+                .add(createServiceDependency().setService(HttpService.class).setRequired(true))
+        };
+    }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java Thu Oct 10 14:11:13 2013
@@ -134,7 +134,6 @@ public class DiscoveryHandlerImpl extend
      */
     @Override
     public URL getServerUrl() {
-
         List<String> serverURLs = m_serverURLs; // local reference
         boolean checkURLs = m_checkURLs; // local value
 

Modified: ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/AuthenticationTestBase.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/AuthenticationTestBase.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/AuthenticationTestBase.java (original)
+++ ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/AuthenticationTestBase.java Thu Oct 10 14:11:13 2013
@@ -23,7 +23,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
-import java.net.URLConnection;
 import java.util.Date;
 import java.util.Enumeration;
 
@@ -46,7 +45,7 @@ public class AuthenticationTestBase exte
         System.out.println("Log:");
         while (e.hasMoreElements()) {
             LogEntry entry = (LogEntry) e.nextElement();
-            System.out.println(" * " + (new Date(entry.getTime())) + " - " + entry.getMessage() + " - " + entry.getBundle().getBundleId() + " - " + entry.getException());
+            System.out.println(" * " + (new Date(entry.getTime())) + " - " + entry.getMessage() + " - " + entry.getBundle().getBundleId());
             if (entry.getException() != null) {
                 entry.getException().printStackTrace();
             }
@@ -93,26 +92,22 @@ public class AuthenticationTestBase exte
     protected final boolean waitForURL(ConnectionFactory connectionFactory, URL url, int responseCode, int timeout) {
         long deadline = System.currentTimeMillis() + timeout;
         while (System.currentTimeMillis() < deadline) {
+            HttpURLConnection connection = null;
             try {
-                URLConnection connection = connectionFactory.createConnection(url);
+                connection = (HttpURLConnection) connectionFactory.createConnection(url);
 
-                connection.connect();
-
-                if (connection instanceof HttpURLConnection) {
-                    int respCode = ((HttpURLConnection) connection).getResponseCode();
-                    if (respCode == responseCode) {
-                        return true;
-                    }
-                    else {
-                        System.err.println("Got response code " + respCode + " for " + url);
-                    }
+                int respCode = ((HttpURLConnection) connection).getResponseCode();
+                if (respCode == responseCode) {
+                    return true;
+                }
+                else {
+                    System.err.println("Got response code " + respCode + " for " + url);
                 }
-            }
-            catch (ClassCastException cce) {
-                throw new IllegalArgumentException("Expected url to be an HTTP url, not: " + url.toString(), cce);
             }
             catch (IOException ioe) {
-                // retry
+                if (connection != null) {
+                    connection.disconnect();
+                }
             }
             try {
                 Thread.sleep(100);

Modified: ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/ObrAuthenticationTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/ObrAuthenticationTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/ObrAuthenticationTest.java (original)
+++ ace/trunk/org.apache.ace.authentication.itest/src/org/apache/ace/it/authentication/ObrAuthenticationTest.java Thu Oct 10 14:11:13 2013
@@ -63,6 +63,8 @@ public class ObrAuthenticationTest exten
     private volatile ConnectionFactory m_connectionFactory;
     private volatile LogReaderService m_logReader;
 
+    private URL m_obrURL;
+
     @Override
     protected Component[] getDependencies() {
         return new Component[] {
@@ -107,6 +109,10 @@ public class ObrAuthenticationTest exten
             "org.apache.ace.server.servlet.endpoint", m_endpoint,
             "authentication.enabled", "true");
 
+        m_obrURL = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/");
+
+        configure("org.apache.ace.client.repository", "obrlocation", m_obrURL.toExternalForm());
+
         configure("org.apache.ace.obr.storage.file",
             "OBRInstance", "singleOBRStore",
             OBRFileStoreConstants.FILE_LOCATION_KEY, fileLocation);
@@ -120,15 +126,12 @@ public class ObrAuthenticationTest exten
             importSingleUser(m_userRepository, userName, password);
             waitForUser(m_userAdmin, userName);
 
-            URL obrURL = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/");
-            m_artifactRepository.setObrBase(obrURL);
-
-            URL testURL = new URL(obrURL, "repository.xml");
+            URL testURL = new URL(m_obrURL, "repository.xml");
 
             assertTrue("Failed to access OBR in time!", waitForURL(m_connectionFactory, testURL, 401, 15000));
 
             m_authConfigPID = configureFactory("org.apache.ace.connectionfactory",
-                "authentication.baseURL", obrURL.toExternalForm(),
+                "authentication.baseURL", m_obrURL.toExternalForm(),
                 "authentication.type", "basic",
                 "authentication.user.name", userName,
                 "authentication.user.password", password);

Modified: ace/trunk/org.apache.ace.client.repository.itest/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository.itest/bnd.bnd?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.client.repository.itest/bnd.bnd Thu Oct 10 14:11:13 2013
@@ -73,7 +73,12 @@ Test-Cases: ${classes;CONCRETE;EXTENDS;o
 	org.apache.felix.gogo.runtime,\
 	org.apache.felix.gogo.shell,\
 	org.apache.ace.feedback.common;version=latest
--runproperties: org.apache.felix.eventadmin.Timeout=0
+-runproperties: \
+	org.apache.felix.eventadmin.Timeout=0,\
+	org.apache.felix.log.storeDebug=true,\
+    org.apache.felix.log.maxSize=-1,\
+    org.osgi.framework.bootdelegation="com.yourkit.*,com.sun.*,sun.*,apple.*,com.apple.*"
+
 Private-Package: org.apache.ace.it.repositoryadmin
 Bundle-Version: 1.0.0
 Bundle-Name: Apache ACE Client Repository itest

Modified: ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/BaseRepositoryAdminTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/BaseRepositoryAdminTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/BaseRepositoryAdminTest.java (original)
+++ ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/BaseRepositoryAdminTest.java Thu Oct 10 14:11:13 2013
@@ -18,23 +18,18 @@
  */
 package org.apache.ace.it.repositoryadmin;
 
-import static org.apache.ace.client.repository.RepositoryObject.PRIVATE_TOPIC_ROOT;
-import static org.apache.ace.client.repository.RepositoryObject.PUBLIC_TOPIC_ROOT;
-import static org.apache.ace.client.repository.stateful.StatefulTargetObject.TOPIC_ALL;
-
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
@@ -64,6 +59,7 @@ import org.apache.ace.repository.Reposit
 import org.apache.ace.repository.impl.constants.RepositoryConstants;
 import org.apache.ace.test.constants.TestConstants;
 import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentStateListener;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
@@ -76,9 +72,9 @@ import org.osgi.service.http.HttpService
 import org.osgi.service.useradmin.User;
 import org.osgi.util.tracker.ServiceTracker;
 
-public abstract class BaseRepositoryAdminTest extends IntegrationTestBase implements EventHandler {
+public abstract class BaseRepositoryAdminTest extends IntegrationTestBase {
 
-	final class MockUser implements User {
+    final class MockUser implements User {
         private final String m_name;
 
         public MockUser() {
@@ -109,58 +105,45 @@ public abstract class BaseRepositoryAdmi
     protected static final String ENDPOINT_NAME = "/AdminRepTest";
     protected static final String HOST = "http://localhost:" + TestConstants.PORT;
 
-    protected volatile ConfigurationAdmin m_configAdmin; /* Injected by dependency manager */
-    protected volatile RepositoryAdmin m_repositoryAdmin; /* Injected by dependency manager */
-    protected volatile ArtifactRepository m_artifactRepository; /* Injected by dependency manager */
-    protected volatile Artifact2FeatureAssociationRepository m_artifact2featureRepository; /* Injected by dependency manager */
-    protected volatile FeatureRepository m_featureRepository; /* Injected by dependency manager */
-    protected volatile Feature2DistributionAssociationRepository m_feature2distributionRepository; /* Injected by dependency manager */
-    protected volatile DistributionRepository m_distributionRepository; /* Injected by dependency manager */
-    protected volatile Distribution2TargetAssociationRepository m_distribution2targetRepository; /* Injected by dependency manager */
-    protected volatile TargetRepository m_targetRepository; /* Injected by dependency manager */
-    protected volatile DeploymentVersionRepository m_deploymentVersionRepository; /* Injected by dependency manager */
-    protected volatile StatefulTargetRepository m_statefulTargetRepository; /* Injected by dependency manager */
-    protected volatile LogStore m_auditLogStore; /* Injected by dependency manager */
-    protected volatile List<String> m_waitingForTopic = Collections.synchronizedList(new ArrayList<String>());
-    protected volatile Semaphore m_semaphore;
-    
     protected URL m_endpoint;
-    
-    private volatile boolean m_runAndWaitDebug = false;
+    protected URL m_obrURL;
+
+    /* All injected by dependency manager */
+    protected volatile ConfigurationAdmin m_configAdmin;
+    protected volatile RepositoryAdmin m_repositoryAdmin;
+    protected volatile ArtifactRepository m_artifactRepository;
+    protected volatile Artifact2FeatureAssociationRepository m_artifact2featureRepository;
+    protected volatile FeatureRepository m_featureRepository;
+    protected volatile Feature2DistributionAssociationRepository m_feature2distributionRepository;
+    protected volatile DistributionRepository m_distributionRepository;
+    protected volatile Distribution2TargetAssociationRepository m_distribution2targetRepository;
+    protected volatile TargetRepository m_targetRepository;
+    protected volatile DeploymentVersionRepository m_deploymentVersionRepository;
+    protected volatile StatefulTargetRepository m_statefulTargetRepository;
+    protected volatile LogStore m_auditLogStore;
 
-    public void handleEvent(Event event) {
-        if (m_runAndWaitDebug) {
-            System.err.println("Received event: " + event.getTopic());
-        }
-        if (m_waitingForTopic.remove(event.getTopic())) {
-            if (m_runAndWaitDebug) {
-                System.err.println("Event was expected.");
-            }
-            if ((m_semaphore != null) && m_waitingForTopic.isEmpty()) {
-                m_semaphore.release();
-                m_runAndWaitDebug = false;
-            }
-        }
-    }
-    
     protected final void addObr(String endpoint, String fileLocation) throws IOException, InterruptedException {
+        String baseURL = String.format("http://localhost:%d%s/", TestConstants.PORT, endpoint);
+
+        m_obrURL = new URL(baseURL);
+
+        configure("org.apache.ace.client.repository", "obrlocation", m_obrURL.toExternalForm());
         configure("org.apache.ace.obr.servlet", "OBRInstance", "singleOBRServlet", "org.apache.ace.server.servlet.endpoint", endpoint, "authentication.enabled", "false");
         configure("org.apache.ace.obr.storage.file", "OBRInstance", "singleOBRStore", OBRFileStoreConstants.FILE_LOCATION_KEY, fileLocation);
 
         // Wait for the endpoint to respond.
-        // TODO below there is a similar url that does put a slash between port and endpoint, why?
-        URL url = new URL("http://localhost:" + TestConstants.PORT + endpoint + "/repository.xml");
-        int response = ((HttpURLConnection) url.openConnection()).getResponseCode();
+        URL repoURL = new URL(baseURL + "repository.xml");
+        int response = ((HttpURLConnection) repoURL.openConnection()).getResponseCode();
         int tries = 0;
         while ((response != 200) && (tries++ < 50)) {
-            response = ((HttpURLConnection) url.openConnection()).getResponseCode();
+            response = ((HttpURLConnection) repoURL.openConnection()).getResponseCode();
             Thread.sleep(100); // If we get interrupted, there will be a good reason for it.
         }
         if (tries == 50) {
             throw new IOException("The OBR servlet does not seem to be responding well. Last response code: " + response);
         }
     }
-    
+
     /* Configure a new repository instance */
     protected final void addRepository(String instanceName, String customer, String name, boolean isMaster) throws IOException,
         InterruptedException, InvalidSyntaxException {
@@ -185,16 +168,17 @@ public abstract class BaseRepositoryAdmi
     }
 
     @Override
-	protected void configureAdditionalServices() throws Exception {
+    protected void configureAdditionalServices() throws Exception {
         // remove all repositories, in case a test case does not reach it's cleanup section due to an exception
         removeAllRepositories();
     }
 
     @Override
-	protected void configureProvisionedServices() throws Exception {
+    protected void configureProvisionedServices() throws Exception {
         m_endpoint = new URL(HOST + ENDPOINT_NAME);
 
         getService(SessionFactory.class).createSession("test-session-ID", null);
+
         configureFactory("org.apache.ace.log.server.store.factory",
             "name", "auditlog", "authentication.enabled", "false");
     }
@@ -216,10 +200,10 @@ public abstract class BaseRepositoryAdmi
             m_repositoryAdmin.logout(true);
         }
         catch (Exception ioe) {
-//            ioe.printStackTrace(System.out);
+            // ioe.printStackTrace(System.out);
         }
     }
-    
+
     protected ArtifactObject createBasicArtifactObject(String name, String mimetype, String processorPID)
         throws InterruptedException {
         Map<String, String> attr = new HashMap<String, String>();
@@ -239,7 +223,7 @@ public abstract class BaseRepositoryAdmi
     protected ArtifactObject createBasicBundleObject(String symbolicName, String version, String processorPID) {
         return createBasicBundleObject(symbolicName, version, processorPID, null);
     }
-    
+
     protected ArtifactObject createBasicBundleObject(String symbolicName, String version, String processorPID, String size) {
         Map<String, String> attr = new HashMap<String, String>();
         attr.put(BundleHelper.KEY_SYMBOLICNAME, symbolicName);
@@ -291,6 +275,7 @@ public abstract class BaseRepositoryAdmi
         Properties propsServlet = new Properties();
         propsServlet.put(HttpConstants.ENDPOINT, endpoint + "invalid");
         propsServlet.put("OBRInstance", "singleOBRServlet");
+        propsServlet.put("authentication.enabled", "false");
         Configuration configServlet = m_configAdmin.getConfiguration("org.apache.ace.obr.servlet");
         configServlet.update(propsServlet);
 
@@ -308,15 +293,8 @@ public abstract class BaseRepositoryAdmi
     }
 
     protected Component[] getDependencies() {
-        Dictionary<String, Object> topics = new Hashtable<String, Object>();
-        topics.put(EventConstants.EVENT_TOPIC, new String[] { PUBLIC_TOPIC_ROOT + "*",
-            PRIVATE_TOPIC_ROOT + "*",
-            RepositoryAdmin.PUBLIC_TOPIC_ROOT + "*",
-            RepositoryAdmin.PRIVATE_TOPIC_ROOT + "*",
-            TOPIC_ALL });
         return new Component[] {
             createComponent()
-                .setInterface(EventHandler.class.getName(), topics)
                 .setImplementation(this)
                 .add(createServiceDependency().setService(HttpService.class).setRequired(true))
                 .add(createServiceDependency().setService(RepositoryAdmin.class).setRequired(true))
@@ -334,18 +312,69 @@ public abstract class BaseRepositoryAdmi
         };
     }
 
-    protected <T> T runAndWaitForEvent(Callable<T> callable, boolean debug, String... topic) throws Exception {
-        m_runAndWaitDebug = debug;
-        T result = null;
-        m_waitingForTopic.clear();
-        m_waitingForTopic.addAll(Arrays.asList(topic));
-        m_semaphore = new Semaphore(0);
-        result = callable.call();
-        assertTrue("We expect the event within a reasonable timeout.", m_semaphore.tryAcquire(15000, TimeUnit.MILLISECONDS));
-        m_semaphore = null;
-        return result;
+    protected <T> T runAndWaitForEvent(Callable<T> callable, final boolean debug, final String... topicList) throws Exception {
+        Dictionary<String, Object> topics = new Hashtable<String, Object>();
+        topics.put(EventConstants.EVENT_TOPIC, topicList);
+
+        final CopyOnWriteArrayList<String> waitingForTopic = new CopyOnWriteArrayList<String>(Arrays.asList(topicList));
+        final CountDownLatch topicLatch = new CountDownLatch(topicList.length);
+        final CountDownLatch startLatch = new CountDownLatch(1);
+
+        Component comp = m_dependencyManager.createComponent()
+            .setInterface(EventHandler.class.getName(), topics)
+            .setImplementation(new EventHandler() {
+                @Override
+                public void handleEvent(Event event) {
+                    if (debug) {
+                        System.err.println("Received event: " + event.getTopic());
+                    }
+                    if (waitingForTopic.remove(event.getTopic())) {
+                        if (debug) {
+                            System.err.println("Event was expected.");
+                        }
+                        topicLatch.countDown();
+                    }
+                }
+            });
+        comp.addStateListener(new ComponentStateListener() {
+            public void stopping(Component comp) {
+            }
+
+            public void stopped(Component comp) {
+            }
+
+            public void starting(Component comp) {
+            }
+
+            public void started(Component comp) {
+                startLatch.countDown();
+            }
+        });
+
+        if (debug) {
+            System.err.printf("Waiting for events: %s.%n", Arrays.toString(topicList));
+        }
+
+        m_dependencyManager.add(comp);
+
+        try {
+            assertTrue(startLatch.await(1500, TimeUnit.MILLISECONDS));
+
+            T result = callable.call();
+
+            boolean r = topicLatch.await(15000, TimeUnit.MILLISECONDS);
+            if (!r && debug) {
+                System.err.println("EVENT NOTIFICATION FAILED!!!");
+            }
+            assertTrue("We expect the event within a reasonable timeout.", r);
+
+            return result;
+        }
+        finally {
+            m_dependencyManager.remove(comp);
+        }
     }
-    
+
     protected void startRepositoryService() throws IOException {
         // configure the (replication)repository servlets
         configure("org.apache.ace.repository.servlet.RepositoryServlet", HttpConstants.ENDPOINT,
@@ -354,32 +383,36 @@ public abstract class BaseRepositoryAdmi
 
     @Override
     protected void doTearDown() throws Exception {
-    	try {
-			m_repositoryAdmin.logout(true);
-		} catch (RuntimeException e) {
-			// Ignore...
-		}
-
-    	try {
-			cleanUp();
-		} catch (Exception e) {
-			// Ignore...
-		}
-    	
-    	try {
-			removeAllRepositories();
-		} catch (IOException e) {
-			// Ignore...
-		}
+        try {
+            m_repositoryAdmin.logout(true);
+        }
+        catch (RuntimeException e) {
+            // Ignore...
+        }
+
+        try {
+            cleanUp();
+        }
+        catch (Exception e) {
+            // Ignore...
+        }
+
+        try {
+            removeAllRepositories();
+        }
+        catch (IOException e) {
+            // Ignore...
+        }
     }
 
     private <T extends RepositoryObject> void clearRepository(ObjectRepository<T> rep) {
         for (T entity : rep.get()) {
             try {
-				rep.remove(entity);
-			} catch (RuntimeException e) {
-				// Ignore; try to recover...
-			}
+                rep.remove(entity);
+            }
+            catch (RuntimeException e) {
+                // Ignore; try to recover...
+            }
         }
         assertEquals("Something went wrong clearing the repository.", 0, rep.get().size());
     }
@@ -387,10 +420,11 @@ public abstract class BaseRepositoryAdmi
     private void clearResourceProcessors(ArtifactRepository rep) {
         for (ArtifactObject entity : rep.getResourceProcessors()) {
             try {
-				rep.remove(entity);
-			} catch (RuntimeException e) {
-				// Ignore; try to recover...
-			}
+                rep.remove(entity);
+            }
+            catch (RuntimeException e) {
+                // Ignore; try to recover...
+            }
         }
         assertEquals("Something went wrong clearing the repository.", 0, rep.get().size());
     }

Modified: ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/RepositoryAdminTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/RepositoryAdminTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/RepositoryAdminTest.java (original)
+++ ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/RepositoryAdminTest.java Thu Oct 10 14:11:13 2013
@@ -55,7 +55,7 @@ public class RepositoryAdminTest extends
     public void testAssociationsWithMovingEndpoints() throws Exception {
         final ArtifactObject b1 = createBasicBundleObject("thebundle", "1", null);
         final FeatureObject g1 = createBasicFeatureObject("thefeature");
-        
+
         final Artifact2FeatureAssociation bg = runAndWaitForEvent(new Callable<Artifact2FeatureAssociation>() {
             public Artifact2FeatureAssociation call() throws Exception {
                 Map<String, String> properties = new HashMap<String, String>();
@@ -152,7 +152,7 @@ public class RepositoryAdminTest extends
                 .setLocation(m_endpoint).setCustomer("apache").setName("deployment").setWriteable());
 
         m_repositoryAdmin.login(loginContext);
-        
+
         m_repositoryAdmin.checkout();
 
         runAndWaitForEvent(new Callable<Object>() {
@@ -188,14 +188,14 @@ public class RepositoryAdminTest extends
         assertTrue("Turning on the autoapprove should not automatically approve whatever was waiting.", sgo.needsApprove());
 
         sgo.approve();
-        
+
         runAndWaitForEvent(new Callable<Void>() {
             public Void call() throws Exception {
                 m_repositoryAdmin.commit();
                 return null;
             }
-        }, false, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED);        
-        
+        }, false, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED);
+
         assertFalse("We approved the new version by hand, so we should not need approval.", sgo.needsApprove());
 
         runAndWaitForEvent(new Callable<Object>() {
@@ -212,8 +212,8 @@ public class RepositoryAdminTest extends
                 m_repositoryAdmin.commit();
                 return null;
             }
-        }, false, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED);           
-        
+        }, false, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED);
+
         assertFalse("With autoapprove on, adding new deployment information should still not need approval (at least, after the two CHANGED events).", sgo.needsApprove());
 
         runAndWaitForEvent(new Callable<Object>() {
@@ -270,7 +270,6 @@ public class RepositoryAdminTest extends
 
         // Supply the OBR.
         addObr("/obr", "store");
-        m_artifactRepository.setObrBase(new URL(HOST + "/obr/"));
 
         m_artifactRepository.importArtifact(temp.toURI().toURL(), true);
 
@@ -345,8 +344,8 @@ public class RepositoryAdminTest extends
     }
 
     /**
-     * Tests read only repository access: marking a repository as readonly for a login should
-     * mean that it does not get committed, but local changes will stay around between logins.
+     * Tests read only repository access: marking a repository as readonly for a login should mean that it does not get
+     * committed, but local changes will stay around between logins.
      */
     public void testReadOnlyRepositoryAccess() throws Exception {
         User user1 = new MockUser();
@@ -441,8 +440,7 @@ public class RepositoryAdminTest extends
     }
 
     /**
-     * Tests the behavior with logging in and out (with multiple users), and communication
-     * with the server.
+     * Tests the behavior with logging in and out (with multiple users), and communication with the server.
      * 
      * @throws Exception
      */

Modified: ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/TemplateProcessorTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/TemplateProcessorTest.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/TemplateProcessorTest.java (original)
+++ ace/trunk/org.apache.ace.client.repository.itest/src/org/apache/ace/it/repositoryadmin/TemplateProcessorTest.java Thu Oct 10 14:11:13 2013
@@ -50,7 +50,6 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.TargetObject;
 import org.apache.ace.client.repository.stateful.StatefulTargetObject;
 import org.apache.ace.client.repository.stateful.StatefulTargetObject.StoreState;
-import org.apache.ace.test.constants.TestConstants;
 import org.apache.felix.dm.Component;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.useradmin.User;
@@ -180,7 +179,7 @@ public class TemplateProcessorTest exten
                 m_repositoryAdmin.commit();
                 return null;
             }
-        }, true, TOPIC_STATUS_CHANGED);
+        }, false, TOPIC_STATUS_CHANGED);
         
         assertEquals("Store state for target should still be new, because the resource processor is missing.", StoreState.New, sgo.getStoreState());
         
@@ -258,7 +257,6 @@ public class TemplateProcessorTest exten
         setupRepository();
         
         addObr("/obr", "store");
-        m_artifactRepository.setObrBase(new URL("http://localhost:" + TestConstants.PORT + "/obr/"));
 
         // create some template things
         String xmlHeader =

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/RepositoryAdminLoginContext.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/RepositoryAdminLoginContext.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/RepositoryAdminLoginContext.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/RepositoryAdminLoginContext.java Thu Oct 10 14:11:13 2013
@@ -97,12 +97,4 @@ public interface RepositoryAdminLoginCon
      * @return this context, never <code>null</code>.
      */
     public RepositoryAdminLoginContext add(BaseRepositoryContext<?> repositoryContext);
-
-    /**
-     * When uploads are needed, this is the base OBR that will be used.
-     * 
-     * @param base The URL of the OBR to be used.
-     * @return this object, to allow chaining.
-     */
-    public RepositoryAdminLoginContext setObrBase(URL base);
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java Thu Oct 10 14:11:13 2013
@@ -40,6 +40,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.TargetObject;
 import org.apache.ace.client.repository.repository.ArtifactRepository;
 import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.apache.ace.client.repository.repository.TargetRepository;
 import org.apache.ace.client.repository.stateful.StatefulTargetRepository;
 import org.apache.ace.client.repository.stateful.impl.StatefulTargetRepositoryImpl;
@@ -59,49 +60,53 @@ import org.osgi.service.log.LogService;
 import org.osgi.service.prefs.PreferencesService;
 
 /**
- * Activator for the RepositoryAdmin bundle. Creates the repository admin, which internally
- * creates all required repositories.
+ * Activator for the RepositoryAdmin bundle. Creates the repository admin, which internally creates all required
+ * repositories.
  */
 public class Activator extends DependencyActivatorBase implements SessionFactory, ManagedService {
-	private static final String PID = "org.apache.ace.client.repository";
-    private static final String KEY_SHOWUNREGISTEREDTARGETS = "showunregisteredtargets";
-	private final Map<String, SessionData> m_sessions = new HashMap<String, SessionData>();
-    private volatile DependencyManager m_dependencyManager;
-	private boolean m_showUnregisteredTargets;
+    /**
+     * Small container that keeps the session-related services for us.
+     */
+    private static final class SessionData {
+        private final List<Component> m_services = new ArrayList<Component>();
 
-    @Override
-    public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
-        m_dependencyManager = manager;
-        
-        Properties props = new Properties();
-        props.put(Constants.SERVICE_PID, PID);
-        props.put(CommandProcessor.COMMAND_SCOPE, "clientrepo");
-        props.put(CommandProcessor.COMMAND_FUNCTION, new String[] { "sessions" });
-        
-        manager.add(createComponent()
-            .setInterface(new String[] { SessionFactory.class.getName(), ManagedService.class.getName() }, props)
-            .setImplementation(this)
-        );
-    }
+        final void addComponents(DependencyManager manager, Component... comps) {
+            synchronized (m_services) {
+                for (Component c : comps) {
+                    m_services.add(c);
+                }
+            }
 
-    /** Shell command to show the active sessions. */
-    public void sessions() {
-        synchronized (m_sessions) {
-        	if (m_sessions.isEmpty()) {
-        		System.out.println("No sessions.");
-        	}
-        	else {
-        		System.out.println("Sessions:");
-        		for (Entry<String, SessionData> session : m_sessions.entrySet()) {
-        			System.out.println(" * " + session.getKey());
-        		}
-        	}
+            for (Component c : comps) {
+                manager.add(c);
+            }
+        }
+
+        final boolean isEmpty() {
+            synchronized (m_services) {
+                return m_services.isEmpty();
+            }
+        }
+
+        final void removeAllComponents(DependencyManager manager) {
+            Component[] comps;
+            synchronized (m_services) {
+                comps = m_services.toArray(new Component[m_services.size()]);
+                m_services.clear();
+            }
+
+            for (Component c : comps) {
+                manager.remove(c);
+            }
         }
     }
-    
-    @Override
-    public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
-    }
+
+    private static final String PID = "org.apache.ace.client.repository";
+
+    private final Map<String, SessionData> m_sessions = new HashMap<String, SessionData>();
+    private final RepositoryConfigurationImpl m_repoConfiguration = new RepositoryConfigurationImpl();
+
+    private volatile DependencyManager m_dependencyManager;
 
     public void createSession(String sessionID, Map sessionConfiguration) {
         SessionData sessionData = null;
@@ -111,19 +116,17 @@ public class Activator extends Dependenc
                 m_sessions.put(sessionID, sessionData);
             }
         }
-        
-        boolean showUnregisteredTargets = m_showUnregisteredTargets;
-        if (sessionConfiguration != null) {
-        	Object value = sessionConfiguration.get(KEY_SHOWUNREGISTEREDTARGETS);
-        	showUnregisteredTargets = parseBoolean(value, m_showUnregisteredTargets);
-        }
 
         // Allow session to be created outside the lock; to avoid potential deadlocks...
         if (sessionData != null) {
-            createSessionServices(sessionData, sessionID, showUnregisteredTargets);
+            createSessionServices(sessionData, sessionID, getConfiguration(sessionConfiguration));
         }
     }
 
+    @Override
+    public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+    }
+
     public void destroySession(String sessionID) {
         SessionData sessionData = null;
         synchronized (m_sessions) {
@@ -135,16 +138,53 @@ public class Activator extends Dependenc
             destroySessionServices(sessionData, sessionID);
         }
     }
-    
+
+    @Override
+    public void init(BundleContext context, DependencyManager manager) throws Exception {
+        m_dependencyManager = manager;
+
+        Properties props = new Properties();
+        props.put(Constants.SERVICE_PID, PID);
+        props.put(CommandProcessor.COMMAND_SCOPE, "clientrepo");
+        props.put(CommandProcessor.COMMAND_FUNCTION, new String[] { "sessions" });
+
+        manager.add(createComponent()
+            .setInterface(new String[] { SessionFactory.class.getName(), ManagedService.class.getName() }, props)
+            .setImplementation(this)
+            );
+    }
+
+    /** Shell command to show the active sessions. */
+    public void sessions() {
+        synchronized (m_sessions) {
+            if (m_sessions.isEmpty()) {
+                System.out.println("No sessions.");
+            }
+            else {
+                System.out.println("Sessions:");
+                for (Entry<String, SessionData> session : m_sessions.entrySet()) {
+                    System.out.println(" * " + session.getKey());
+                }
+            }
+        }
+    }
+
+    @Override
+    public void updated(Dictionary properties) throws ConfigurationException {
+        m_repoConfiguration.update(properties);
+    }
+
     /**
      * Creates all necessary session-related service for the given session.
      * 
-     * @param sd the session data to keep the session-related services;
-     * @param sessionID the session ID to use.
+     * @param sd
+     *            the session data to keep the session-related services;
+     * @param sessionID
+     *            the session ID to use.
      */
     @SuppressWarnings("unchecked")
-    private void createSessionServices(SessionData sd, String sessionID, boolean showUnregisteredTargets) {
-        RepositoryAdminImpl rai = new RepositoryAdminImpl(sessionID);
+    private void createSessionServices(SessionData sd, String sessionID, RepositoryConfiguration repoConfig) {
+        RepositoryAdminImpl rai = new RepositoryAdminImpl(sessionID, repoConfig);
         Component repositoryAdminComponent = createComponent()
             .setInterface(RepositoryAdmin.class.getName(), rai.getSessionProps())
             .setImplementation(rai)
@@ -168,12 +208,12 @@ public class Activator extends Dependenc
             Distribution2TargetAssociation.PRIVATE_TOPIC_ALL,
             TargetObject.PRIVATE_TOPIC_ALL,
             DeploymentVersionObject.PRIVATE_TOPIC_ALL,
-            RepositoryAdmin.PRIVATE_TOPIC_HOLDUNTILREFRESH, 
-            RepositoryAdmin.PRIVATE_TOPIC_REFRESH, 
-            RepositoryAdmin.PRIVATE_TOPIC_LOGIN 
+            RepositoryAdmin.PRIVATE_TOPIC_HOLDUNTILREFRESH,
+            RepositoryAdmin.PRIVATE_TOPIC_REFRESH,
+            RepositoryAdmin.PRIVATE_TOPIC_LOGIN
         });
-        
-        StatefulTargetRepositoryImpl statefulTargetRepositoryImpl = new StatefulTargetRepositoryImpl(sessionID, showUnregisteredTargets);
+
+        StatefulTargetRepositoryImpl statefulTargetRepositoryImpl = new StatefulTargetRepositoryImpl(sessionID, repoConfig);
         Component statefulTargetRepositoryComponent = createComponent()
             .setInterface(new String[] { StatefulTargetRepository.class.getName(), EventHandler.class.getName() }, topic)
             .setImplementation(statefulTargetRepositoryImpl)
@@ -184,7 +224,7 @@ public class Activator extends Dependenc
             .add(createServiceDependency().setService(BundleHelper.class).setRequired(true))
             .add(createServiceDependency().setService(EventAdmin.class).setRequired(true))
             .add(createServiceDependency().setService(LogService.class).setRequired(false));
-        
+
         rai.addPreCommitMember(statefulTargetRepositoryImpl);
 
         // Publish our components to our session data for later use...
@@ -194,69 +234,29 @@ public class Activator extends Dependenc
     /**
      * Removes the session-related services from the session.
      * 
-     * @param sd the session data that keeps the session-related services;
-     * @param sessionID the session ID to use.
+     * @param sd
+     *            the session data that keeps the session-related services;
+     * @param sessionID
+     *            the session ID to use.
      */
     private void destroySessionServices(SessionData sd, String sessionID) {
         sd.removeAllComponents(m_dependencyManager);
     }
 
     /**
-     * Small container that keeps the session-related services for us.
+     * Creates a copy of the repository configuration that is supposed to remain stable for the duration of a session,
+     * if there are settings overridden. If no settings are to be overridden, the current (mutable!) repository
+     * configuration is used.
+     * 
+     * @param sessionConfiguration
+     *            the session configuration overriding the current repository configuration values, can be
+     *            <code>null</code> to keep the current configuration as-is.
+     * @return a new {@link RepositoryConfiguration} instance, never <code>null</code>.
      */
-    private static final class SessionData {
-        private final List<Component> m_services = new ArrayList<Component>();
-
-        final void addComponents(DependencyManager manager, Component... comps) {
-            synchronized (m_services) {
-                for (Component c : comps) {
-                    m_services.add(c);
-                }
-            }
-
-            for (Component c : comps) {
-                manager.add(c);
-            }
-        }
-
-        final void removeAllComponents(DependencyManager manager) {
-            Component[] comps;
-            synchronized (m_services) {
-                comps = m_services.toArray(new Component[m_services.size()]);
-                m_services.clear();
-            }
-            
-            for (Component c : comps) {
-                manager.remove(c);
-            }
-        }
-        
-        final boolean isEmpty() {
-            synchronized (m_services) {
-                return m_services.isEmpty();
-            }
+    private RepositoryConfiguration getConfiguration(Map<String, Object> sessionConfiguration) {
+        if (sessionConfiguration != null) {
+            return new RepositoryConfigurationImpl(m_repoConfiguration, sessionConfiguration);
         }
+        return m_repoConfiguration;
     }
-
-	@Override
-	public void updated(Dictionary properties) throws ConfigurationException {
-		if (properties == null) {
-			// by default, we show unregistered targets
-			m_showUnregisteredTargets = true;
-		}
-		else {
-        	Object value = properties.get(KEY_SHOWUNREGISTEREDTARGETS);
-        	m_showUnregisteredTargets = parseBoolean(value, true);
-		}
-	}
-	
-	private boolean parseBoolean(Object value, boolean defaultValue) {
-    	if (value instanceof String) {
-    		return Boolean.parseBoolean((String) value);
-    	}
-    	else if (value instanceof Boolean) {
-    		return (Boolean) value;
-    	}
-    	return defaultValue;
-	}
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -24,6 +24,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.ArtifactObject;
 import org.apache.ace.client.repository.object.FeatureObject;
 import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.osgi.framework.InvalidSyntaxException;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -38,8 +39,8 @@ public class Artifact2FeatureAssociation
     private final ArtifactRepositoryImpl m_artifactRepository;
     private final FeatureRepositoryImpl m_featureRepository;
 
-    public Artifact2FeatureAssociationRepositoryImpl(ArtifactRepositoryImpl artifactRepository, FeatureRepositoryImpl featureRepository, ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public Artifact2FeatureAssociationRepositoryImpl(ArtifactRepositoryImpl artifactRepository, FeatureRepositoryImpl featureRepository, ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
         m_artifactRepository = artifactRepository;
         m_featureRepository = featureRepository;
     }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ArtifactRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ArtifactRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ArtifactRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ArtifactRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -40,6 +40,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.ArtifactObject;
 import org.apache.ace.client.repository.object.TargetObject;
 import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.apache.ace.connectionfactory.ConnectionFactory;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -69,10 +70,9 @@ public class ArtifactRepositoryImpl exte
     private volatile ConnectionFactory m_connectionFactory;
 
     private final Map<String, ArtifactHelper> m_helpers = new HashMap<String, ArtifactHelper>();
-    private URL m_obrBase;
 
-    public ArtifactRepositoryImpl(ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public ArtifactRepositoryImpl(ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
     }
 
     public List<ArtifactObject> getResourceProcessors() {
@@ -111,12 +111,6 @@ public class ArtifactRepositoryImpl exte
     }
 
     @Override
-    ArtifactObjectImpl createNewInhabitant(Map<String, String> attributes) {
-        ArtifactHelper helper = getHelper(attributes.get(ArtifactObject.KEY_MIMETYPE));
-        return new ArtifactObjectImpl(helper.checkAttributes(attributes), helper.getMandatoryAttributes(), this, this);
-    }
-
-    @Override
     ArtifactObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
         ArtifactHelper helper = getHelper(attributes.get(ArtifactObject.KEY_MIMETYPE));
         ArtifactObjectImpl ao = new ArtifactObjectImpl(helper.checkAttributes(attributes), helper.getMandatoryAttributes(), tags, this, this);
@@ -280,6 +274,13 @@ public class ArtifactRepositoryImpl exte
         }
     }
 
+    /**
+     * @return the OBR base URL to use, can be <code>null</code>.
+     */
+    public URL getObrBase() {
+        return getRepositoryConfiguration().getOBRLocation();
+    }
+
     public ArtifactObject importArtifact(URL artifact, boolean upload) throws IllegalArgumentException, IOException {
         try {
             if ((artifact == null) || (artifact.toString().length() == 0)) {
@@ -295,11 +296,11 @@ public class ArtifactRepositoryImpl exte
             return importArtifact(artifact, recognizer, helper, mimetype, false, upload);
         }
         catch (IllegalArgumentException iae) {
-            m_log.log(LogService.LOG_INFO, "Error importing artifact: " + iae.getMessage());
+            m_log.log(LogService.LOG_WARNING, "Error importing artifact: " + iae.getMessage(), iae);
             throw iae;
         }
         catch (IOException ioe) {
-            m_log.log(LogService.LOG_INFO, "Error storing artifact: " + ioe.getMessage());
+            m_log.log(LogService.LOG_WARNING, "Error storing artifact: " + ioe.getMessage(), ioe);
             throw ioe;
         }
     }
@@ -322,11 +323,11 @@ public class ArtifactRepositoryImpl exte
             return importArtifact(artifact, recognizer, helper, mimetype, true, upload);
         }
         catch (IllegalArgumentException iae) {
-            m_log.log(LogService.LOG_INFO, "Error importing artifact: " + iae.getMessage());
+            m_log.log(LogService.LOG_WARNING, "Error importing artifact: " + iae.getMessage(), iae);
             throw iae;
         }
         catch (IOException ioe) {
-            m_log.log(LogService.LOG_INFO, "Error storing artifact: " + ioe.getMessage());
+            m_log.log(LogService.LOG_WARNING, "Error storing artifact: " + ioe.getMessage(), ioe);
             throw ioe;
         }
     }
@@ -371,10 +372,12 @@ public class ArtifactRepositoryImpl exte
      */
 
     private void checkURL(URL artifact) throws IllegalArgumentException {
+        URLConnection connection = null;
         // First, check whether we can actually reach something from this URL.
         InputStream is = null;
         try {
-            is = openInputStream(artifact);
+            connection = m_connectionFactory.createConnection(artifact);
+            is = connection.getInputStream();
         }
         catch (IOException ioe) {
             throw new IllegalArgumentException("Artifact " + artifact + " does not point to a valid file.");
@@ -388,6 +391,9 @@ public class ArtifactRepositoryImpl exte
                     // Too bad, nothing to do.
                 }
             }
+            if (connection instanceof HttpURLConnection) {
+                ((HttpURLConnection) connection).disconnect();
+            }
         }
 
         // Then, check whether the name is legal.
@@ -413,48 +419,54 @@ public class ArtifactRepositoryImpl exte
      *             for any problem uploading the artifact.
      */
     private String upload(URL artifact, String filename, String mimetype) throws IOException {
-        if (m_obrBase == null) {
+        URL obrBase = getObrBase();
+        if (obrBase == null) {
             throw new IOException("There is no storage available for this artifact.");
         }
 
+        URLConnection inputConn = null;
+        URLConnection outputConn = null;
         InputStream input = null;
         OutputStream output = null;
-        URL url = m_obrBase;
+        URL url = obrBase;
         String location = null;
+
+        int blockSize = 8192;
+
         try {
-            input = openInputStream(artifact);
+            inputConn = m_connectionFactory.createConnection(artifact);
+            input = inputConn.getInputStream();
 
-            if(filename != null){
-                url = new URL(m_obrBase,"?filename=" + filename);
-            } 
-            URLConnection connection = m_connectionFactory.createConnection(url);
-
-            connection.setDoOutput(true);
-            connection.setDoInput(true);
-            connection.setUseCaches(false);
+            if (filename != null) {
+                url = new URL(obrBase, "?filename=" + filename);
+            }
 
-            connection.setRequestProperty("Content-Type", mimetype);
-            if (connection instanceof HttpURLConnection) {
+            outputConn = m_connectionFactory.createConnection(url);
+            outputConn.setDoOutput(true);
+            outputConn.setDoInput(true);
+            outputConn.setUseCaches(false);
+            outputConn.setRequestProperty("Content-Type", mimetype);
+            if (outputConn instanceof HttpURLConnection) {
                 // ACE-294: enable streaming mode causing only small amounts of memory to be
                 // used for this commit. Otherwise, the entire input stream is cached into
                 // memory prior to sending it to the server...
-                ((HttpURLConnection) connection).setChunkedStreamingMode(8192);
+                ((HttpURLConnection) outputConn).setChunkedStreamingMode(blockSize);
             }
 
-            output = connection.getOutputStream();
+            output = outputConn.getOutputStream();
 
-            byte[] buffer = new byte[4 * 1024];
+            byte[] buffer = new byte[blockSize];
             for (int count = input.read(buffer); count != -1; count = input.read(buffer)) {
                 output.write(buffer, 0, count);
             }
 
             output.close();
 
-            if (connection instanceof HttpURLConnection) {
-                int responseCode = ((HttpURLConnection) connection).getResponseCode();
+            if (outputConn instanceof HttpURLConnection) {
+                int responseCode = ((HttpURLConnection) outputConn).getResponseCode();
                 switch (responseCode) {
                     case HttpURLConnection.HTTP_CREATED:
-                        location = connection.getHeaderField("Location");
+                        location = outputConn.getHeaderField("Location");
                         break;
                     case HttpURLConnection.HTTP_CONFLICT:
                         throw new IOException("Artifact already exists in storage.");
@@ -466,7 +478,7 @@ public class ArtifactRepositoryImpl exte
             }
         }
         catch (IOException ioe) {
-            throw new IOException("Error importing artifact " + artifact.toString() + ": " + ioe.getMessage());
+            throw new IOException("Error importing artifact " + artifact.toString() + ": " + ioe.getMessage(), ioe);
         }
         finally {
             if (input != null) {
@@ -477,6 +489,10 @@ public class ArtifactRepositoryImpl exte
                     // Not much we can do
                 }
             }
+            if (inputConn instanceof HttpURLConnection) {
+                ((HttpURLConnection) inputConn).disconnect();
+            }
+
             if (output != null) {
                 try {
                     output.close();
@@ -485,22 +501,21 @@ public class ArtifactRepositoryImpl exte
                     // Not much we can do
                 }
             }
+            if (outputConn instanceof HttpURLConnection) {
+                ((HttpURLConnection) outputConn).disconnect();
+            }
         }
 
         return location;
     }
 
-    public void setObrBase(URL obrBase) {
-        m_obrBase = obrBase;
-    }
-
     public String preprocessArtifact(ArtifactObject artifact, TargetObject target, String targetID, String version) throws IOException {
         ArtifactPreprocessor preprocessor = getHelper(artifact.getMimetype()).getPreprocessor();
         if (preprocessor == null) {
             return artifact.getURL();
         }
         else {
-            return preprocessor.preprocess(artifact.getURL(), new TargetPropertyResolver(target), targetID, version, m_obrBase);
+            return preprocessor.preprocess(artifact.getURL(), new TargetPropertyResolver(target), targetID, version, getObrBase());
         }
     }
 
@@ -514,20 +529,11 @@ public class ArtifactRepositoryImpl exte
         }
     }
 
-    public URL getObrBase() {
-        return m_obrBase;
-    }
-
     /**
      * Custom comparator which sorts service references by service rank, highest rank first.
      */
-    private static Comparator<ServiceReference> SERVICE_RANK_COMPARATOR = new Comparator<ServiceReference>() { // TODO
-                                                                                                               // ServiceReferences
-                                                                                                               // are
-                                                                                                               // comparable
-                                                                                                               // by
-                                                                                                               // default
-                                                                                                               // now
+    // TODO ServiceReferences are comparable by default now
+    private static Comparator<ServiceReference> SERVICE_RANK_COMPARATOR = new Comparator<ServiceReference>() {
         public int compare(ServiceReference o1, ServiceReference o2) {
             int rank1 = 0;
             int rank2 = 0;
@@ -550,11 +556,6 @@ public class ArtifactRepositoryImpl exte
         }
     };
 
-    private InputStream openInputStream(URL artifactURL) throws IOException {
-        URLConnection connection = m_connectionFactory.createConnection(artifactURL);
-        return connection.getInputStream();
-    }
-
     /**
      * Converts a given URL to a {@link ArtifactResource} that abstracts the way we access the contents of the URL away
      * from the URL itself. This way, we can avoid having to pass authentication credentials, or a

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationImpl.java Thu Oct 10 14:11:13 2013
@@ -166,7 +166,6 @@ public class AssociationImpl<L extends R
      * @param clazz The class of the 'other side' of this association.
      * @return The most suited endpoint; this could be equal to <code>endpoint</code>.
      */
-    @SuppressWarnings("unchecked")
     private <TYPE extends RepositoryObject> List<TYPE> locateEndpoint(ObjectRepositoryImpl<?, TYPE> objectRepositoryImpl, Filter filter, List<TYPE> endpoints, int cardinality, Class<? extends RepositoryObject> clazz, boolean notify) {
 
         List<TYPE> candidates = objectRepositoryImpl.get(filter);

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/AssociationRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -25,6 +25,7 @@ import java.util.Map;
 import org.apache.ace.client.repository.Association;
 import org.apache.ace.client.repository.AssociationRepository;
 import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 
 
 /**
@@ -43,8 +44,8 @@ import org.apache.ace.client.repository.
 public abstract class AssociationRepositoryImpl<L extends RepositoryObject, R extends RepositoryObject, I extends AssociationImpl<L, R, T>, T extends Association<L, R>> extends ObjectRepositoryImpl<I, T> implements AssociationRepository<L, R, T> {
     private Object m_lock = new Object();
 
-    public AssociationRepositoryImpl(ChangeNotifier notifier, String xmlNode) {
-        super(notifier, xmlNode);
+    public AssociationRepositoryImpl(ChangeNotifier notifier, String xmlNode, RepositoryConfiguration repoConfig) {
+        super(notifier, xmlNode, repoConfig);
     }
 
     @SuppressWarnings("unchecked")
@@ -58,7 +59,9 @@ public abstract class AssociationReposit
                 attributes.put(Association.LEFT_CARDINALITY, "" + leftCardinality);
                 attributes.put(Association.RIGHT_CARDINALITY, "" + rightCardinality);
                 association = (T) createNewInhabitant(attributes);
-                add(association);
+                if (!add(association)) {
+                    return null;
+                }
             }
             catch (Exception e) {
                 // We have not been able to instantiate our constructor. Not much to do about that.
@@ -111,4 +114,13 @@ public abstract class AssociationReposit
             super.remove(entity);
         }
     }
+
+    /**
+     * Creates a new inhabitant of the repository based on a map of attributes.
+     * 
+     * @param attributes
+     *            A map of attributes
+     * @return The new inhabitant.
+     */
+    abstract I createNewInhabitant(Map<String, String> attributes);
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierImpl.java Thu Oct 10 14:11:13 2013
@@ -26,16 +26,17 @@ import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 
 /**
- * ChangeNotifierImpl provides a basic implementation of a ChangeNotifier, intended to be used
- * by classes related to the RepositoryAdmin.<br>
+ * ChangeNotifierImpl provides a basic implementation of a ChangeNotifier, intended to be used by classes related to the
+ * RepositoryAdmin.<br>
  * <br>
  * Topics are built up in the following fashion:
  * <ul>
- * <li><b>...TopicRoot</b> All topics start with a TopicRoot, which is the same for all related classes, and ends with a "/".
- * There can be internal and external topics, hence two TopicRoot parameters in the constructor.</li>
- * <li><b>entityRoot</b> This is followed by a class-specific root, usually consisting of the classname with an added "/".</li>
- * <li>Finally, for each call to <code>notifyChanged</code>, a topic can be specified, which is something like
- * "CHANGED" or "ADDED".</li>
+ * <li><b>...TopicRoot</b> All topics start with a TopicRoot, which is the same for all related classes, and ends with a
+ * "/". There can be internal and external topics, hence two TopicRoot parameters in the constructor.</li>
+ * <li><b>entityRoot</b> This is followed by a class-specific root, usually consisting of the classname with an added
+ * "/".</li>
+ * <li>Finally, for each call to <code>notifyChanged</code>, a topic can be specified, which is something like "CHANGED"
+ * or "ADDED".</li>
  * </ul>
  */
 public class ChangeNotifierImpl implements ChangeNotifier {
@@ -48,10 +49,15 @@ public class ChangeNotifierImpl implemen
 
     /**
      * Creates a new ChangeNotifierImpl.
-     * @param eventAdmin An EventAdmin to send events to.
-     * @param privateTopicRoot The root of all private topics; see TopicRoot in the description of this class.
-     * @param publicTopicRoot The root of all public topics; see TopicRoot in the description of this class.
-     * @param entityRoot A class-specific root for the class which will use this ChangeNotifierImpl.
+     * 
+     * @param eventAdmin
+     *            An EventAdmin to send events to.
+     * @param privateTopicRoot
+     *            The root of all private topics; see TopicRoot in the description of this class.
+     * @param publicTopicRoot
+     *            The root of all public topics; see TopicRoot in the description of this class.
+     * @param entityRoot
+     *            A class-specific root for the class which will use this ChangeNotifierImpl.
      */
     ChangeNotifierImpl(EventAdmin eventAdmin, String privateTopicRoot, String publicTopicRoot, String entityRoot, String sessionID) {
         m_eventAdmin = eventAdmin;
@@ -71,7 +77,7 @@ public class ChangeNotifierImpl implemen
 
     public void notifyChanged(String topic, Properties props, boolean internalOnly) {
         props = addSession(props);
-        m_eventAdmin.sendEvent(new Event(m_privateTopicRoot + m_entityRoot + topic,(Dictionary) props));
+        m_eventAdmin.sendEvent(new Event(m_privateTopicRoot + m_entityRoot + topic, (Dictionary) props));
         if (!internalOnly) {
             m_eventAdmin.postEvent(new Event(m_publicTopicRoot + m_entityRoot + topic, (Dictionary) props));
         }