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

svn commit: r1518177 [1/4] - in /ace/trunk: org.apache.ace.agent.itest/ org.apache.ace.agent.itest/conf/ org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ org.apache.ace.agent.launcher/ org.apache.ace.agent.launcher/src/org/apache/ace/agent/la...

Author: bramk
Date: Wed Aug 28 12:28:00 2013
New Revision: 1518177

URL: http://svn.apache.org/r1518177
Log:
ACE-347 API refactor, code cleanup, new features

* Added deployment integration testing
* Removed unneeded 3rd party (DM/commons-codec)
* Added propper connection failure handling
* Added support for extension service
* Improved configuration
* more..




Added:
    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
      - copied, changed from r1516756, ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java
    ace/trunk/org.apache.ace.agent.launcher/launcher-example.properties
    ace/trunk/org.apache.ace.agent.update.itest/   (with props)
    ace/trunk/org.apache.ace.agent.update.itest/.classpath
    ace/trunk/org.apache.ace.agent.update.itest/.gitignore
    ace/trunk/org.apache.ace.agent.update.itest/.project
    ace/trunk/org.apache.ace.agent.update.itest/.settings/
    ace/trunk/org.apache.ace.agent.update.itest/.settings/org.eclipse.jdt.core.prefs
    ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd
    ace/trunk/org.apache.ace.agent.update.itest/build.xml
    ace/trunk/org.apache.ace.agent.update.itest/conf/
    ace/trunk/org.apache.ace.agent.update.itest/conf/org.apache.ace.deployment.servlet.agent.cfg
    ace/trunk/org.apache.ace.agent.update.itest/src/
    ace/trunk/org.apache.ace.agent.update.itest/src/.gitignore
    ace/trunk/org.apache.ace.agent.update.itest/src/org/
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/
    ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java
    ace/trunk/org.apache.ace.agent.update.itest/test/
    ace/trunk/org.apache.ace.agent.update.itest/test/.gitignore
    ace/trunk/org.apache.ace.agent/README
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventListener.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventsHandler.java
      - copied, changed from r1517469, ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/LoggingHandler.java
      - copied, changed from r1517469, ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionUtil.java
