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/15 23:46:43 UTC

svn commit: r1532552 - 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/src/org/apache/ace/agent/itest/ org.apache.ace.agent/src/org/apache/ace/agent/ org.apache.ace...

Author: jawi
Date: Tue Oct 15 21:46:42 2013
New Revision: 1532552

URL: http://svn.apache.org/r1532552
Log:
ACE-419 - show how to create a custom agent controller:

- created a integration test that shows how a simple agent
  controller can be implemented using the APIs provided by
  the agent.


Added:
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java   (with props)
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/src/org/apache/ace/agent/itest/AgentUpdateTest.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
    ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java
    ace/trunk/org.apache.ace.test/src/org/apache/ace/test/utils/NetUtils.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=1532552&r1=1532551&r2=1532552&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.itest/bnd.bnd Tue Oct 15 21:46:42 2013
@@ -11,6 +11,7 @@ Test-Cases: ${classes;CONCRETE;EXTENDS;j
 	org.apache.felix.gogo.runtime,\
 	org.apache.felix.gogo.shell,\
 	org.apache.felix.http.jetty,\
+	org.apache.felix.log,\
 	biz.aQute.bnd,\
 	osgi.cmpn
 Private-Package: aQute.bnd.annotation.component,\

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=1532552&r1=1532551&r2=1532552&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 Tue Oct 15 21:46:42 2013
@@ -18,7 +18,6 @@
  */
 package org.apache.ace.agent.itest;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -88,18 +87,6 @@ public class AgentDeploymentTest extends
         }
     }
 
-    private static class TestBundle {
-        private final File m_file;
-
-        public TestBundle(String name, Version version, String... headers) throws Exception {
-            m_file = createBundle(name, version, headers);
-        }
-
-        public File getFile() {
-            return m_file;
-        }
-    }
-
     private static class TestDeploymentServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
 
@@ -153,7 +140,7 @@ public class AgentDeploymentTest extends
                     throw new IllegalStateException("Test error! Should never happen... " + pathinfoTail);
                 }
                 int offset = -2;
-                resp.addIntHeader("X-ACE-DPSize", offset + dpackage.m_version.getMajor());
+                resp.addIntHeader("X-ACE-DPSize", offset + dpackage.getVersion().getMajor());
                 resp.flushBuffer();
             }
         }
@@ -308,31 +295,6 @@ public class AgentDeploymentTest extends
         }
     }
 
-    private static class TestPackage {
-        private final String m_name;
-        private final Version m_version;
-        private final File m_file;
-
-        public TestPackage(String name, Version version, TestBundle... bundles) throws Exception {
-            m_name = name;
-            m_version = version;
-
-            File[] files = new File[bundles.length];
-            for (int i = 0; i < bundles.length; i++) {
-                files[i] = bundles[i].getFile();
-            }
-            m_file = createPackage(m_name, m_version, files);
-        }
-
-        public File getFile() {
-            return m_file;
-        }
-
-        public Version getVersion() {
-            return m_version;
-        }
-    }
-
     private static class TestUpdateServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
 

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=1532552&r1=1532551&r2=1532552&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 Tue Oct 15 21:46:42 2013
@@ -122,6 +122,7 @@ public class AgentExtensionTest extends 
             }, null);
     }
 