Removed:
    ace/trunk/org.apache.ace.agent.itest/conf/
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentUpdateTest.java
    ace/trunk/org.apache.ace.agent.launcher/launcher.properties
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ReflectionUtil.java
Modified:
    ace/trunk/org.apache.ace.agent.itest/bnd.bnd
    ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Launcher.java
    ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/launcher-defaults.properties
    ace/trunk/org.apache.ace.agent/bnd.bnd
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentConstants.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentContext.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentControl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConfigurationHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConnectionHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DiscoveryHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackChannel.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/IdentificationHandler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/RetryAfterException.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentControlImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/FeedbackChannelImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/FeedbackHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/IdentificationHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/UpdateHandlerBase.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConfigurationHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/ConnectionHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/CustomControllerTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/DeploymentHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/DiscoveryHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/DownloadHandlerTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/FeedbackHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/IdentificationHandlerImplTest.java
    ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/testutil/BaseAgentTest.java
    ace/trunk/org.apache.ace.builder/.classpath

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=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.itest/bnd.bnd Wed Aug 28 12:28:00 2013
@@ -2,33 +2,62 @@ Test-Cases: ${classes;CONCRETE;EXTENDS;j
 -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.dependencymanager,\
-	osgi.cmpn,\
-	org.apache.felix.http.jetty,\
-	org.apache.ace.deployment.servlet;version=latest,\
-	org.apache.ace.deployment.api;version=latest,\
-	org.apache.ace.deployment.streamgenerator;version=latest,\
-	org.apache.ace.authentication.api;version=latest,\
-	org.apache.ace.connectionfactory;version=latest,\
-	org.apache.ace.deployment.provider.api;version=latest,\
+	org.apache.felix.dependencymanager.shell,\
 	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.felix.configadmin,\
-	org.apache.ace.http.listener;version=latest
-Private-Package: org.apache.ace.agent.itest
+	org.apache.felix.http.jetty,\
+	biz.aQute.bnd,\
+	osgi.cmpn
+Private-Package: aQute.bnd.annotation.component,\
+	aQute.bnd.help,\
+	aQute.bnd.service.action,\
+	aQute.lib.deployer,\
+	aQute.lib.osgi.eclipse,\
+	aQute.libg.filelock,\
+	aQute.bnd.build,\
+	aQute.bnd.maven.support,\
+	aQute.bnd.settings,\
+	aQute.libg.command,\
+	aQute.libg.tuple,\
+	org.apache.ace.agent.itest,\
+	aQute.lib.osgi,\
+	aQute.bnd.annotation,\
+	aQute.bnd.annotation.metatype,\
+	aQute.bnd.component,\
+	aQute.bnd.make,\
+	aQute.bnd.make.component,\
+	aQute.bnd.make.metatype,\
+	aQute.bnd.maven,\
+	aQute.bnd.service,\
+	aQute.lib.base64,\
+	aQute.lib.collections,\
+	aQute.lib.filter,\
+	aQute.lib.hex,\
+	aQute.lib.io,\
+	aQute.lib.tag,\
+	aQute.libg.cryptography,\
+	aQute.libg.generics,\
+	aQute.libg.header,\
+	aQute.libg.qtokens,\
+	aQute.libg.reporter,\
+	aQute.libg.sed,\
+	aQute.libg.tarjan,\
+	aQute.libg.version
 -runee: JavaSE-1.6
 -runvm: -ea
 -runfw: org.apache.felix.framework
 -buildpath: osgi.core;version='[4.2,5)',\
-	junit.osgi,\
-	org.mockito.mockito-all,\
 	org.apache.ace.agent;version=latest,\
+	org.apache.ace.builder;version=latest,\
 	org.apache.ace.test;version=latest,\
 	org.apache.felix.dependencymanager,\
-	org.apache.felix.http.jetty
+	org.apache.felix.http.jetty,\
+	biz.aQute.bnd,\
+	junit.osgi,\
+	org.mockito.mockito-all	
 -runsystempackages: sun.reflect
 -runproperties: org.apache.felix.log.storeDebug=true,\
 	org.apache.felix.eventadmin.Timeout=0,\
@@ -36,6 +65,7 @@ Private-Package: org.apache.ace.agent.it
 	org.osgi.service.http.port=8080,\
 	org.apache.felix.log.maxSize=1000
 Import-Package: org.apache.ace.agent,\
+	!org.osgi.service.component.annotations,\
 	*
 Bundle-Version: 1.0.0
 Bundle-Name: Apache ACE Agent itest

Added: 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=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java (added)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java Wed Aug 28 12:28:00 2013
@@ -0,0 +1,453 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.EventListener;
+import org.apache.ace.agent.LoggingHandler;
+import org.apache.ace.builder.DeploymentPackageBuilder;
+import org.apache.felix.dm.Component;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.http.HttpService;
+
+import aQute.lib.osgi.Builder;
+import aQute.lib.osgi.Jar;
+
+/**
+ * Tests updating the management agent. In fact it tests different failure paths first, and finally gets to update the
+ * agent. The tests it does are:
+ * <ul>
+ * <li>Try to update to a corrupt bundle (with some random garbage injected in the JAR file).</li>
+ * <li>Try to update to a bundle that does not resolve because of some impossible import package statement.</li>
+ * <li>Try to update to a bundle that does resolve, but does not start because of a non-existing bundle activator.</li>
+ * <li>Update to a new version of the agent (actually, it's the same bundle, but with a different version.</li>
+ * </ul>
+ */
+public class AgentDeploymentTest extends BaseAgentTest {
+
+    private enum Failure {
+        EMPTY_STREAM, CORRUPT_STREAM, ABORT_STREAM, VERSIONS_RETRY_AFTER, DEPLOYMENT_RETRY_AFTER
+
+    }
+
+    private volatile TestDeploymentServlet m_servlet;
+    private volatile HttpService m_http;
+    private volatile TestEventListener m_listener;
+
+    private final Version version1 = Version.parseVersion("1.0.0");
+    private final Version version2 = Version.parseVersion("2.0.0");
+    private final Version version3 = Version.parseVersion("3.0.0");
+    private final Version version4 = Version.parseVersion("4.0.0");
+    private final Version version5 = Version.parseVersion("5.0.0");
+    private final Version version6 = Version.parseVersion("6.0.0");
+
+    private TestPackage m_package1;
+    private TestPackage m_package2;
+    private TestPackage m_package3;
+    private TestPackage m_package4;
+    private TestPackage m_package5;
+    private TestPackage m_package6;
+
+    @Override
+    protected Component[] getDependencies() {
+        m_listener = new TestEventListener();
+        return new Component[] {
+            createComponent()
+                .setImplementation(this)
+                .add(createServiceDependency().setService(HttpService.class).setRequired(true)),
+            createComponent()
+                .setInterface(EventListener.class.getName(), null)
+                .setImplementation(m_listener)
+        };
+    }
+
+    @Override
+    public void configureAdditionalServices() throws Exception {
+
+        TestBundle bundle1v1 = new TestBundle("bundle1", version1);
+        TestBundle bundle1v2 = new TestBundle("bundle1", version2);
+        TestBundle bundle2v1 = new TestBundle("bundle2", version1);
+        TestBundle bundle2v2 = new TestBundle("bundle2", version2);
+
+        TestBundle bundle3v1 = new TestBundle("bundle3", version1, Constants.BUNDLE_ACTIVATOR, "no.Such.Class");
+        TestBundle bundle3v2 = new TestBundle("bundle3", version2);
+
+        m_package1 = new TestPackage("007", version1, bundle1v1);
+        m_package2 = new TestPackage("007", version2, bundle1v2);
+        m_package3 = new TestPackage("007", version3, bundle1v2, bundle2v1);
+        m_package4 = new TestPackage("007", version4, bundle1v2, bundle2v2);
+        m_package5 = new TestPackage("007", version5, bundle1v2, bundle2v2, bundle3v1);
+        m_package6 = new TestPackage("007", version6, bundle1v2, bundle2v2, bundle3v2);
+
+        m_servlet = new TestDeploymentServlet("007");
+        m_http.registerServlet("/deployment", m_servlet, null, null);
+        m_http.registerServlet("/agent", new TestUpdateServlet(), null, null);
+        m_http.registerServlet("/auditlog", new TestAuditlogServlet(), null, null);
+
+    }
+
+    public void tearDown() throws Exception {
+        m_http.unregister("/deployment");
+        m_http.unregister("/agent");
+        m_http.unregister("/auditlog");
+    }
+
+    public void testDeployment() throws Exception {
+
+        AgentControl control = getService(AgentControl.class);
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_LOGGING_LEVEL, LoggingHandler.Levels.DEBUG.name());
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_IDENTIFICATION_AGENTID, "007");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_STREAMING, "true");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_SYNCDELAY, "1");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_SYNCINTERVAL, "2");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_RETRIES, "2");
+        waitForInstalledVersion(Version.emptyVersion);
+
+        expectSuccessfulDeployment(m_package1, Failure.VERSIONS_RETRY_AFTER);
+        expectSuccessfulDeployment(m_package2, Failure.DEPLOYMENT_RETRY_AFTER);
+        expectSuccessfulDeployment(m_package3, Failure.EMPTY_STREAM);
+        expectSuccessfulDeployment(m_package4, Failure.CORRUPT_STREAM);
+        expectSuccessfulDeployment(m_package5, Failure.ABORT_STREAM);
+        expectSuccessfulDeployment(m_package6, null);
+
+        resetAgentBundleState();
+
+        control = getService(AgentControl.class);
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_LOGGING_LEVEL, LoggingHandler.Levels.DEBUG.name());
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_IDENTIFICATION_AGENTID, "007");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_STREAMING, "true");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_SYNCDELAY, "2");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_SYNCINTERVAL, "2");
+        control.getConfigurationHandler().put(AgentConstants.CONFIG_CONTROLLER_RETRIES, "2");
+        m_servlet.clearPackages();
+
+        control.getConfigurationHandler().put("ace.agent.controller.updateStreaming", "false");
+        control.getConfigurationHandler().put("ace.agent.identification.agentId", "007");
+        control.getConfigurationHandler().put("ace.agent.controller.syncDelay", "2");
+        waitForInstalledVersion(Version.emptyVersion);
+
+        expectSuccessfulDeployment(m_package1, Failure.VERSIONS_RETRY_AFTER);
+        expectSuccessfulDeployment(m_package2, Failure.DEPLOYMENT_RETRY_AFTER);
+        expectSuccessfulDeployment(m_package3, Failure.EMPTY_STREAM);
+        expectSuccessfulDeployment(m_package4, Failure.CORRUPT_STREAM);
+        expectSuccessfulDeployment(m_package5, Failure.ABORT_STREAM);
+        expectSuccessfulDeployment(m_package6, null);
+    }
+
+    private void expectSuccessfulDeployment(TestPackage dpackage, Failure failure) throws Exception {
+        synchronized (m_servlet) {
+            if (failure != null) {
+                m_servlet.setFailure(Failure.VERSIONS_RETRY_AFTER);
+            }
+            m_servlet.addPackage(dpackage);
+            m_listener.getTopics().clear();
+        }
+        waitForEventReceived("org/osgi/service/deployment/INSTALL");
+        waitForEventReceived("org/osgi/service/deployment/COMPLETE");
+        waitForInstalledVersion(dpackage.getVersion());
+    }
+
+    private void waitForInstalledVersion(Version version) throws Exception {
+        ServiceReference reference = m_bundleContext.getServiceReference(AgentControl.class.getName());
+        AgentControl control = (AgentControl) m_bundleContext.getService(reference);
+        int timeout = 100;
+        while (!control.getDeploymentHandler().getInstalledVersion().equals(version)) {
+            Thread.sleep(100);
+            if (timeout-- <= 0) {
+                m_bundleContext.ungetService(reference);
+                fail("Timed out while waiting for deployment " + version);
+            }
+        }
+        m_bundleContext.ungetService(reference);
+    }
+
+    private void waitForEventReceived(String topic) throws Exception {
+        int timeout = 100;
+        while (!m_listener.getTopics().contains(topic)) {
+            Thread.sleep(100);
+            if (timeout-- <= 0) {
+                fail("Timed out while waiting for event " + topic);
+            }
+        }
+    }
+
+    private static File createPackage(String name, Version version, File... bundles) throws Exception {
+        DeploymentPackageBuilder builder = DeploymentPackageBuilder.createDeploymentPackage(name, version.toString());
+        for (File bundle : bundles) {
+            builder.addBundle(bundle.toURI().toURL());
+        }
+        File file = File.createTempFile("testpackage", ".jar");
+        OutputStream fos = new FileOutputStream(file);
+        builder.generate(fos);
+        fos.close();
+        return file;
+    }
+
+    private static File createBundle(String bsn, Version version, String... headers) throws Exception {
+        Builder b = new Builder();
+        b.setProperty("Bundle-SymbolicName", bsn);
+        b.setProperty("Bundle-Version", version.toString());
+        for (int i = 0; i < headers.length; i += 2) {
+            b.setProperty(headers[i], headers[i + 1]);
+        }
+        b.setProperty("Include-Resource", "bnd.bnd");
+        Jar jar = b.build();
+        jar.getManifest(); // Not sure whether this is needed...
+        File file = File.createTempFile("testbundle", ".jar");
+        jar.write(file);
+        return file;
+    }
+
+    private static class TestBundle {
+
+        private final String m_name;
+        private final Version m_version;
+        private final String[] m_headers;
+        private final File m_file;
+
+        public TestBundle(String name, Version version, String... headers) throws Exception {
+            m_name = name;
+            m_version = version;
+            m_headers = headers;
+            m_file = createBundle(name, version, headers);
+        }
+
+        public String getName() {
+            return m_name;
+        }
+
+        public Version getVersion() {
+            return m_version;
+        }
+
+        public String[] getHeaders() {
+            return m_headers;
+        }
+
+        public File getFile() {
+            return m_file;
+        }
+    }
+
+    private static class TestPackage {
+
+        private final String m_name;
+        private final Version m_version;
+        private final TestBundle[] m_bundles;
+        private final File m_file;
+
+        public TestPackage(String name, Version version, TestBundle... bundles) throws Exception {
+            m_name = name;
+            m_version = version;
+            m_bundles = bundles;
+
+            File[] files = new File[bundles.length];
+            for (int i = 0; i < bundles.length; i++) {
+                files[i] = bundles[i].getFile();
+            }
+            m_file = createPackage(name, version, files);
+        }
+
+        public String getName() {
+            return m_name;
+        }
+
+        public Version getVersion() {
+            return m_version;
+        }
+
+        public TestBundle[] getBundles() {
+            return m_bundles;
+        }
+
+        public File getFile() {
+            return m_file;
+        }
+    }
+
+    private static class TestEventListener implements EventListener {
+
+        private final List<String> m_topics = new ArrayList<String>();
+
+        @Override
+        public synchronized void handle(String topic, Map<String, String> payload) {
+            System.out.println("Event: " + topic + " => " + payload);
+            m_topics.add(topic);
+        }
+
+        public List<String> getTopics() {
+            return m_topics;
+        }
+    }
+
+    private 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;
+
+        private Failure m_failure;
+
+        public TestDeploymentServlet(String agentId) {
+            m_agentId = agentId;
+        }
+
+        @Override
+        protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+            String pathinfoTail = req.getPathInfo().replaceFirst("/" + 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, resp);
+            }
+        }
+
+        public synchronized void addPackage(TestPackage testPackage) {
+            m_packages.put(testPackage.getVersion().toString(), testPackage);
+        }
+
+        public synchronized void clearPackages() {
+            m_packages.clear();
+        }
+
+        public synchronized void setFailure(Failure failure) {
+            m_failure = failure;
+        }
+
+        private void sendPackage(TestPackage dpackage, HttpServletResponse resp) throws IOException {
+            if (m_failure == Failure.DEPLOYMENT_RETRY_AFTER) {
+                resp.addHeader("Retry-After", "3");
+                resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+                m_failure = null;
+                return;
+            }
+
+            long middle = dpackage.getFile().length() / 2;
+            FileInputStream fis = null;
+            OutputStream os = null;
+            try {
+                fis = new FileInputStream(dpackage.getFile());
+                os = resp.getOutputStream();
+
+                if (m_failure == Failure.EMPTY_STREAM) {
+                    m_failure = null;
+                    return;
+                }
+
+                if (m_failure == Failure.CORRUPT_STREAM) {
+                    os.write("garbage".getBytes());
+                    m_failure = null;
+                }
+
+                int b;
+                int count = 0;
+                while ((b = fis.read()) != -1) {
+                    os.write(b);
+                    if (count++ == middle && m_failure == Failure.ABORT_STREAM) {
+                        m_failure = null;
+                        break;
+                    }
+                }
+
+            }
+            finally {
+                fis.close();
+                if (os != null) {
+                    os.close();
+                }
+            }
+        }
+
+        private void sendVersions(HttpServletResponse resp) throws IOException {
+            if (m_failure == Failure.VERSIONS_RETRY_AFTER) {
+                resp.addHeader("Retry-After", "3");
+                resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+                m_failure = null;
+                return;
+            }
+            PrintWriter writer = resp.getWriter();
+            for (String version : m_packages.keySet()) {
+                writer.println(version);
+            }
+            writer.close();
+            resp.setContentType("text/plain");
+            resp.setStatus(200);
+        }
+    }
+
+    private static class TestUpdateServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            resp.setContentType("text/plain");
+            resp.setStatus(200);
+        }
+    }
+
+    private static class TestAuditlogServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        // FIXME Ignoring auditlog.. but why do we get and empty send if we set range to high?
+
+        @Override
+        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+            response.setContentType("text/plain");
+            PrintWriter writer = response.getWriter();
+            writer.println(request.getParameter("tid") + "," + request.getParameter("logid") + ",0-10");
+            writer.close();
+        }
+
+        @Override
+        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
+            InputStream is = request.getInputStream();
+            while (is.read() != -1) {
+            }
+            is.close();
+            response.setContentType("text/plain");
+        }
+    }
+}

Copied: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java (from r1516756, ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java)
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java?p2=ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java&p1=ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java&r1=1516756&r2=1518177&rev=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentExtensionTest.java Wed Aug 28 12:28:00 2013
@@ -18,22 +18,113 @@
  */
 package org.apache.ace.agent.itest;
 
-import junit.framework.Assert;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Properties;
 
+import org.apache.ace.agent.AgentConstants;
 import org.apache.ace.agent.AgentControl;
-import org.apache.ace.it.IntegrationTestBase;
+import org.apache.ace.agent.ConnectionHandler;
+import org.apache.ace.agent.DiscoveryHandler;
+import org.apache.ace.agent.IdentificationHandler;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
 
 /**
- * Integration test for Management Agent Configuration
- * 
+ * Integration test for Agent life-cycle. When the agent is configured to use external handler services, the agent must
+ * only be active and available if and when those external services are available. In addition, when multiple services
+ * for a handler are published the highest ranked should be used.
  */
-public class ManagementAgentTest extends IntegrationTestBase {
+public class AgentExtensionTest extends BaseAgentTest {
 
-    public void testOneAgentConfiguration() throws Exception {
+    public void testLifecycle() throws Exception {
 
-        // agent factory should be up
         AgentControl agentControl = getService(AgentControl.class);
-        Assert.assertNotNull(agentControl);
+        assertNotNull(agentControl);
 
+        getAgentBundle().stop();
+        System.setProperty(AgentConstants.CONFIG_IDENTIFICATION_DISABLED, "true");
+        System.setProperty(AgentConstants.CONFIG_DISCOVERY_DISABLED, "true");
+        System.setProperty(AgentConstants.CONFIG_CONNECTION_DISABLED, "true");
+        getAgentBundle().start();
+
+        assertNull(locateService(AgentControl.class));
+
+        ServiceRegistration idreg1 = registerIdentification("TEST1", 1);
+        assertNull(locateService(AgentControl.class));
+        ServiceRegistration direg1 = registerDiscovery(new URL("http://test1"), 1);
+        assertNull(locateService(AgentControl.class));
+        ServiceRegistration coreg1 = registerConnectionHandler();
+        assertNotNull(locateService(AgentControl.class));
+
+        assertEquals("TEST1", locateService(AgentControl.class).getAgentId());
+
+        ServiceRegistration idreg2 = registerIdentification("TEST2", 2);
+
+        assertEquals("TEST2", locateService(AgentControl.class).getAgentId());
+
+        idreg2.unregister();
+
+        assertEquals("TEST1", locateService(AgentControl.class).getAgentId());
+
+        idreg1.unregister();
+
+        assertNull(locateService(AgentControl.class));
+
+        direg1.unregister();
+        coreg1.unregister();
+    }
+
+    private ServiceRegistration registerIdentification(final String id, final int rank) {
+        return m_bundleContext
+            .registerService(IdentificationHandler.class.getName(), new IdentificationHandler() {
+
+                @Override
+                public String getAgentId() {
+                    return id;
+                }
+            }, new Properties() {
+                {
+                    put(Constants.SERVICE_RANKING, rank);
+                }
+            });
+
+    }
+
+    private ServiceRegistration registerDiscovery(final URL url, final int rank) {
+        return m_bundleContext
+            .registerService(DiscoveryHandler.class.getName(), new DiscoveryHandler() {
+
+                @Override
+                public URL getServerUrl() {
+                    return url;
+                }
+            }, new Properties() {
+                {
+                    put(Constants.SERVICE_RANKING, rank);
+                }
+            });
+
+    }
+
+    private ServiceRegistration registerConnectionHandler() {
+        return m_bundleContext
+            .registerService(ConnectionHandler.class.getName(), new ConnectionHandler() {
+
+                @Override
+                public URLConnection getConnection(URL url) throws IOException {
+                    return url.openConnection();
+                }
+            }, null);
+    }
+
+    private <T> T locateService(Class<T> iface) {
+        ServiceReference reference = m_bundleContext.getServiceReference(iface.getName());
+        if (reference == null) {
+            return null;
+        }
+        return (T) m_bundleContext.getService(reference);
     }
 }

Added: 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=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java (added)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/BaseAgentTest.java Wed Aug 28 12:28:00 2013
@@ -0,0 +1,69 @@
+package org.apache.ace.agent.itest;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Stack;
+
+import org.apache.ace.agent.AgentConstants;
+import org.apache.ace.agent.AgentControl;
+import org.apache.ace.it.IntegrationTestBase;
+import org.osgi.framework.Bundle;
+
+public abstract class BaseAgentTest extends IntegrationTestBase {
+
+    @Override
+    public void configureProvisionedServices() throws Exception {
+        resetAgentBundleState();
+    }
+
+    protected void resetAgentBundleState() throws Exception {
+        Bundle agentBundle = getAgentBundle();
+        System.out.println("BaseAgentTest: Stopping agent bundle");
+        File dataDir = agentBundle.getBundleContext().getDataFile("");
+        agentBundle.stop();
+        System.out.println("BaseAgentTest: Cleaning bundle data dir");
+        cleanDir(dataDir);
+        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)) {
+                keysBeRemoved.add((String) key);
+            }
+        }
+        for (String removeKey : keysBeRemoved) {
+            System.clearProperty(removeKey);
+        }
+        System.out.println("BaseAgentTest: Starting agent bundle");
+        agentBundle.start();
+    }
+
+    protected Bundle getAgentBundle() {
+        for (Bundle bundle : m_bundleContext.getBundles()) {
+            if (bundle.getSymbolicName().equals(AgentControl.class.getPackage().getName())) {
+                return bundle;
+            }
+        }
+        throw new IllegalStateException("No agentBundle found");
+    }
+
+    private void cleanDir(File dir) {
+        if (!dir.isDirectory()) {
+            throw new IllegalStateException();
+        }
+        Stack<File> dirs = new Stack<File>();
+        dirs.push(dir);
+        while (!dirs.isEmpty()) {
+            File currentDir = dirs.pop();
+            File[] files = currentDir.listFiles();
+            for (File file : files) {
+                if (file.isDirectory()) {
+                    dirs.push(file);
+                }
+                else {
+                    file.delete();
+                }
+            }
+        }
+    }
+}