+    @SuppressWarnings("unchecked")
     private <T> T locateService(Class<T> iface) {
         ServiceReference reference = m_bundleContext.getServiceReference(iface.getName());
         if (reference == null) {

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=1532552&r1=1532551&r2=1532552&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 Tue Oct 15 21:46:42 2013
@@ -18,6 +18,47 @@ import aQute.lib.osgi.Jar;
 
 public abstract class BaseAgentTest extends IntegrationTestBase {
 
+    protected static class TestBundle {
+        private final File m_file;
+
+        public TestBundle(String name, Version version, String... headers) throws Exception {
+            m_file = createBundle(name, version, headers);
+        }
+
+        public File getFile() {
+            return m_file;
+        }
+    }
+
+    protected static class TestPackage {
+        private final String m_name;
+        private final Version m_version;
+        private final File m_file;
+
+        public TestPackage(String name, Version version, TestBundle... bundles) throws Exception {
+            m_name = name;
+            m_version = version;
+
+            File[] files = new File[bundles.length];
+            for (int i = 0; i < bundles.length; i++) {
+                files[i] = bundles[i].getFile();
+            }
+            m_file = createPackage(m_name, m_version, files);
+        }
+        
+        public String getName() {
+            return m_name;
+        }
+
+        public File getFile() {
+            return m_file;
+        }
+
+        public Version getVersion() {
+            return m_version;
+        }
+    }
+
     protected static File createBundle(String bsn, Version version, String... headers) throws Exception {
         Builder b = new Builder();
 

Added: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java?rev=1532552&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java (added)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java Tue Oct 15 21:46:42 2013
@@ -0,0 +1,442 @@
+/*
+ * 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.ace.agent.itest;
+
+import java.io.FileInputStream;
+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.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletException;
+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.agent.DeploymentHandler;
+import org.apache.ace.agent.DownloadHandle;
+import org.apache.ace.agent.DownloadResult;
+import org.apache.ace.agent.FeedbackChannel;
+import org.apache.ace.agent.FeedbackHandler;
+import org.apache.ace.agent.UpdateHandler;
+import org.apache.ace.test.constants.TestConstants;
+import org.apache.ace.test.utils.NetUtils;
+import org.apache.felix.dm.Component;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.service.http.HttpService;
+
+/**
+ * Tests that we can create an agent with a completely custom controller.
+ */
+public class CustomAgentControllerTest extends BaseAgentTest {
+    /**
+     * Provides a simple implementation of {@link AgentUser} that always acknowledges a download and/or installation.
+     */
+    static class AcknowledgingAgentUser implements AgentUser {
+        @Override
+        public boolean downloadAvailableUpdate(UpdateType updateType, String agentId, Version from, Version to) {
+            // Always proceed with a download...
+            return true;
+        }
+
+        @Override
+        public boolean installAvailableUpdate(UpdateType updateType, String agentId, Version from, Version to) {
+            // Always proceed with the installation...
+            return true;
+        }
+    }
+
+    /**
+     * Denotes a "user" of our agent that is monitoring our agent and able to respond to questions.
+     */
+    static interface AgentUser {
+        /**
+         * Asks the user whether or not to download an available update.
+         * 
+         * @param updateType
+         *            the type of update to download, cannot be <code>null</code>;
+         * @param agentId
+         *            the identification of the agent that has an update available;
+         * @param from
+         *            the current installed version to upgrade from;
+         * @param to
+         *            the available version to upgrade to.
+         * @return <code>true</code> if the update should be downloaded, <code>false</code> otherwise.
+         */
+        boolean downloadAvailableUpdate(UpdateType updateType, String agentId, Version from, Version to);
+
+        /**
+         * Asks the user whether or not to install an available update, after it has been downloaded.
+         * 
+         * @param updateType
+         *            the type of update to install, cannot be <code>null</code>;
+         * @param agentId
+         *            the identification of the agent that has an update available;
+         * @param from
+         *            the current installed version to upgrade from;
+         * @param to
+         *            the available version to upgrade to.
+         * @return <code>true</code> if the update should be installed, <code>false</code> otherwise.
+         */
+        boolean installAvailableUpdate(UpdateType updateType, String agentId, Version from, Version to);
+    }
+
+    /**
+     * The actual custom controller as {@link Runnable} task, that simply loops and executes its tasks until notified to
+     * stop.
+     */
+    class CustomController implements Runnable, DownloadHandle.DownloadProgressListener {
+        private final CountDownLatch m_latch;
+        private volatile boolean m_stop = false;
+
+        public CustomController(CountDownLatch latch) {
+            m_latch = latch;
+        }
+
+        @Override
+        public void progress(long bytesRead, long totalBytes) {
+            System.out.printf("Download progress: %d of %d bytes read...%n", bytesRead, totalBytes);
+        }
+
+        @Override
+        public void run() {
+            while (!m_stop) {
+                try {
+                    TimeUnit.MILLISECONDS.sleep(500);
+                }
+                catch (InterruptedException exception) {
+                    // We're requested to stop...
+                    break;
+                }
+
+                try {
+                    // Send our feedback...
+                    sendFeedbackToServer();
+                }
+                catch (Exception exception) {
+                    System.out.printf("Feedback synchronization failed with %s.%n", exception.getMessage());
+                    exception.printStackTrace(System.out);
+                }
+
+                try {
+                    // Check for agent updates...
+                    checkForUpdate(UpdateType.AGENT);
+                }
+                catch (Exception exception) {
+                    System.out.printf("Agent update failed with %s.%n", exception.getMessage());
+                    exception.printStackTrace(System.out);
+                }
+
+                try {
+                    // Check for deployment updates...
+                    checkForUpdate(UpdateType.DEPLOYMENT);
+                }
+                catch (Exception exception) {
+                    System.out.printf("Deployment update failed with %s.%n", exception.getMessage());
+                    exception.printStackTrace(System.out);
+                }
+            }
+        }
+
+        public void stop() {
+            m_stop = true;
+        }
+
+        private void checkForUpdate(UpdateType updateType) throws Exception {
+            UpdateHandler updateHandler = getUpdateHandler(updateType);
+
+            Version installed = updateHandler.getInstalledVersion();
+            Version available = updateHandler.getHighestAvailableVersion();
+            if (installed != null && installed.compareTo(available) < 0) {
+                // Update available, update the agent...
+                if (!m_agentUser.downloadAvailableUpdate(updateType, getAgentId(), installed, available)) {
+                    // No, we may not download this update now...
+                    return;
+                }
+
+                System.out.printf("Downloading %s update (from v%s to v%s)...%n", updateType, installed, available);
+
+                DownloadHandle downloadHandle = updateHandler.getDownloadHandle(available, false /* fixPackage */);
+
+                Future<DownloadResult> future = downloadHandle.start(this);
+                // Block until the download is complete...
+                DownloadResult result = future.get();
+
+                if (m_agentUser.installAvailableUpdate(updateType, getAgentId(), installed, available)) {
+                    System.out.printf("Installing %s update (from v%s to v%s)...%n", updateType, installed, available);
+
+                    // We've confirmation that we can install this update...
+                    updateHandler.install(result.getInputStream());
+
+                    m_latch.countDown();
+                }
+            }
+        }
+
+        private String getAgentId() {
+            return m_control.getAgentId();
+        }
+
+        private UpdateHandler getUpdateHandler(UpdateType updateType) {
+            UpdateHandler updateHandler;
+            if (UpdateType.AGENT == updateType) {
+                updateHandler = m_control.getAgentUpdateHandler();
+            }
+            else {
+                updateHandler = m_control.getDeploymentHandler();
+            }
+            return updateHandler;
+        }
+
+        private void sendFeedbackToServer() throws IOException {
+            FeedbackHandler feedbackHandler = m_control.getFeedbackHandler();
+            Set<String> channelNames = feedbackHandler.getChannelNames();
+            for (String channelName : channelNames) {
+                FeedbackChannel channel = feedbackHandler.getChannel(channelName);
+
+                System.out.printf("Synchronizing feedback of %s with server...%n", channelName);
+
+                channel.sendFeedback();
+
+                m_latch.countDown();
+            }
+        }
+    }
+
+    static class TestDeploymentServlet extends HttpServlet {
+        private static final long serialVersionUID = 1L;
+
+        private final Map<String, TestPackage> m_packages = new HashMap<String, TestPackage>();
+        private final String m_agentId;
+
+        public TestDeploymentServlet(String agentId, TestPackage... testPackages) {
+            m_agentId = agentId;
+
+            for (TestPackage testPackage : testPackages) {
+                m_packages.put(testPackage.getVersion().toString(), testPackage);
+            }
+        }
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            String pathInfo = req.getPathInfo();
+
+            if (pathInfo.startsWith("/auditlog/query")) {
+                resp.setContentType("text/plain");
+                PrintWriter writer = resp.getWriter();
+                writer.println(req.getParameter("tid") + "," + req.getParameter("logid") + ",0-10");
+                writer.close();
+            }
+            else if (pathInfo.startsWith("/deployment/")) {
+                String pathinfoTail = pathInfo.replaceFirst("/deployment/" + m_agentId + "/versions/?", "");
+                if (pathinfoTail.equals("")) {
+                    sendVersions(resp);
+                }
+                else {
+                    TestPackage dpackage = m_packages.get(pathinfoTail);
+                    if (dpackage == null) {
+                        throw new IllegalStateException("Test error! Should never happen... " + pathinfoTail);
+                    }
+                    sendPackage(dpackage, req, resp);
+                }
+            }
+            else if (pathInfo.startsWith("/agent/")) {
+                String tail = pathInfo.replaceFirst("/agent/" + m_agentId + "/org.apache.ace.agent/versions/", "");
+                if ("".equals(tail)) {
+                    sendVersions(resp);
+                }
+            }
+            else {
+                resp.setContentLength(0);
+                resp.setStatus(HttpServletResponse.SC_OK);
+            }
+            resp.flushBuffer();
+        }
+
+        @Override
+        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
+            String pathInfo = request.getPathInfo();
+            if (pathInfo.startsWith("/auditlog/")) {
+                InputStream is = request.getInputStream();
+                while (is.read() != -1) {
+                }
+                is.close();
+            }
+            response.setContentType("text/plain");
+            response.flushBuffer();
+        }
+
+        @Override
+        protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+            response.setContentType("text/plain");
+            response.flushBuffer();
+        }
+
+        private void sendPackage(TestPackage dpackage, HttpServletRequest req, HttpServletResponse resp) throws IOException {
+            InputStream is = null;
+            OutputStream os = null;
+            try {
+                is = new FileInputStream(dpackage.getFile());
+                os = resp.getOutputStream();
+
+                int read;
+                byte[] buffer = new byte[4096];
+                do {
+                    read = is.read(buffer);
+                    if (read >= 0) {
+                        os.write(buffer, 0, read);
+                    }
+                }
+                while (read >= 0);
+            }
+            finally {
+                if (is != null) {
+                    is.close();
+                }
+                if (os != null) {
+                    os.close();
+                }
+            }
+        }
+
+        private void sendVersions(HttpServletResponse resp) throws IOException {
+            PrintWriter writer = resp.getWriter();
+            for (String version : m_packages.keySet()) {
+                writer.println(version);
+            }
+            writer.close();
+
+            resp.setContentType("text/plain");
+            resp.setStatus(200);
+            resp.flushBuffer();
+        }
+    }
+
+    /**
+     * Denotes the kind of update.
+     */
+    static enum UpdateType {
+        AGENT, DEPLOYMENT;
+    }
+
+    private static final Version V1_0_0 = Version.parseVersion("1.0.0");
+    private static final String TEST_BUNDLE_NAME_PREFIX = "test.bundle";
+    private static final String AGENT_ID = "defaultTargetID";
+
+    // Injected by Felix DM...
+    private volatile HttpService m_http;
+    private volatile AgentControl m_control;
+    private volatile AgentUser m_agentUser;
+
+    /**
+     * Tests that we can provide a custom controller implementation based on the following use-case:
+     * <p>
+     * ...
+     * </p>
+     */
+    public void testCustomController() throws Exception {
+        CountDownLatch latch = new CountDownLatch(3);
+
+        CustomController controller = new CustomController(latch);
+
+        Thread thread = new Thread(controller);
+        thread.start();
+
+        boolean success = latch.await(30, TimeUnit.SECONDS);
+
+        waitForInstalledVersion(V1_0_0);
+
+        controller.stop();
+        thread.join();
+
+        assertTrue("Use case not completed!", success);
+    }
+
+    @Override
+    protected void configureAdditionalServices() throws Exception {
+        m_control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_DISABLED, "true");
+
+        TestBundle bundle1v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("1"), V1_0_0);
+        TestPackage package1 = new TestPackage(AGENT_ID, V1_0_0, bundle1v1);
+
+        TestDeploymentServlet servlet = new TestDeploymentServlet(AGENT_ID, package1);
+
+        String url = String.format("http://localhost:%d/", TestConstants.PORT);
+        NetUtils.waitForURL(url, 404, 10000);
+
+        m_http.registerServlet("/", servlet, null, null);
+
+        NetUtils.waitForURL(url, 200, 10000);
+    }
+
+    @Override
+    protected void configureProvisionedServices() throws Exception {
+        m_bundleContext.registerService(AgentUser.class.getName(), new AcknowledgingAgentUser(), null);
+    }
+
+    @Override
+    protected void doTearDown() throws Exception {
+        // Remove all provisioned components...
+        m_dependencyManager.clear();
+
+        m_http.unregister("/");
+
+        // Force an uninstall of all remaining test bundles...
+        for (Bundle bundle : m_bundleContext.getBundles()) {
+            String bsn = bundle.getSymbolicName();
+            if (bsn.startsWith(TEST_BUNDLE_NAME_PREFIX)) {
+                bundle.uninstall();
+            }
+        }
+
+        resetAgentBundleState();
+    }
+
+    @Override
+    protected Component[] getDependencies() {
+        return new Component[] {
+            createComponent()
+                .setImplementation(this)
+                .add(createServiceDependency().setService(HttpService.class).setRequired(true))
+                .add(createServiceDependency().setService(AgentControl.class).setRequired(true))
+                .add(createServiceDependency().setService(AgentUser.class).setRequired(true))
+        };
+    }
+
+    private void waitForInstalledVersion(Version version) throws Exception {
+        DeploymentHandler deploymentHandler = m_control.getDeploymentHandler();
+
+        int timeout = 100;
+        while (!deploymentHandler.getInstalledVersion().equals(version)) {
+            Thread.sleep(100);
+            if (timeout-- <= 0) {
+                fail("Timed out while waiting for deployment " + version);
+            }
+        }
+    }
+}