Added: ace/trunk/org.apache.ace.agent.launcher/launcher-example.properties
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/launcher-example.properties?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/launcher-example.properties (added)
+++ ace/trunk/org.apache.ace.agent.launcher/launcher-example.properties Wed Aug 28 12:28:00 2013
@@ -0,0 +1,33 @@
+
+#
+# Agent properties:
+# 
+# These properties control the agent and may also be set through system properties. 
+# For a complete list and documentation see the AgentConstants.
+#
+agent.logging.level=DEBUG
+
+agent.identification.disabled=false
+agent.identification.agentid=Agent007
+
+agent.discovery.disabled=false
+agent.discovery.serverurls=http://localhost:80,http://localhost:8080
+agent.discovery.checking=true
+
+agent.controller.disabled=false
+agent.controller.syncdelay=10
+agent.controller.syncinterval=10
+agent.controller.streaming=false
+agent.controller.fixpackages=true
+agent.controller.retries=1
+
+agent.connection.disabled=false
+agent.connection.authtype=NONE
+
+agent.feedback.channels=auditlog,custom
+
+
+#
+# Framework properties; Keys are prepended by 'framework.'
+#
+framework.felix.log.level=1
\ No newline at end of file

Modified: ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Launcher.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Launcher.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Launcher.java (original)
+++ ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Launcher.java Wed Aug 28 12:28:00 2013
@@ -35,7 +35,9 @@ import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.ServiceLoader;
 
+import org.apache.ace.agent.AgentConstants;
 import org.apache.ace.agent.AgentControl;
+import org.apache.ace.agent.LoggingHandler;
 import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
@@ -94,33 +96,12 @@ public class Launcher {
             }
         }
 
+        // convenience debug override
         if (command.hasOption("v")) {
             configuration.put("verbose", "true");
+            configuration.put(AgentConstants.CONFIG_LOGGING_LEVEL, LoggingHandler.Levels.DEBUG.name());
         }
 
-        // // overwrite with user args
-        // if (command.hasOption("a")) {
-        // configuration.put(CONFIG_IDENTIFICATION_KEY,
-        // command.getOptionValue("a"));
-        // }
-        // if (command.hasOption("s")) {
-        // configuration.put(CONFIG_SERVERURL_KEY, command.getOptionValue("s"));
-        // }
-        // if (command.hasOption("v")) {
-        // configuration.put(CONFIG_LOGLEVEL_KEY, "DEBUG");
-        // }
-        //
-        // // set defaults
-        // if (!configuration.containsKey(CONFIG_LOGLEVEL_KEY)) {
-        // configuration.put(CONFIG_LOGLEVEL_KEY, "INFO");
-        // }
-        //
-        // // basic checks
-        // if (!configuration.containsKey(CONFIG_IDENTIFICATION_KEY)) {
-        // System.err.println("No agent specified");
-        // System.exit(1);
-        // }
-
         new Launcher(configuration).run();
     }
 
@@ -179,18 +160,18 @@ public class Launcher {
      * Main execution logic of the launcher; Start a framework, install bundles and pass configuration to the
      * {@link AgentFactory}.
      * 
-     * @throws Exception
-     *             on failure
+     * @throws Exception on failure
      */
     public void run() throws Exception {
 
         try {
             FrameworkFactory frameworkFactory = loadFrameworkFactory();
             Map<String, String> frameworkProperties = createFrameworkProperties();
-            if (m_verbose)
+            if (m_verbose) {
                 System.out.println("Launching OSGI framework\n factory\t: "
                     + frameworkFactory.getClass().getName()
                     + "\n properties\t: " + frameworkProperties);
+            }
 
             Framework framework = frameworkFactory.newFramework(frameworkProperties);
             BundleContext context = null;
@@ -202,10 +183,17 @@ public class Launcher {
                 installBundles(context, bundleProvider);
             }
 
+            for (Entry<String, String> entry : m_configuration.entrySet()) {
+                if (entry.getKey().startsWith(AgentConstants.CONFIG_KEY_NAMESPACE)) {
+                    System.setProperty(entry.getKey(), entry.getValue());
+                }
+            }
+
             framework.start();
 
-            if (m_verbose)
+            if (m_verbose) {
                 System.out.println("Startup complete..");
+            }
             framework.waitForStop(0);
         }
         catch (Exception e) {
@@ -219,8 +207,9 @@ public class Launcher {
     private Bundle[] installBundles(BundleContext context, BundleProvider extensionProvider) throws BundleException, IOException {
         List<Bundle> bundles = new ArrayList<Bundle>();
         for (String bundleName : extensionProvider.getBundleNames()) {
-            if (m_verbose)
+            if (m_verbose) {
                 System.out.println("Installing bundle\t: " + bundleName);
+            }
             InputStream inputStream = null;
             try {
                 inputStream = extensionProvider.getInputStream(bundleName);
@@ -241,8 +230,7 @@ public class Launcher {
      * Load {@link FrameworkFactory} through the {@link ServiceLoader}.
      * 
      * @return the first factory
-     * @throws Exception
-     *             on failure
+     * @throws Exception on failure
      */
     private FrameworkFactory loadFrameworkFactory() throws Exception {
         ServiceLoader<FrameworkFactory> frameworkFactoryLoader = ServiceLoader.load(FrameworkFactory.class);
@@ -257,8 +245,7 @@ public class Launcher {
      * Load {@link BundleProvider}s through the {@link ServiceLoader}.
      * 
      * @return list of providers
-     * @throws Exception
-     *             on failure
+     * @throws Exception on failure
      */
     private BundleProvider[] loadBundleProviders() throws Exception {
         ServiceLoader<BundleProvider> bundleFactoryLoader = ServiceLoader.load(BundleProvider.class);
@@ -274,15 +261,14 @@ public class Launcher {
      * Build the framework launch properties.
      * 
      * @return the launch properties
-     * @throws Exception
-     *             on failure
+     * @throws Exception on failure
      */
     private Map<String, String> createFrameworkProperties() throws Exception {
         Map<String, String> frameworkProperties = new HashMap<String, String>();
         for (Entry<String, String> entry : m_configuration.entrySet()) {
             if (entry.getKey().startsWith("framework.")) {
                 String frameworkKey = entry.getKey().replaceFirst("framework.", "");
-                String frameworkValue = m_configuration.get(entry.getValue());
+                String frameworkValue = m_configuration.get(entry.getKey());
                 frameworkProperties.put(frameworkKey, frameworkValue);
             }
         }
@@ -301,8 +287,7 @@ public class Launcher {
      * Determines the export clause for the agent API package.
      * 
      * @return the export clause
-     * @throws Exception
-     *             on failure
+     * @throws Exception on failure
      */
     private String getAgentApiPackageSpec() throws IOException {
         String apiPackage = AgentControl.class.getPackage().getName();

Modified: ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/launcher-defaults.properties
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/launcher-defaults.properties?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/launcher-defaults.properties (original)
+++ ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/launcher-defaults.properties Wed Aug 28 12:28:00 2013
@@ -1 +1,2 @@
-#TODO
\ No newline at end of file
+#TODO
+#framework.felix.log.level=4
\ No newline at end of file

Propchange: ace/trunk/org.apache.ace.agent.update.itest/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Aug 28 12:28:00 2013
@@ -0,0 +1,7 @@
+bin
+bin_test
+generated
+store
+bundle-cache
+felix-cache
+

Added: ace/trunk/org.apache.ace.agent.update.itest/.classpath
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/.classpath?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/.classpath (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/.classpath Wed Aug 28 12:28:00 2013
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/trunk/org.apache.ace.agent.update.itest/.gitignore
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/.gitignore?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/.gitignore (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/.gitignore Wed Aug 28 12:28:00 2013
@@ -0,0 +1,3 @@
+/bin/
+/bin_test/
+/generated/

Added: ace/trunk/org.apache.ace.agent.update.itest/.project
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/.project?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/.project (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/.project Wed Aug 28 12:28:00 2013
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.agent.update.itest</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/trunk/org.apache.ace.agent.update.itest/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/.settings/org.eclipse.jdt.core.prefs?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/.settings/org.eclipse.jdt.core.prefs (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/.settings/org.eclipse.jdt.core.prefs Wed Aug 28 12:28:00 2013
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7

Added: 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=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/bnd.bnd Wed Aug 28 12:28:00 2013
@@ -0,0 +1,49 @@
+# NOTE: This test is stored in a seperate from the main agent itest project because 
+# 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,\
+	org.apache.ace.agent;version=latest,\
+	org.apache.ace.test;version=latest,\
+	org.apache.felix.dependencymanager,\
+	osgi.cmpn,\
+	org.apache.felix.http.jetty,\
+	org.apache.ace.deployment.servlet;version=latest,\
+	org.apache.ace.deployment.api;version=latest,\
+	org.apache.ace.deployment.streamgenerator;version=latest,\
+	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.felix.configadmin,\
+	org.apache.ace.http.listener;version=latest,\
+	biz.aQute.bnd,\
+	org.apache.ace.builder;version=latest
+Private-Package: org.apache.ace.agent.itest
+-runee: JavaSE-1.6
+-runvm: -ea
+-runfw: org.apache.felix.framework
+-buildpath: osgi.core;version='[4.2,5)',\
+	org.apache.ace.agent;version=latest,\
+	org.apache.ace.test;version=latest,\
+	org.apache.felix.dependencymanager,\
+	org.apache.felix.http.jetty,\
+	biz.aQute.bnd,\
+	junit.osgi,\
+	org.mockito.mockito-all	
+-runsystempackages: sun.reflect
+-runproperties: org.apache.felix.log.storeDebug=true,\
+	org.apache.felix.eventadmin.Timeout=0,\
+	org.apache.ace.server.port=8080,\
+	org.osgi.service.http.port=8080,\
+	org.apache.felix.log.maxSize=1000
+Import-Package: org.apache.ace.agent,\
+	!org.osgi.service.component.annotations,\
+	*
+Bundle-Version: 1.0.0
+Bundle-Name: Apache ACE Agent itest
+Bundle-Description: Integration test bundle for the Apache ACE Agent
\ No newline at end of file

Added: ace/trunk/org.apache.ace.agent.update.itest/build.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/build.xml?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/build.xml (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/build.xml Wed Aug 28 12:28:00 2013
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build">
+
+	<!-- -->
+
+	<import file="../cnf/build.xml" />
+</project>

Added: ace/trunk/org.apache.ace.agent.update.itest/conf/org.apache.ace.deployment.servlet.agent.cfg
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/conf/org.apache.ace.deployment.servlet.agent.cfg?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/conf/org.apache.ace.deployment.servlet.agent.cfg (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/conf/org.apache.ace.deployment.servlet.agent.cfg Wed Aug 28 12:28:00 2013
@@ -0,0 +1,4 @@
+org.apache.ace.server.servlet.endpoint=/agent
+# OBR settings
+obr.url = http://localhost:${org.apache.ace.server.port}/obr/
+authentication.enabled = false

Added: ace/trunk/org.apache.ace.agent.update.itest/src/.gitignore
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/src/.gitignore?rev=1518177&view=auto
==============================================================================
    (empty)

Added: 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=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java (added)
+++ ace/trunk/org.apache.ace.agent.update.itest/src/org/apache/ace/agent/itest/AgentUpdateTest.java Wed Aug 28 12:28:00 2013
@@ -0,0 +1,209 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.ace.it.IntegrationTestBase;
+import org.apache.felix.dm.Component;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.service.http.HttpService;
+
+/**
+ * Tests updating the management agent. In fact it tests different failure paths first, and finally gets to update the
+ * agent. The tests it does are:
+ * <ul>
+ * <li>Try to update to a corrupt bundle (with some random garbage injected in the JAR file).</li>
+ * <li>Try to update to a bundle that does not resolve because of some impossible import package statement.</li>
+ * <li>Try to update to a bundle that does resolve, but does not start because of a non-existing bundle activator.</li>
+ * <li>Update to a new version of the agent (actually, it's the same bundle, but with a different version.</li>
+ * </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
+    }
+
+    private enum PhaseStatus {
+        ACTIVE, DONE
+    }
+
+    @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);
+    }
+
+    public void tearDown() throws Exception {
+        m_http.unregister("/obr");
+    }
+
+    public void testAgentUpdate() throws Exception {
+
+        int timeout = 50;
+        m_servlet.setPhase(Phase.CORRUPT_STREAM);
+        while (m_servlet.getPhaseStatus() == PhaseStatus.ACTIVE) {
+            Thread.sleep(200);
+            if (timeout-- <= 0) {
+                fail("Timed out while recovering from update with broken stream.");
+            }
+        }
+        timeout = 50;
+        m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_RESOLVE);
+        while (m_servlet.getPhaseStatus() == PhaseStatus.ACTIVE) {
+            Thread.sleep(200);
+            if (timeout-- <= 0) {
+                fail("Timed out while recovering from update with agent that does not resolve.");
+            }
+        }
+        timeout = 50;
+        m_servlet.setPhase(Phase.BUNDLE_DOES_NOT_START);
+        while (m_servlet.getPhaseStatus() == PhaseStatus.ACTIVE) {
+            Thread.sleep(200);
+            if (timeout-- <= 0) {
+                fail("Timed out while recovering from update with agent that does not start.");
+            }
+        }
+        timeout = 50;
+        m_servlet.setPhase(Phase.BUNDLE_WORKS);
+        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.");
+    }
+
+    private static class AgentUpdateOBRServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+        private Phase m_phase;
+        private PhaseStatus m_phaseStatus;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            String path = req.getPathInfo();
+            if ("/repository.xml".equals(path)) {
+                PrintWriter w = resp.getWriter();
+                w.println("<?xml version='1.0' encoding='utf-8'?><repository>");
+                w.println(createResource("org.apache.ace.agent", "1.0.0"));
+                w.println(createResource("org.apache.ace.agent", "2.0.0"));
+                w.println("</repository>");
+            }
+            else {
+                if (path.endsWith("1.0.0.jar")) {
+                    write(getBundle(), "1.0.0", resp.getOutputStream());
+                }
+                else if (path.endsWith("2.0.0.jar")) {
+                    write(getBundle(), "2.0.0", resp.getOutputStream());
+                }
+                else {
+                    throw new Error("Statement should never be reached.");
+                }
+            }
+        }
+
+        public synchronized void setPhase(Phase phase) {
+            m_phase = phase;
+            m_phaseStatus = PhaseStatus.ACTIVE;
+        }
+
+        public synchronized PhaseStatus getPhaseStatus() {
+            return m_phaseStatus;
+        }
+
+        private InputStream getBundle() throws IOException {
+            return new FileInputStream(new File("../org.apache.ace.agent/generated/org.apache.ace.agent.jar"));
+        }
+
+        private synchronized void write(InputStream object, String version, OutputStream outputStream) throws IOException {
+            JarInputStream jis = new JarInputStream(object);
+            Manifest manifest = jis.getManifest();
+            manifest.getMainAttributes().put(new Attributes.Name("Bundle-Version"), version);
+            if (m_phase == Phase.BUNDLE_DOES_NOT_START && "2.0.0".equals(version)) {
+                manifest.getMainAttributes().put(new Attributes.Name("Bundle-Activator"), "org.foo.NonExistingClass");
+            }
+            if (m_phase == Phase.BUNDLE_DOES_NOT_RESOLVE && "2.0.0".equals(version)) {
+                manifest.getMainAttributes().put(new Attributes.Name("Import-Package"), "org.foo.nonexistingpackage");
+            }
+            JarOutputStream jos = new JarOutputStream(outputStream, manifest);
+            JarEntry entry;
+            int length;
+            byte[] buffer = new byte[4096];
+            while ((entry = jis.getNextJarEntry()) != null) {
+                jos.putNextEntry(entry);
+                while ((length = jis.read(buffer)) != -1) {
+                    jos.write(buffer, 0, length);
+                    if (m_phase == Phase.CORRUPT_STREAM && "2.0.0".equals(version)) {
+                        jos.write("garbage".getBytes());
+                    }
+                }
+                jos.closeEntry();
+                jis.closeEntry();
+            }
+            jis.close();
+            jos.close();
+            if (m_phase == Phase.BUNDLE_WORKS && "2.0.0".equals(version)) {
+                m_phaseStatus = PhaseStatus.DONE;
+            }
+            if (m_phase != Phase.BUNDLE_WORKS && "1.0.0".equals(version)) {
+                m_phaseStatus = PhaseStatus.DONE;
+            }
+        }
+    }
+
+    private static String createResource(String bsn, String version) {
+        return "<resource id='" + bsn + "/" + version + "' symbolicname='" + bsn + "' version='" + version + "' uri='" + bsn + "-" + version + ".jar'></resource>";
+    }
+}

Added: ace/trunk/org.apache.ace.agent.update.itest/test/.gitignore
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.update.itest/test/.gitignore?rev=1518177&view=auto
==============================================================================
    (empty)

Added: ace/trunk/org.apache.ace.agent/README
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/README?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/README (added)
+++ ace/trunk/org.apache.ace.agent/README Wed Aug 28 12:28:00 2013
@@ -0,0 +1,14 @@
+
+TODOs:
+
+1) Download handler now store files in a tmp file and are not able to resume interrupted 
+downloads from a new handle. This should be changed to storage in the data dir and using 
+names that can be discovered and resumed.
+
+2) Download result provide access to the download through a File. This should be an 
+inputstream.
+
+
+3) EventsHandler/EVentListener do not yet support an interest list like eventadmin does.
+This should be added as it will help reduce event load if we start throwing more.
+

Modified: ace/trunk/org.apache.ace.agent/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/bnd.bnd?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent/bnd.bnd Wed Aug 28 12:28:00 2013
@@ -16,9 +16,7 @@ Private-Package: org.apache.ace.range,\
 
 # No wildcard import here on purpose. Are you sure the agent must 
 # require an extra external dependency? Probably not...
-Import-Package:javax.net.ssl,\
-	org.osgi.framework,\
-	org.osgi.service.packageadmin
+Import-Package: !org.apache.felix.dm, *
 
 # This is a minimal set on purpose. Are you really sure the agent must 
 # expose another package? Probably not...
@@ -27,6 +25,10 @@ Export-Package: org.apache.ace.agent,\
 	org.osgi.service.deploymentadmin.spi;-split-package:=merge-last
 
 
+# Keeping the agent as lean as possible. Remove debug when compiling
+# offline
+javac.debug:  off
+
 -buildpath: osgi.core;version=4.2,\
 	osgi.cmpn;version=4.2,\
 	javax.servlet;version=2.5,\

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=1518177&r1=1518176&r2=1518177&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 Wed Aug 28 12:28:00 2013
@@ -19,12 +19,163 @@
 package org.apache.ace.agent;
 
 /**
- * Compile time constants for this package.
- * 
+ * Compile time constants for this package. Includes configuration keys and event topics.
  */
 public interface AgentConstants {
 
     /**
+     * Namespace for all agent configuration property
+     */
+    String CONFIG_KEY_NAMESPACE = "agent";
+
+    /**
+     * Agent configuration property key postfix. When set to true, the system property will not overwrite an existing
+     * configuration value
+     */
+    String CONFIG_KEY_RETAIN = ".retain";
+
+    /**
+     * Configuration loglevel for default logger. Should be a valid options s specified by {@link LoggingHandler.Levels}
+     * , default is <code>INFO</code>.
+     */
+    String CONFIG_LOGGING_LEVEL = CONFIG_KEY_NAMESPACE + ".logging.level";
+
+    /**
+     * 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>.
+     */
+    String CONFIG_IDENTIFICATION_DISABLED = CONFIG_KEY_NAMESPACE + ".identification.disabled";
+
+    /**
+     * Configuration option for the agentid of the default identification handler. Should be a filesystem safe string,
+     * default is <code>defaultAgentID</code>/
+     */
+    String CONFIG_IDENTIFICATION_AGENTID = CONFIG_KEY_NAMESPACE + ".identification.agentid";
+
+    /**
+     * 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>.
+     */
+    String CONFIG_DISCOVERY_DISABLED = CONFIG_KEY_NAMESPACE + ".discovery.disabled";
+
+    /**
+     * Configuration option for the serverurls of the default discovery handler. Should be a comma-seperated list of
+     * valid urls, default is <code>http://localhost:8080</code>.
+     */
+    String CONFIG_DISCOVERY_SERVERURLS = CONFIG_KEY_NAMESPACE + ".discovery.serverurls";
+
+    /**
+     * Configuration option to enable checking for the default discovery handler. Should be e {true,false}, default is
+     * false.
+     */
+    String CONFIG_DISCOVERY_CHECKING = CONFIG_KEY_NAMESPACE + ".discovery.checking";
+
+    /**
+     * 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>.
+     */
+    String CONFIG_CONTROLLER_DISABLED = CONFIG_KEY_NAMESPACE + ".controller.disabled";
+
+    /**
+     * Configuration option to set streaming behavior of the default controller. Should be <code>{true,false}</code>,
+     * default is <code>true</code>.
+     */
+    String CONFIG_CONTROLLER_STREAMING = CONFIG_KEY_NAMESPACE + ".controller.streaming";
+
+    /**
+     * Configuration option to set fixpackages behavior of the default controller. Should be <code>{true,false}</code>,
+     * default is <code>true</code>.
+     */
+    String CONFIG_CONTROLLER_FIXPACKAGES = CONFIG_KEY_NAMESPACE + ".controller.fixpackages";
+
+    /**
+     * Configuration option to set retries behavior of the default controller. Should be an int, default is
+     * <code>1</code>.
+     */
+    String CONFIG_CONTROLLER_RETRIES = CONFIG_KEY_NAMESPACE + ".controller.retries";
+
+    /**
+     * Configuration option to set initial sync delay seconds of the default controller. Should be an int, default is
+     * <code>5</code>.
+     */
+    String CONFIG_CONTROLLER_SYNCDELAY = CONFIG_KEY_NAMESPACE + ".controller.syndelay";
+
+    /**
+     * Configuration option to set initial sync interval seconds of the default controller. Should be an int, default is
+     * <code>30</code>.
+     */
+    String CONFIG_CONTROLLER_SYNCINTERVAL = CONFIG_KEY_NAMESPACE + ".controller.syncinterval";
+
+    /**
+     * 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>.
+     */
+    String CONFIG_CONNECTION_DISABLED = CONFIG_KEY_NAMESPACE + ".connection.disabled";
+
+    /**
+     * Configuration auth type for the default {@link ConnectionHandler}. Should be a valid type as specified by
+     * {@link ConnectionHandler.Types}, default if <code>NONE</code>.
+     */
+    String CONFIG_CONNECTION_AUTHTYPE = CONFIG_KEY_NAMESPACE + ".connection.authtype";
+
+    /**
+     * Configuration option to set the basic authentication username for the default {@link ConnectionHandler}. Should
+     * be an string, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_USERNAME = CONFIG_KEY_NAMESPACE + ".connection.username";
+
+    /**
+     * Configuration option to set the basic authentication password for the default {@link ConnectionHandler}. Should
+     * be an string, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_PASSWORD = CONFIG_KEY_NAMESPACE + ".connection.password";
+
+    /**
+     * Configuration option to set the client-cert authentication keystore path for the default
+     * {@link ConnectionHandler} . Should be a valid path, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_KEYFILE = CONFIG_KEY_NAMESPACE + ".connection.keyfile";
+
+    /**
+     * Configuration option to set the client-cert authentication keystore password for the default
+     * {@link ConnectionHandler}. Should be a string, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_KEYPASS = CONFIG_KEY_NAMESPACE + ".connection.keypass";
+
+    /**
+     * Configuration option to set the client-cert authentication truststore path for the default
+     * {@link ConnectionHandler}. Should be a valid path, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_TRUSTFILE = CONFIG_KEY_NAMESPACE + ".connection.trustfile";
+
+    /**
+     * Configuration option to set the client-cert authentication truststore password for the default
+     * {@link ConnectionHandler}. Should be a string, default is <code>""</code>.
+     */
+    String CONFIG_CONNECTION_TRUSTPASS = CONFIG_KEY_NAMESPACE + ".connection.trustpass";
+
+    /**
+     * Configuration option to set the feedback channels for the default {@link FeedbackHandler}. Should be a
+     * comma-separated string, default is <code>auditlog</code>.
+     */
+    String CONFIG_FEEDBACK_CHANNELS = CONFIG_KEY_NAMESPACE + ".feedback.channels";
+
+    /**
+     * Event topic for deployment install events.
+     */
+    String EVENT_DEPLOYMENT_INSTALL = "org/osgi/service/deployment/INSTALL";
+
+    /**
+     * Event topic for deployment uninstall events.
+     */
+    String EVENT_DEPLOYMENT_UNINSTALL = "org/osgi/service/deployment/UNINSTALL";
+
+    /**
+     * Event topic for deployment install events.
+     */
+    String EVENT_DEPLOYMENT_COMPLETE = "org/osgi/service/deployment/COMPLETE";
+
+    /**
      * HTTP headers name for Deployment Package size estimate.
      */
     String HEADER_DPSIZE = "X-ACE-DPSize";

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentContext.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentContext.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentContext.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentContext.java Wed Aug 28 12:28:00 2013
@@ -19,81 +19,13 @@
 package org.apache.ace.agent;
 
 import java.io.File;
-import java.util.Dictionary;
-import java.util.Formatter;
-import java.util.concurrent.ScheduledExecutorService;
-
 
 /**
  * Internal interface that provides access to handlers, supporting services and static configuration.
- * 
  */
 public interface AgentContext {
 
     /**
-     * Return the identification handler.
-     * 
-     * @return The handler
-     */
-    IdentificationHandler getIdentificationHandler();
-
-    /**
-     * Return the discovery handler.
-     * 
-     * @return The handler
-     */
-    DiscoveryHandler getDiscoveryHandler();
-
-    /**
-     * Return the connection handler.
-     * 
-     * @return The handler
-     */
-    ConnectionHandler getConnectionHandler();
-
-    /**
-     * Return the deployment handler.
-     * 
-     * @return The handler
-     */
-    DeploymentHandler getDeploymentHandler();
-
-    /**
-     * Return the download handler.
-     * 
-     * @return The handler
-     */
-    DownloadHandler getDownloadHandler();
-
-    /**
-     * Return the configuration handler.
-     * 
-     * @return The handler
-     */
-    ConfigurationHandler getConfigurationHandler();
-
-    /**
-     * Return the update handler.
-     * 
-     * @return The handler
-     */
-    AgentUpdateHandler getAgentUpdateHandler();
-
-    /**
-     * Return the feedback handler.
-     * 
-     * @return The handler
-     */
-    FeedbackHandler getFeedbackHandler();
-
-    /**
-     * Return the executor service.
-     * 
-     * @return The service
-     */
-    ScheduledExecutorService getExecutorService();
-
-    /**
      * Return the work directory.
      * 
      * @return The directory
@@ -101,95 +33,10 @@ public interface AgentContext {
     File getWorkDir();
 
     /**
-     * Post an event to any eventAdmin services outside the agent available at this time. There is no guarantee on
-     * delivery. Only string values are supported to avoid any potential class-loading issues.
-     * 
-     * @param topic The topic
-     * @param properties The payload
-     */
-    void postEvent(String topic, Dictionary<String, String> payload);
-
-    /**
-     * Log a debug message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logDebug(String component, String message, Object... args);
-
-    /**
-     * Log a debug message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param cause The cause, may be <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logDebug(String component, String message, Throwable cause, Object... args);
-
-    /**
-     * Log an info message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logInfo(String component, String message, Object... args);
-
-    /**
-     * Log an info message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param cause The cause, may be <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logInfo(String component, String message, Throwable cause, Object... args);
-
-    /**
-     * Log a warning message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logWarning(String component, String message, Object... args);
-
-    /**
-     * Log a warning message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param cause The cause, may be <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logWarning(String component, String message, Throwable cause, Object... args);
-
-    /**
-     * Log an error message. If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
-     * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param args The optional formatter arguments
-     */
-    void logError(String component, String message, Object... args);
-
-    /**
-     * Log an error message.If <code>args</code> are provided the message will be processed as a format using the
-     * standard {@link Formatter}.
+     * Return the handler for a specified interface.
      * 
-     * @param component The component identifier, not <code>null</code>
-     * @param message The log message or format, not <code>null</code>
-     * @param cause The cause, may be <code>null</code>
-     * @param args The optional formatter arguments
+     * @param iface An interface
+     * @return The handler, or <code>null</code>
      */
-    void logError(String component, String message, Throwable cause, Object... args);
+    <T> T getHandler(Class<T> iface);
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentControl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentControl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentControl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentControl.java Wed Aug 28 12:28:00 2013
@@ -24,6 +24,9 @@ package org.apache.ace.agent;
  */
 public interface AgentControl {
 
+    /** Returns the agent's identifier */
+    String getAgentId();
+    
     /** Returns the configuration handler */
     ConfigurationHandler getConfigurationHandler();
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java Wed Aug 28 12:28:00 2013
@@ -1,3 +1,21 @@
+/*
+ * 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;
 
 import java.io.IOException;
@@ -7,8 +25,7 @@ import java.util.SortedSet;
 import org.osgi.framework.Version;
 
 /**
- * Agent control delegate interface that is responsible for managing agent updates.
- *
+ * Agent context delegate interface that is responsible for managing agent updates.
  */
 public interface AgentUpdateHandler {
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConfigurationHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConfigurationHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConfigurationHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConfigurationHandler.java Wed Aug 28 12:28:00 2013
@@ -21,10 +21,11 @@ package org.apache.ace.agent;
 import java.util.Set;
 
 /**
- * Agent control delegate interface that is responsible for managing persisted configuration. External launchers may
- * override or set values within the {@link CONFIG_KEY_NAMESPACE} through system properties when the agent starts. If
- * the launcher wants to retain existing persisted values, instead of overwriting them, it should specify an additional
- * property with the same name post-fixed with {@link CONFIG_KEY_RETAIN} set to <code>true</code>. <br/>
+ * Agent context delegate interface that is responsible for managing persisted configuration. External launchers may
+ * override or set values within the {@link AgentConstants.CONFIG_KEY_NAMESPACE} through system properties when the
+ * agent starts. If the launcher wants to retain existing persisted values, instead of overwriting them, it should
+ * specify an additional property with the same name post-fixed with {@link AgentConstants.CONFIG_KEY_RETAIN} set to
+ * <code>true</code>. <br/>
  * <br/>
  * Example: A launcher that wants to ensure the syncinterval is set to 3000 only when not configuration is already set
  * should specify the following two system properties:<br/>
@@ -34,16 +35,6 @@ import java.util.Set;
 public interface ConfigurationHandler {
 
     /**
-     * Key namespace; All system property keys that start with this are considered.
-     */
-    String CONFIG_KEY_NAMESPACE = "ace.agent";
-
-    /**
-     * Retain postfix; The postfix for override property keys.
-     */
-    String CONFIG_KEY_RETAIN = ".retain";
-
-    /**
      * Return an unmodifiable copy of the configuration keys.
      * 
      * @return The set of keys

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConnectionHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConnectionHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConnectionHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ConnectionHandler.java Wed Aug 28 12:28:00 2013
@@ -23,12 +23,18 @@ import java.net.URL;
 import java.net.URLConnection;
 
 /**
- * Agent control delegate interface that is responsible for opening connection.
- * 
+ * Agent context delegate interface that is responsible for opening connection.
  */
 public interface ConnectionHandler {
 
     /**
+     * Supported authentication types.
+     */
+    enum Types {
+        NONE, BASIC, CLIENTCERT;
+    }
+
+    /**
      * Return a connection for the specified url.
      * 
      * @param url The URL

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java Wed Aug 28 12:28:00 2013
@@ -23,10 +23,10 @@ import java.io.InputStream;
 import java.util.SortedSet;
 
 import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentException;
 
 /**
- * Agent control delegate interface that provides the deployment functions.
- * 
+ * Agent context delegate interface that provides the deployment functions.
  */
 public interface DeploymentHandler {
 
@@ -41,50 +41,38 @@ public interface DeploymentHandler {
      * Return the sorted set of available deployment package versions as reported by the server.
      * 
      * @return The sorted set of versions, may be empty
-     * @throws RetryAfterException
-     *             If the server indicates it is too busy with a Retry-After header
-     * @throws IOException
-     *             If the connection to the server fails
+     * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
+     * @throws IOException If the connection to the server fails
      */
     SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException;
 
     /**
      * Return the estimated size for a deployment package as reported by the server.
      * 
-     * @param version
-     *            The version of the package
-     * @param fixPackage
-     *            Request the server for a fix-package
+     * @param version The version of the package
+     * @param fixPackage Request the server for a fix-package
      * @return The estimated size in bytes, <code>-1</code> indicates the size is unknown
-     * @throws RetryAfterException
-     *             If the server indicates it is too busy with a Retry-After header
-     * @throws IOException
-     *             If the connection to the server fails
+     * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
+     * @throws IOException If the connection to the server fails
      */
     long getPackageSize(Version version, boolean fixPackage) throws RetryAfterException, IOException;
 
     /**
      * Returns the {@link InputStream} for a deployment package.
      * 
-     * @param version
-     *            The version of the deployment package
-     * @param fixPackage
-     *            Request the server for a fix-package
+     * @param version The version of the deployment package
+     * @param fixPackage Request the server for a fix-package
      * @return The input-stream for the deployment package
-     * @throws RetryAfterException
-     *             If the server indicates it is too busy with a Retry-After header
-     * @throws IOException
-     *             If the connection to the server fails
+     * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
+     * @throws IOException If the connection to the server fails
      */
     InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException;
 
     /**
      * Return the {@link DownloadHandle} for a deployment package.
      * 
-     * @param version
-     *            The version of the deployment package
-     * @param fixPackage
-     *            Request the server for a fix-package
+     * @param version The version of the deployment package
+     * @param fixPackage Request the server for a fix-package
      * @return The download handle
      */
     DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException, IOException;
@@ -92,11 +80,9 @@ public interface DeploymentHandler {
     /**
      * Install a deployment package from an input stream.
      * 
-     * @param inputStream
-     *            The inputStream, not <code>null</code>
-     * @throws IOException
-     *             If reading the input stream fails.
+     * @param inputStream The inputStream, not <code>null</code>
+     * @throws IOException If reading the input stream fails.
      */
-    // TODO deployment exceptions
-    void deployPackage(InputStream inputStream) throws IOException;
+    // TODO should we expose the foreign exception?
+    void deployPackage(InputStream inputStream) throws DeploymentException, IOException;
 }