Propchange: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1532552&r1=1532551&r2=1532552&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 Tue Oct 15 21:46:42 2013
@@ -43,6 +43,7 @@ import org.apache.ace.agent.AgentConstan
 import org.apache.ace.agent.AgentControl;
 import org.apache.ace.it.IntegrationTestBase;
 import org.apache.ace.test.constants.TestConstants;
+import org.apache.ace.test.utils.NetUtils;
 import org.apache.felix.dm.Component;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Version;
@@ -61,18 +62,19 @@ import org.osgi.service.http.HttpService
 public class AgentUpdateTest extends IntegrationTestBase {
     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 {
+            }
+            else {
                 resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
             }
         }
     }
-    
+
     private static class AgentUpdateOBRServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
         private Phase m_phase;
@@ -108,6 +110,11 @@ public class AgentUpdateTest extends Int
             }
         }
 
+        protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+            response.setContentType("text/plain");
+            response.flushBuffer();
+        }
+
         private InputStream getBundle() throws IOException {
             return new FileInputStream(new File("../org.apache.ace.agent/generated/org.apache.ace.agent.jar"));
         }
@@ -209,9 +216,14 @@ public class AgentUpdateTest extends Int
     @Override
     protected void configureAdditionalServices() throws Exception {
         m_servlet = new AgentUpdateOBRServlet();
+
+        String url = String.format("http://localhost:%d/obr", TestConstants.PORT);
+        NetUtils.waitForURL(url, 404, 10000);
+
         m_http.registerServlet("/obr", m_servlet, null, null);
-        
         m_http.registerServlet("/auditlog", new DummyAuditLogServlet(), null, null);
+
+        NetUtils.waitForURL(url, 200, 10000);
     }
 
     @Override

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java?rev=1532552&r1=1532551&r2=1532552&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java Tue Oct 15 21:46:42 2013
@@ -41,16 +41,19 @@ public interface AgentConstants {
      * , default is <code>INFO</code>.
      */
     String CONFIG_LOGGING_LEVEL = CONFIG_KEY_NAMESPACE + ".logging.level";
-    
+
     /**
      * Exclude list for auditlog events. Should be a comma separated list of integers, as defined by {@link AuditEvent}.
      * Example : '2001,2003,2005,3001'
      */
     String CONFIG_LOGGING_EXCLUDE_EVENTS = CONFIG_KEY_NAMESPACE + ".logging.events.exclude";
-    
+
     /**
      * Configuration option to disable the default identification handler. When set to true some other bundle must
      * provide it as a service. Should be <code>{true,false}</code>, default is <code>false</code>.
+     * <p>
+     * Note that this property is expected to be set as system or environment setting!
+     * </p>
      */
     String CONFIG_IDENTIFICATION_DISABLED = CONFIG_KEY_NAMESPACE + ".identification.disabled";
 
@@ -63,6 +66,9 @@ public interface AgentConstants {
     /**
      * Configuration option to disable the default discovery handler. When set to true some other bundle must provide it
      * as a service. Should be <code>{true,false}</code>, default is <code>false</code>.
+     * <p>
+     * Note that this property is expected to be set as system or environment setting!
+     * </p>
      */
     String CONFIG_DISCOVERY_DISABLED = CONFIG_KEY_NAMESPACE + ".discovery.disabled";
 
@@ -81,6 +87,9 @@ public interface AgentConstants {
     /**
      * Configuration option to disable the default controller. When set to true some other bundle control the agent's
      * behavior. Should be <code>{true,false}</code>, default is <code>false</code>.
+     * <p>
+     * Note that this property is expected to be set as system or environment setting!
+     * </p>
      */
     String CONFIG_CONTROLLER_DISABLED = CONFIG_KEY_NAMESPACE + ".controller.disabled";
 
@@ -117,6 +126,9 @@ public interface AgentConstants {
     /**
      * Configuration option to disable the default {@link ConnectionHandler}. When set to true some other bundle must
      * provide it as a service. Should be <code>{true,false}</code>, default is <code>false</code>.
+     * <p>
+     * Note that this property is expected to be set as system or environment setting!
+     * </p>
      */
     String CONFIG_CONNECTION_DISABLED = CONFIG_KEY_NAMESPACE + ".connection.disabled";
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java?rev=1532552&r1=1532551&r2=1532552&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java Tue Oct 15 21:46:42 2013
@@ -43,6 +43,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.ace.agent.AgentConstants;
 import org.apache.ace.agent.DownloadHandle;
 import org.apache.ace.agent.DownloadHandle.DownloadProgressListener;
 import org.apache.ace.agent.DownloadResult;
@@ -418,7 +419,7 @@ public class DefaultController extends C
     public DefaultController() {
         super("controller");
 
-        m_disabled = new AtomicBoolean(false);
+        m_disabled = new AtomicBoolean(Boolean.getBoolean(AgentConstants.CONFIG_CONTROLLER_DISABLED));
         m_interval = new AtomicLong(60);
         m_syncDelay = new AtomicLong(5);
 

Modified: ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java?rev=1532552&r1=1532551&r2=1532552&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java (original)
+++ ace/trunk/org.apache.ace.test/src/org/apache/ace/it/IntegrationTestBase.java Tue Oct 15 21:46:42 2013
@@ -541,7 +541,10 @@ public class IntegrationTestBase extends
         System.setProperty("org.apache.ace.server.port", Integer.toString(TestConstants.PORT));
 
         // Ensure the HTTP service is running on the port we expect...
-        configureHttpService(TestConstants.PORT);
+        int port = Integer.getInteger("org.osgi.service.http.port", 8080);
+        if (port != TestConstants.PORT) {
+            configureHttpService(TestConstants.PORT);
+        }
 
         // Call back the implementation...
         configureProvisionedServices();

Modified: ace/trunk/org.apache.ace.test/src/org/apache/ace/test/utils/NetUtils.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.test/src/org/apache/ace/test/utils/NetUtils.java?rev=1532552&r1=1532551&r2=1532552&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.test/src/org/apache/ace/test/utils/NetUtils.java (original)
+++ ace/trunk/org.apache.ace.test/src/org/apache/ace/test/utils/NetUtils.java Tue Oct 15 21:46:42 2013
@@ -67,8 +67,9 @@ public class NetUtils {
         while (System.currentTimeMillis() < deadline) {
             try {
                 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-                connection.connect();
-                if (connection.getResponseCode() == responseCode) {
+                connection.setRequestMethod("HEAD");
+                int rc = connection.getResponseCode();
+                if (rc == responseCode) {
                     return true;
                 }
             }