ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1518177 [2/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...
Date Wed, 28 Aug 2013 12:28:02 GMT
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DiscoveryHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DiscoveryHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DiscoveryHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DiscoveryHandler.java Wed Aug 28 12:28:00 2013
@@ -21,9 +21,8 @@ package org.apache.ace.agent;
 import java.net.URL;
 
 /**
- * Agent control delegate interface that is responsible for discovering servers. If the handler supports dynamic
+ * Agent context delegate interface that is responsible for discovering servers. If the handler supports dynamic
  * discovery or multiple URLs it should select the most appropriate candidate.
- * 
  */
 public interface DiscoveryHandler {
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java Wed Aug 28 12:28:00 2013
@@ -40,12 +40,13 @@ public interface DownloadResult {
      * 
      * @return The file, <code>null</code> if the download was unsuccessful
      */
-    //TODO inputstream
+    // TODO inputstream
     File getFile();
 
     int getCode();
-    
+
     Map<String, List<String>> getHeaders();
+
     /**
      * Return the cause of an unsuccessful download.
      * 

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventListener.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventListener.java?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventListener.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventListener.java Wed Aug 28 12:28:00 2013
@@ -0,0 +1,18 @@
+package org.apache.ace.agent;
+
+import java.util.Map;
+
+/**
+ * Listener interface for consumers that wish to be notified of agent events. This includes events deployment events as
+ * defined by the OSGi DeploymentAdmin specification.F
+ */
+public interface EventListener {
+
+    /**
+     * Event callback.
+     * 
+     * @param topic The topic string
+     * @param payload An unmodifiable map
+     */
+    void handle(String topic, Map<String, String> payload);
+}

Copied: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventsHandler.java (from r1517469, ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java)
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventsHandler.java?p2=ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventsHandler.java&p1=ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java&r1=1517469&r2=1518177&rev=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/EventsHandler.java Wed Aug 28 12:28:00 2013
@@ -16,17 +16,42 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ace.agent.impl;
+package org.apache.ace.agent;
 
-import java.util.Dictionary;
-
-import org.apache.ace.agent.AgentContext;
+import java.util.Map;
 
 /**
- * Agent context delegate interface that is responsible for handling events. This is an internal interface as event
- * methods are exposed on the {@link AgentContext} directly.
+ * Agent context delegate interface that is responsible for handling events.
  */
 public interface EventsHandler {
 
-    void postEvent(String topic, Dictionary<String, String> payload);
+    /**
+     * Post an event asynchronously.
+     * 
+     * @param topic The topic string
+     * @param payload The payload map
+     */
+    void postEvent(String topic, Map<String, String> payload);
+
+    /**
+     * Post an event synchronously.
+     * 
+     * @param topic The topic string
+     * @param payload The payload map
+     */
+    void sendEvent(String topic, Map<String, String> payload);
+
+    /**
+     * Add a listener.
+     * 
+     * @param listener The listener
+     */
+    void addListener(EventListener listener);
+
+    /**
+     * Remove a listener.
+     * 
+     * @param listener The listener
+     */
+    void removeListener(EventListener listener);
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackChannel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackChannel.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackChannel.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackChannel.java Wed Aug 28 12:28:00 2013
@@ -23,7 +23,6 @@ import java.util.Map;
 
 
 /**
- * 
  *
  */
 public interface FeedbackChannel {

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/FeedbackHandler.java Wed Aug 28 12:28:00 2013
@@ -22,7 +22,7 @@ import java.io.IOException;
 import java.util.Set;
 
 /**
- * Agent control delegate interface that is responsible for handling feedback channels.
+ * Agent context delegate interface that is responsible for handling feedback channels.
  */
 public interface FeedbackHandler {
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/IdentificationHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/IdentificationHandler.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/IdentificationHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/IdentificationHandler.java Wed Aug 28 12:28:00 2013
@@ -19,8 +19,7 @@
 package org.apache.ace.agent;
 
 /**
- * Agent control delegate interface that is responsible for target identification.
- * 
+ * Agent context delegate interface that is responsible for target identification.
  */
 public interface IdentificationHandler {
 

Copied: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/LoggingHandler.java (from r1517469, ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java)
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/LoggingHandler.java?p2=ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/LoggingHandler.java&p1=ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java&r1=1517469&r2=1518177&rev=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/LoggingHandler.java Wed Aug 28 12:28:00 2013
@@ -16,18 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ace.agent.impl;
+package org.apache.ace.agent;
 
 import java.util.Formatter;
 
-import org.apache.ace.agent.AgentContext;
-
 /**
- * Agent context delegate interface that is responsible for logging. This is an internal interface as log methods are
- * exposed on the {@link AgentContext} directly.
+ * Agent context delegate interface that is responsible for logging.
  */
 public interface LoggingHandler {
 
+    enum Levels {
+        DEBUG, INFO, WARNING, ERROR;
+    }
+
     /**
      * Log an debug message. If <code>args</code> are provided the message will be processed as a format using the
      * standard {@link Formatter}.

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/RetryAfterException.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/RetryAfterException.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/RetryAfterException.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/RetryAfterException.java Wed Aug 28 12:28:00 2013
@@ -18,6 +18,9 @@
  */
 package org.apache.ace.agent;
 
+/**
+ * Exception that indicates that the upstream server responded with a Retry-After.
+ */
 public class RetryAfterException extends Exception {
 
     private static final long serialVersionUID = 1L;
@@ -27,8 +30,8 @@ public class RetryAfterException extends
         super("Server too busy. Retry after " + seconds + " seconds");
         m_seconds = seconds;
     }
-    
-    public int getSeconds(){
+
+    public int getSeconds() {
         return m_seconds;
     }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java Wed Aug 28 12:28:00 2013
@@ -18,30 +18,27 @@
  */
 package org.apache.ace.agent.impl;
 
-import static org.apache.ace.agent.impl.ReflectionUtil.configureField;
-import static org.apache.ace.agent.impl.ReflectionUtil.invokeMethod;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 
+import org.apache.ace.agent.AgentConstants;
 import org.apache.ace.agent.AgentControl;
+import org.apache.ace.agent.AgentUpdateHandler;
+import org.apache.ace.agent.ConfigurationHandler;
 import org.apache.ace.agent.ConnectionHandler;
+import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.DiscoveryHandler;
+import org.apache.ace.agent.DownloadHandler;
+import org.apache.ace.agent.EventsHandler;
+import org.apache.ace.agent.FeedbackHandler;
 import org.apache.ace.agent.IdentificationHandler;
+import org.apache.ace.agent.LoggingHandler;
 import org.apache.ace.agent.impl.DependencyTrackerImpl.DependencyCallback;
 import org.apache.ace.agent.impl.DependencyTrackerImpl.LifecycleCallbacks;
-import org.apache.felix.deploymentadmin.DeploymentAdminImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.deploymentadmin.DeploymentAdmin;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.log.LogService;
 import org.osgi.service.packageadmin.PackageAdmin;
 
 /**
@@ -49,18 +46,12 @@ import org.osgi.service.packageadmin.Pac
  */
 public class Activator implements BundleActivator {
 
-    // internal delegates
-    private final EventsHandlerImpl m_internalEvents = new EventsHandlerImpl();
-    private final LoggingHandlerImpl m_internalLogger = new LoggingHandlerImpl(LogService.LOG_DEBUG);
-
     // managed state
-    private AgentContextImpl m_agentContext;
-    private AgentControlImpl m_agentControl;
-    private ScheduledExecutorService m_executorService;
-    private EventLoggerImpl m_eventLoggerImpl;
-    private DefaultController m_defaultController;
-    private volatile DeploymentAdmin m_deploymentAdmin;
-    private ServiceRegistration m_agentControlRegistration;
+    private volatile AgentContextImpl m_agentContext;
+    private volatile ScheduledExecutorService m_executorService;
+    private volatile ServiceRegistration m_agentControlRegistration;
+    private volatile BundleContext m_bundleContext;
+    private volatile DependencyTrackerImpl m_dependencyTracker;
 
     // injected services
     private volatile PackageAdmin m_packageAdmin;
@@ -68,15 +59,13 @@ public class Activator implements Bundle
     private volatile DiscoveryHandler m_discoveryHandler;
     private volatile ConnectionHandler m_connectionHandler;
 
-    private volatile BundleContext m_bundleContext;
-    private DependencyTrackerImpl m_dependencyTracker;
-
     @Override
     public void start(final BundleContext bundleContext) throws Exception {
 
         m_bundleContext = bundleContext;
         m_executorService = Executors.newScheduledThreadPool(1, new InternalThreadFactory());
 
+        // FIXME minimize
         m_dependencyTracker = new DependencyTrackerImpl(bundleContext, new LifecycleCallbacks() {
 
             @Override
@@ -101,15 +90,13 @@ public class Activator implements Bundle
         });
 
         m_dependencyTracker.addDependency(PackageAdmin.class, null, new DependencyCallback() {
-
             @Override
             public void updated(Object service) {
                 m_packageAdmin = (PackageAdmin) service;
             }
         });
 
-        // FIXME fake config
-        if (Boolean.parseBoolean(System.getProperty("agent.identificationhandler.disabled"))) {
+        if (Boolean.parseBoolean(System.getProperty(AgentConstants.CONFIG_IDENTIFICATION_DISABLED))) {
             m_dependencyTracker.addDependency(IdentificationHandler.class, null, new DependencyCallback() {
                 @Override
                 public void updated(Object service) {
@@ -117,8 +104,8 @@ public class Activator implements Bundle
                 }
             });
         }
-        // FIXME fake config
-        if (Boolean.parseBoolean(System.getProperty("agent.discoveryhandler.disabled"))) {
+
+        if (Boolean.parseBoolean(System.getProperty(AgentConstants.CONFIG_DISCOVERY_DISABLED))) {
             m_dependencyTracker.addDependency(DiscoveryHandler.class, null, new DependencyCallback() {
                 @Override
                 public void updated(Object service) {
@@ -126,8 +113,8 @@ public class Activator implements Bundle
                 }
             });
         }
-        // FIXME fake config
-        if (Boolean.parseBoolean(System.getProperty("agent.connectionhandler.disabled"))) {
+
+        if (Boolean.parseBoolean(System.getProperty(AgentConstants.CONFIG_CONNECTION_DISABLED))) {
             m_dependencyTracker.addDependency(ConnectionHandler.class, null, new DependencyCallback() {
                 @Override
                 public void updated(Object service) {
@@ -146,162 +133,52 @@ public class Activator implements Bundle
         m_executorService = null;
     }
 
-    void startAgent() throws Exception {
-
-        m_internalLogger.logInfo("activator", "Agent starting...", null);
-
-        m_deploymentAdmin = new DeploymentAdminImpl();
-        configureField(m_deploymentAdmin, BundleContext.class, m_bundleContext);
-        configureField(m_deploymentAdmin, PackageAdmin.class, m_packageAdmin);
-        configureField(m_deploymentAdmin, EventAdmin.class, new InternalEventAdmin(m_internalEvents));
-        configureField(m_deploymentAdmin, LogService.class, new InternalLogService(m_internalLogger, "deployment"));
-        invokeMethod(m_deploymentAdmin, "start", new Class<?>[] {}, new Object[] {});
+    private void startAgent() throws Exception {
 
         m_agentContext = new AgentContextImpl(m_bundleContext.getDataFile(""));
-        m_agentContext.setLoggingHandler(m_internalLogger);
-        m_agentContext.setEventsHandler(m_internalEvents);
-        m_agentContext.setConfigurationHandler(new ConfigurationHandlerImpl());
-        m_agentContext.setExecutorService(m_executorService);
-        m_agentContext.setConnectionHandler(new ConnectionHandlerImpl());
-        m_agentContext.setIdentificationHandler(new IdentificationHandlerImpl());
-        m_agentContext.setDiscoveryHandler(new DiscoveryHandlerImpl());
-        m_agentContext.setDownloadHandler(new DownloadHandlerImpl());
-        m_agentContext.setDeploymentHandler(new DeploymentHandlerImpl(m_deploymentAdmin));
-        m_agentContext.setAgentUpdateHandler(new AgentUpdateHandlerImpl(m_bundleContext));
-        m_agentContext.setFeedbackHandler(new FeedbackHandlerImpl());
-        m_agentContext.start();
-        m_internalLogger.logInfo("activator", "AgentContext started", null);
+        m_agentContext.setHandler(LoggingHandler.class, new LoggingHandlerImpl());
+        m_agentContext.setHandler(ConfigurationHandler.class, new ConfigurationHandlerImpl());
+        m_agentContext.setHandler(EventsHandler.class, new EventsHandlerImpl(m_bundleContext));
+        m_agentContext.setHandler(ScheduledExecutorService.class, m_executorService);
+        m_agentContext.setHandler(DownloadHandler.class, new DownloadHandlerImpl());
+        m_agentContext.setHandler(DeploymentHandler.class, new DeploymentHandlerImpl(m_bundleContext, m_packageAdmin));
+        m_agentContext.setHandler(AgentUpdateHandler.class, new AgentUpdateHandlerImpl(m_bundleContext));
+        m_agentContext.setHandler(FeedbackHandler.class, new FeedbackHandlerImpl());
 
-        m_agentControl = new AgentControlImpl(m_agentContext);
-        m_agentControlRegistration = m_bundleContext.registerService(AgentControl.class.getName(), m_agentControl, null);
-        m_internalLogger.logInfo("activator", "AgentControl registered", null);
-
-        m_defaultController = new DefaultController();
-        m_defaultController.start(m_agentContext);
-        m_internalLogger.logInfo("activator", "DefaultController started", null);
-
-        // FIXME fake config
-        if (!Boolean.parseBoolean(System.getProperty("agent.auditlogging.disabled"))) {
-            m_eventLoggerImpl = new EventLoggerImpl(m_agentControl, m_bundleContext);
-            m_bundleContext.addBundleListener(m_eventLoggerImpl);
-            m_bundleContext.addFrameworkListener(m_eventLoggerImpl);
-            m_internalEvents.registerHandler(m_eventLoggerImpl, EventLoggerImpl.TOPICS_INTEREST);
-            m_internalLogger.logInfo("activator", "Audit logger started", null);
+        if (m_identificationHandler != null) {
+            m_agentContext.setHandler(IdentificationHandler.class, m_identificationHandler);
         }
         else {
-            m_internalLogger.logInfo("activator", "Audit logger disabled", null);
-        }
-        m_internalLogger.logInfo("activator", "Agent statup complete", null);
-    }
-
-    void stopAgent() throws Exception {
-
-        m_internalLogger.logInfo("activator", "Agent stopping..", null);
-
-        m_agentControlRegistration.unregister();
-        m_agentControlRegistration = null;
-
-        m_defaultController.stop();
-        m_defaultController = null;
-
-        invokeMethod(m_deploymentAdmin, "stop", new Class<?>[] {}, new Object[] {});
-
-        if (m_eventLoggerImpl != null) {
-            m_bundleContext.removeFrameworkListener(m_eventLoggerImpl);
-            m_bundleContext.removeBundleListener(m_eventLoggerImpl);
-            m_internalEvents.unregisterHandler(m_eventLoggerImpl);
+            m_agentContext.setHandler(IdentificationHandler.class, new IdentificationHandlerImpl());
         }
 
-        m_agentContext.stop();
-        m_agentContext = null;
-
-        m_internalLogger.logInfo("activator", "Agent stopped", null);
-    }
-
-    private void configureDeploymentAdmin() {
-        m_deploymentAdmin = new DeploymentAdminImpl();
-        configureField(m_deploymentAdmin, BundleContext.class, m_bundleContext);
-        configureField(m_deploymentAdmin, PackageAdmin.class, m_packageAdmin);
-        configureField(m_deploymentAdmin, EventAdmin.class, new InternalEventAdmin(m_internalEvents));
-        configureField(m_deploymentAdmin, LogService.class, new InternalLogService(m_internalLogger, "deployment"));
-        invokeMethod(m_deploymentAdmin, "start", new Class<?>[] {}, new Object[] {});
-    }
-
-    /**
-     * Internal EventAdmin that delegates to actual InternalEvents. Used to inject into the DeploymentAdmin only.
-     */
-    static class InternalEventAdmin implements EventAdmin {
-
-        private final EventsHandler m_events;
-
-        public InternalEventAdmin(EventsHandler events) {
-            m_events = events;
+        if (m_discoveryHandler != null) {
+            m_agentContext.setHandler(DiscoveryHandler.class, m_discoveryHandler);
         }
-
-        @Override
-        public void postEvent(Event event) {
-            m_events.postEvent(event.getTopic(), getPayload(event));
-        }
-
-        @Override
-        public void sendEvent(Event event) {
-            m_events.postEvent(event.getTopic(), getPayload(event));
-        }
-
-        private static Dictionary<String, String> getPayload(Event event) {
-            Dictionary<String, String> payload = new Hashtable<String, String>();
-            for (String propertyName : event.getPropertyNames()) {
-                payload.put(propertyName, event.getProperty(propertyName).toString());
-            }
-            return payload;
+        else {
+            m_agentContext.setHandler(DiscoveryHandler.class, new DiscoveryHandlerImpl());
         }
-    }
-
-    /**
-     * Internal LogService that wraps delegates to actual InternalLogger. Used to inject into the DeploymentAdmin only.
-     */
-    static class InternalLogService implements LogService {
-
-        private final LoggingHandler m_logger;
-        private final String m_identifier;
 
-        public InternalLogService(LoggingHandler logger, String identifier) {
-            m_logger = logger;
-            m_identifier = identifier;
+        if (m_connectionHandler != null) {
+            m_agentContext.setHandler(ConnectionHandler.class, m_connectionHandler);
         }
-
-        @Override
-        public void log(int level, String message) {
-            log(level, message, null);
+        else {
+            m_agentContext.setHandler(ConnectionHandler.class, new ConnectionHandlerImpl());
         }
 
-        @Override
-        public void log(int level, String message, Throwable exception) {
-            switch (level) {
-                case LogService.LOG_WARNING:
-                    m_logger.logWarning(m_identifier, message, exception);
-                    return;
-                case LogService.LOG_INFO:
-                    m_logger.logInfo(m_identifier, message, exception);
-                    return;
-                case LogService.LOG_DEBUG:
-                    m_logger.logDebug(m_identifier, message, exception);
-                    return;
-                default:
-                    m_logger.logError(m_identifier, message, exception);
-                    return;
-            }
-        }
+        m_agentContext.addComponent(new DefaultController());
+        m_agentContext.addComponent(new EventLoggerImpl(m_bundleContext));
+        m_agentContext.start();
 
-        @Override
-        public void log(ServiceReference sr, int level, String message) {
-            log(level, message, null);
-        }
+        m_agentControlRegistration = m_bundleContext.registerService(
+            AgentControl.class.getName(), new AgentControlImpl(m_agentContext), null);
+    }
 
-        @Override
-        public void log(ServiceReference sr, int level, String message, Throwable exception) {
-            log(level, message, exception);
-        }
+    private void stopAgent() throws Exception {
+        m_agentControlRegistration.unregister();
+        m_agentControlRegistration = null;
+        m_agentContext.stop();
+        m_agentContext = null;
     }
 
     /**
@@ -315,8 +192,8 @@ public class Activator implements Bundle
         @Override
         public Thread newThread(Runnable r) {
             Thread thread = new Thread(r, String.format(m_name, ++m_count));
+            thread.setDaemon(true);
             return thread;
         }
     }
-
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentContextImpl.java Wed Aug 28 12:28:00 2013
@@ -19,7 +19,10 @@
 package org.apache.ace.agent.impl;
 
 import java.io.File;
-import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ScheduledExecutorService;
 
 import org.apache.ace.agent.AgentContext;
@@ -30,60 +33,72 @@ import org.apache.ace.agent.ConnectionHa
 import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.DiscoveryHandler;
 import org.apache.ace.agent.DownloadHandler;
+import org.apache.ace.agent.EventsHandler;
 import org.apache.ace.agent.FeedbackHandler;
 import org.apache.ace.agent.IdentificationHandler;
+import org.apache.ace.agent.LoggingHandler;
 
 /**
  * Implementation of the internal agent context service.
- * 
  */
 public class AgentContextImpl implements AgentContext {
 
-    // All service are volatile because they may be updated at runtime.
-    private volatile ConfigurationHandler m_configurationHandler;
-    private volatile IdentificationHandler m_identificationHandler;
-    private volatile DiscoveryHandler m_discoveryHandler;
-    private volatile DeploymentHandler m_deploymentHandler;
-    private volatile DownloadHandler m_downloadHandler;
-    private volatile ConnectionHandler m_connectionHandler;
-    private volatile AgentUpdateHandler m_agentUpdateHandler;
-    private volatile FeedbackHandler m_feedbackHandler;
-    private volatile LoggingHandler m_loggingHandler;
-    private volatile EventsHandler m_eventsHandler;
-    private volatile ScheduledExecutorService m_executorService;
+    // List of required handler in startup order
+    public static final Class<?>[] KNOWN_HANDLERS = new Class<?>[]
+    {
+        LoggingHandler.class,
+        ConfigurationHandler.class,
+        IdentificationHandler.class,
+        DiscoveryHandler.class,
+        DeploymentHandler.class,
+        DownloadHandler.class,
+        ConnectionHandler.class,
+        AgentUpdateHandler.class,
+        FeedbackHandler.class,
+        EventsHandler.class,
+        ScheduledExecutorService.class
+    };
 
+    private final Map<Class<?>, Object> m_handlers = new HashMap<Class<?>, Object>();
+    private final Set<Object> m_components = new HashSet<Object>();
     private final File m_workDir;
 
     public AgentContextImpl(File workDir) {
         m_workDir = workDir;
     }
 
+    /**
+     * Start the context.
+     * 
+     * @throws Exception On failure.
+     */
     public void start() throws Exception {
-        startHandler(m_executorService);
-        startHandler(m_configurationHandler);
-        startHandler(m_loggingHandler);
-        startHandler(m_eventsHandler);
-        startHandler(m_connectionHandler);
-        startHandler(m_downloadHandler);
-        startHandler(m_identificationHandler);
-        startHandler(m_discoveryHandler);
-        startHandler(m_agentUpdateHandler);
-        startHandler(m_deploymentHandler);
-        startHandler(m_feedbackHandler);
+        for (Class<?> handlerIface : KNOWN_HANDLERS) {
+            Object handler = m_handlers.get(handlerIface);
+            if (handler == null) {
+                throw new IllegalStateException("Can not start context. Missing handler: " + handlerIface.getName());
+            }
+            startAgentContextAware(handler);
+        }
+        for (Object component : m_components) {
+            startAgentContextAware(component);
+        }
     }
 
+    /**
+     * Stop the context.
+     * 
+     * @throws Exception On failure.
+     */
     public void stop() throws Exception {
-        stopHandler(m_feedbackHandler);
-        stopHandler(m_deploymentHandler);
-        stopHandler(m_identificationHandler);
-        stopHandler(m_discoveryHandler);
-        stopHandler(m_downloadHandler);
-        stopHandler(m_connectionHandler);
-        stopHandler(m_agentUpdateHandler);
-        stopHandler(m_eventsHandler);
-        stopHandler(m_loggingHandler);
-        stopHandler(m_configurationHandler);
-        stopHandler(m_executorService);
+        for (Object component : m_components) {
+            stopAgentContextAware(component);
+        }
+        for (int i = (KNOWN_HANDLERS.length - 1); i >= 0; i--) {
+            Class<?> iface = KNOWN_HANDLERS[i];
+            Object handler = m_handlers.get(iface);
+            stopAgentContextAware(handler);
+        }
     }
 
     @Override
@@ -91,157 +106,43 @@ public class AgentContextImpl implements
         return m_workDir;
     }
 
-    @Override
-    public IdentificationHandler getIdentificationHandler() {
-        return m_identificationHandler;
-    }
-
-    void setIdentificationHandler(IdentificationHandler identificationHandler) {
-        m_identificationHandler = identificationHandler;
-    }
-
-    @Override
-    public DiscoveryHandler getDiscoveryHandler() {
-        return m_discoveryHandler;
-    }
-
-    void setDiscoveryHandler(DiscoveryHandler discoveryHandler) {
-        m_discoveryHandler = discoveryHandler;
-    }
-
-    @Override
-    public ConnectionHandler getConnectionHandler() {
-        return m_connectionHandler;
-    }
-
-    void setConnectionHandler(ConnectionHandler connectionHandler) {
-        m_connectionHandler = connectionHandler;
-    }
-
-    @Override
-    public DeploymentHandler getDeploymentHandler() {
-        return m_deploymentHandler;
-    }
-
-    void setDeploymentHandler(DeploymentHandler deploymenthandler) {
-        m_deploymentHandler = deploymenthandler;
-    }
-
-    @Override
-    public DownloadHandler getDownloadHandler() {
-        return m_downloadHandler;
-    }
-
-    void setDownloadHandler(DownloadHandler downloadHandler) {
-        m_downloadHandler = downloadHandler;
-    }
-
-    @Override
-    public ConfigurationHandler getConfigurationHandler() {
-        return m_configurationHandler;
-    }
-
-    void setConfigurationHandler(ConfigurationHandler configurationHandler) {
-        m_configurationHandler = configurationHandler;
-    }
-
-    @Override
-    public AgentUpdateHandler getAgentUpdateHandler() {
-        return m_agentUpdateHandler;
-    }
-
-    void setAgentUpdateHandler(AgentUpdateHandler agentUpdateHandler) {
-        m_agentUpdateHandler = agentUpdateHandler;
-    }
-
-    @Override
-    public FeedbackHandler getFeedbackHandler() {
-        return m_feedbackHandler;
+    @SuppressWarnings("unchecked")
+    public <T> T getHandler(Class<T> iface) {
+        return (T) m_handlers.get(iface);
     }
 
-    void setFeedbackHandler(FeedbackHandler feedbackHandler) {
-        m_feedbackHandler = feedbackHandler;
-    }
-
-    @Override
-    public ScheduledExecutorService getExecutorService() {
-        return m_executorService;
-    }
-
-    void setExecutorService(ScheduledExecutorService executorService) {
-        m_executorService = executorService;
-    }
-
-    LoggingHandler getLoggingHandler() {
-        return m_loggingHandler;
-    }
-
-    void setLoggingHandler(LoggingHandler loggingHandler) {
-        m_loggingHandler = loggingHandler;
-    }
-
-    EventsHandler getEventHandler() {
-        return m_eventsHandler;
-    }
-
-    void setEventsHandler(EventsHandler eventsHandler) {
-        m_eventsHandler = eventsHandler;
-    }
-
-    @Override
-    public void postEvent(String topic, Dictionary<String, String> payload) {
-        m_eventsHandler.postEvent(topic, payload);
-    }
-
-    @Override
-    public void logDebug(String component, String message, Object... args) {
-        m_loggingHandler.logDebug(component, message, null, args);
-    }
-
-    @Override
-    public void logDebug(String component, String message, Throwable exception, Object... args) {
-        m_loggingHandler.logDebug(component, message, exception, args);
-    }
-
-    @Override
-    public void logInfo(String component, String message, Object... args) {
-        m_loggingHandler.logInfo(component, message, null, args);
-    }
-
-    @Override
-    public void logInfo(String component, String message, Throwable exception, Object... args) {
-        m_loggingHandler.logInfo(component, message, exception, args);
-    }
-
-    @Override
-    public void logWarning(String component, String message, Object... args) {
-        m_loggingHandler.logWarning(component, message, null, args);
-    }
-
-    @Override
-    public void logWarning(String component, String message, Throwable exception, Object... args) {
-        m_loggingHandler.logWarning(component, message, exception, args);
-    }
-
-    @Override
-    public void logError(String component, String message, Object... args) {
-        m_loggingHandler.logDebug(component, message, null, args);
+    /**
+     * Set a handler on the context.
+     * 
+     * @param iface The handler interface
+     * @param handler The handler implementation
+     */
+    public void setHandler(Class<?> iface, Object handler) {
+        if (!iface.isAssignableFrom(handler.getClass())) {
+            throw new IllegalArgumentException("Handler is not assignable to handler interface: "
+                + handler.getClass().getName() + " => " + iface.getName());
+        }
+        m_handlers.put(iface, handler);
     }
 
-    @Override
-    public void logError(String component, String message, Throwable exception, Object... args) {
-        m_loggingHandler.logDebug(component, message, exception, args);
+    /**
+     * Add a component on the context.
+     * 
+     * @param component The component
+     */
+    public void addComponent(AgentContextAware component) {
+        m_components.add(component);
     }
 
-    private void startHandler(Object handler) throws Exception {
-        if (handler instanceof AgentContextAware) {
-            ((AgentContextAware) handler).start(this);
+    private void startAgentContextAware(Object object) throws Exception {
+        if (object instanceof AgentContextAware) {
+            ((AgentContextAware) object).start(this);
         }
     }
 
-    private void stopHandler(Object handler) throws Exception {
-        if (handler instanceof AgentContextAware) {
-            ((AgentContextAware) handler).stop();
+    private void stopAgentContextAware(Object object) throws Exception {
+        if (object instanceof AgentContextAware) {
+            ((AgentContextAware) object).stop();
         }
     }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentControlImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentControlImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentControlImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentControlImpl.java Wed Aug 28 12:28:00 2013
@@ -26,6 +26,7 @@ import org.apache.ace.agent.AgentUpdateH
 import org.apache.ace.agent.ConfigurationHandler;
 import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.FeedbackHandler;
+import org.apache.ace.agent.IdentificationHandler;
 
 /**
  * Implementation of the public agent control service.
@@ -40,22 +41,27 @@ public class AgentControlImpl implements
     }
 
     @Override
+    public String getAgentId() {
+        return m_agentContext.getHandler(IdentificationHandler.class).getAgentId();
+    }
+
+    @Override
     public ConfigurationHandler getConfigurationHandler() {
-        return m_agentContext.getConfigurationHandler();
+        return m_agentContext.getHandler(ConfigurationHandler.class);
     }
 
     @Override
     public DeploymentHandler getDeploymentHandler() {
-        return m_agentContext.getDeploymentHandler();
+        return m_agentContext.getHandler(DeploymentHandler.class);
     }
 
     @Override
     public AgentUpdateHandler getAgentUpdateHandler() {
-        return m_agentContext.getAgentUpdateHandler();
+        return m_agentContext.getHandler(AgentUpdateHandler.class);
     }
 
     @Override
     public FeedbackHandler getFeedbackHandler() {
-        return m_agentContext.getFeedbackHandler();
+        return m_agentContext.getHandler(FeedbackHandler.class);
     }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -42,11 +42,11 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 import org.osgi.util.tracker.ServiceTracker;
 
+/**
+ * Default implementation of {@link AgentUpdateHandler}.
+ */
 public class AgentUpdateHandlerImpl extends UpdateHandlerBase implements AgentUpdateHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "agentupdate";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
-
     private static final int TIMEOUT = 15000;
     private static final String UPDATER_VERSION = "1.0.0";
     private static final String UPDATER_SYMBOLICNAME = "org.apache.ace.agent.updater";
@@ -54,7 +54,7 @@ public class AgentUpdateHandlerImpl exte
     private BundleContext m_bundleContext;
 
     public AgentUpdateHandlerImpl(BundleContext bundleContext) {
-        super(COMPONENT_IDENTIFIER);
+        super("agentupdate");
         m_bundleContext = bundleContext;
     }
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ComponentBase.java Wed Aug 28 12:28:00 2013
@@ -29,40 +29,42 @@ import org.apache.ace.agent.ConnectionHa
 import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.DiscoveryHandler;
 import org.apache.ace.agent.DownloadHandler;
+import org.apache.ace.agent.EventsHandler;
 import org.apache.ace.agent.FeedbackHandler;
 import org.apache.ace.agent.IdentificationHandler;
+import org.apache.ace.agent.LoggingHandler;
 
 /**
  * Convenience implementation base class for all {@link AgentContextAware} components, such as handlers & controllers.
- * 
  */
 public abstract class ComponentBase implements AgentContextAware {
 
-    private final String m_componentIdentifier;
-    private AgentContext m_agentContext;
+    private final String m_identifier;
+    private volatile AgentContext m_context;
 
     public ComponentBase(String handlerIdentifier) {
-        m_componentIdentifier = handlerIdentifier;
+        m_identifier = handlerIdentifier;
     }
 
     @Override
     public final void start(AgentContext agentContext) throws Exception {
-        m_agentContext = agentContext;
-        m_agentContext.logDebug(m_componentIdentifier, "Starting");
+        if (agentContext == null) {
+            throw new IllegalArgumentException("Context must not be null");
+        }
+        m_context = agentContext;
         onStart();
     }
 
     @Override
     public final void stop() throws Exception {
-        m_agentContext.logDebug(m_componentIdentifier, "Stopping");
-        m_agentContext = null;
         onStop();
+        m_context = null;
     }
 
     protected final AgentContext getAgentContext() {
-        if (m_agentContext == null)
-            throw new IllegalStateException("Handler is not started");
-        return m_agentContext;
+        if (m_context == null)
+            throw new IllegalStateException("Handler is not started: " + m_identifier);
+        return m_context;
     }
 
     protected void onStart() throws Exception {
@@ -72,74 +74,82 @@ public abstract class ComponentBase impl
     }
 
     protected final IdentificationHandler getIdentificationHandler() {
-        return m_agentContext.getIdentificationHandler();
+        return m_context.getHandler(IdentificationHandler.class);
     }
 
     protected final DiscoveryHandler getDiscoveryHandler() {
-        return m_agentContext.getDiscoveryHandler();
+        return m_context.getHandler(DiscoveryHandler.class);
     }
 
     protected final ConnectionHandler getConnectionHandler() {
-        return m_agentContext.getConnectionHandler();
+        return m_context.getHandler(ConnectionHandler.class);
     }
 
     protected final DeploymentHandler getDeploymentHandler() {
-        return m_agentContext.getDeploymentHandler();
+        return m_context.getHandler(DeploymentHandler.class);
     }
 
     protected final DownloadHandler getDownloadHandler() {
-        return m_agentContext.getDownloadHandler();
+        return m_context.getHandler(DownloadHandler.class);
     }
 
     protected final ConfigurationHandler getConfigurationHandler() {
-        return m_agentContext.getConfigurationHandler();
+        return m_context.getHandler(ConfigurationHandler.class);
     }
 
     protected final AgentUpdateHandler getAgentUpdateHandler() {
-        return m_agentContext.getAgentUpdateHandler();
+        return m_context.getHandler(AgentUpdateHandler.class);
     }
 
     protected final FeedbackHandler getFeedbackHandler() {
-        return m_agentContext.getFeedbackHandler();
+        return m_context.getHandler(FeedbackHandler.class);
+    }
+
+    protected final LoggingHandler getLoggingHandler() {
+        return m_context.getHandler(LoggingHandler.class);
+    }
+
+    protected final EventsHandler getEventsHandler() {
+        return m_context.getHandler(EventsHandler.class);
     }
 
     protected final ScheduledExecutorService getExecutorService() {
-        return m_agentContext.getExecutorService();
+        return m_context.getHandler(ScheduledExecutorService.class);
     }
 
     protected final File getWorkDir() {
-        return m_agentContext.getWorkDir();
+        return m_context.getWorkDir();
     }
 
     protected final void logDebug(String message, Object... args) {
-        getAgentContext().logDebug(m_componentIdentifier, message, null, args);
+        getLoggingHandler().logDebug(m_identifier, message, null, args);
     }
 
     protected final void logDebug(String message, Throwable cause, Object... args) {
-        getAgentContext().logDebug(m_componentIdentifier, message, cause, args);
+        getLoggingHandler().logDebug(m_identifier, message, cause, args);
     }
 
     protected final void logInfo(String message, Object... args) {
-        getAgentContext().logInfo(m_componentIdentifier, message, null, args);
+        getLoggingHandler().logInfo(m_identifier, message, null, args);
     }
 
     protected final void logInfo(String message, Throwable cause, Object... args) {
-        getAgentContext().logInfo(m_componentIdentifier, message, cause, args);
+        getLoggingHandler().logInfo(m_identifier, message, cause, args);
     }
 
     protected final void logWarning(String message, Object... args) {
-        getAgentContext().logWarning(m_componentIdentifier, message, null, args);
+        getLoggingHandler().logWarning(m_identifier, message, null, args);
     }
 
     protected final void logWarning(String message, Throwable cause, Object... args) {
-        getAgentContext().logWarning(m_componentIdentifier, message, cause, args);
+        getLoggingHandler().logWarning(m_identifier, message, cause, args);
     }
 
     protected final void logError(String message, Object... args) {
-        getAgentContext().logError(m_componentIdentifier, message, null, args);
+        getLoggingHandler().logError(m_identifier, message, null, args);
     }
 
     protected final void logError(String message, Throwable cause, Object... args) {
-        getAgentContext().logError(m_componentIdentifier, message, cause, args);
+        getLoggingHandler().logError(m_identifier, message, cause, args);
     }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -18,6 +18,9 @@
  */
 package org.apache.ace.agent.impl;
 
+import static org.apache.ace.agent.AgentConstants.CONFIG_KEY_NAMESPACE;
+import static org.apache.ace.agent.AgentConstants.CONFIG_KEY_RETAIN;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -25,6 +28,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map.Entry;
 import java.util.Properties;
@@ -33,14 +37,11 @@ import java.util.Set;
 import org.apache.ace.agent.ConfigurationHandler;
 
 /**
- * Default configuration handler that reads the serverURL(s) from the configuration using key
- * {@link DISCOVERY_CONFIG_KEY}.
+ * Default thread-safe {@link ConfigurationHandler} implementation.
  */
+// TODO performance; less locking using a map and read-write lock
 public class ConfigurationHandlerImpl extends ComponentBase implements ConfigurationHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "configuration";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
-
     /** Directory name use for storage. It is relative to the agent context work directory. */
     public static final String CONFIG_STORAGE_SUBDIR = "config";
 
@@ -50,7 +51,7 @@ public class ConfigurationHandlerImpl ex
     private Properties m_configProps = null;
 
     public ConfigurationHandlerImpl() {
-        super(COMPONENT_IDENTIFIER);
+        super("configuration");
     }
 
     @Override
@@ -89,6 +90,7 @@ public class ConfigurationHandlerImpl ex
             ensureLoadConfig();
             Object value = m_configProps.remove(key);
             if (value != null) {
+                getEventsHandler().postEvent("agent/config/CHANGED", new HashMap<String, String>());
                 ensureStoreConfig();
             }
         }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -18,6 +18,14 @@
  */
 package org.apache.ace.agent.impl;
 
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_AUTHTYPE;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_KEYFILE;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_KEYPASS;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_PASSWORD;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_TRUSTFILE;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_TRUSTPASS;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONNECTION_USERNAME;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -39,64 +47,13 @@ import javax.xml.bind.DatatypeConverter;
 import org.apache.ace.agent.ConnectionHandler;
 
 /**
- * Default connection handler with support for BASIC authentication and HTTPS client certificates.
- * 
+ * Default thread-safe {@link ConnectionHandler} implementation with support for BASIC authentication and HTTPS client
+ * certificates.
  */
 public class ConnectionHandlerImpl extends ComponentBase implements ConnectionHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "connection";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
-
-    public static final String PROP_AUTHTYPE = "agent.authType";
-    public static final String PROP_AUTHUSER = "agent.authUser";
-    public static final String PROP_AUTHPASS = "agent.authPass";
-    public static final String PROP_AUTHKEYFILE = "agent.authKeyFile";
-    public static final String PROP_AUTHKEYPASS = "agent.authKeyPass";
-    public static final String PROP_AUTHTRUSTFILE = "agent.authTrustFile";
-    public static final String PROP_AUTHTRUSTPASS = "agent.authTrustPass";
-
-    private static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
-
-    private enum AuthType {
-
-        NONE,
-        BASIC,
-        CLIENT_CERT;
-
-        static AuthType getAuthType(String name) {
-            if (name.equals(NONE.name()))
-                return NONE;
-            if (name.equals(BASIC.name()))
-                return BASIC;
-            if (name.equals(CLIENT_CERT.name()))
-                return CLIENT_CERT;
-            return null;
-        }
-    }
-
-    private static class UrlCredentials {
-
-        final static UrlCredentials EMPTY_CREDENTIALS = new UrlCredentials(AuthType.NONE, new Object[0]);
-
-        private final AuthType m_type;
-        private final Object[] m_credentials;
-
-        public UrlCredentials(AuthType type, Object... credentials) {
-            m_type = type;
-            m_credentials = (credentials == null) ? new Object[0] : credentials.clone();
-        }
-
-        public Object[] getCredentials() {
-            return m_credentials.clone();
-        }
-
-        public AuthType getType() {
-            return m_type;
-        }
-    }
-
     public ConnectionHandlerImpl() {
-        super(COMPONENT_IDENTIFIER);
+        super("connection");
     }
 
     @Override
@@ -104,10 +61,10 @@ public class ConnectionHandlerImpl exten
         URLConnection connection = (HttpURLConnection) url.openConnection();
         UrlCredentials credentials = getCredentials();
         if (credentials != null) {
-            if (credentials != null && credentials.getType() == AuthType.BASIC)
+            if (credentials != null && credentials.getType() == Types.BASIC)
                 applyBasicAuthentication(connection, credentials.getCredentials());
 
-            else if (credentials != null && credentials.getType() == AuthType.CLIENT_CERT) {
+            else if (credentials != null && credentials.getType() == Types.CLIENTCERT) {
                 applyClientCertificate(connection, credentials.getCredentials());
             }
         }
@@ -139,7 +96,7 @@ public class ConnectionHandlerImpl exten
 
     private void applyBasicAuthentication(URLConnection conn, Object[] values) {
         if (conn instanceof HttpURLConnection) {
-            conn.setRequestProperty(HTTP_HEADER_AUTHORIZATION, getBasicAuthCredentials(values));
+            conn.setRequestProperty("Authorization", getBasicAuthCredentials(values));
         }
     }
 
@@ -151,24 +108,23 @@ public class ConnectionHandlerImpl exten
 
     public UrlCredentials getCredentials() {
 
-        String configValue = getConfigStringValue(PROP_AUTHTYPE);
-        AuthType authType = AuthType.getAuthType(configValue == null ? "" : configValue.trim().toUpperCase());
-        if (authType == null || authType == AuthType.NONE) {
+        String configValue = getConfigStringValue(CONFIG_CONNECTION_AUTHTYPE);
+        Types authType = getType(configValue == null ? "" : configValue.trim().toUpperCase());
+        if (authType == null || authType == Types.NONE) {
             return UrlCredentials.EMPTY_CREDENTIALS;
         }
 
-        if (authType == AuthType.BASIC) {
-            String username = getConfigStringValue(PROP_AUTHUSER);
-            String password = getConfigStringValue(PROP_AUTHPASS);
-            return new UrlCredentials(AuthType.BASIC,
-                new Object[] { username == null ? "" : username, password == null ? "" : password });
+        if (authType == Types.BASIC) {
+            String username = getConfigStringValue(CONFIG_CONNECTION_USERNAME);
+            String password = getConfigStringValue(CONFIG_CONNECTION_PASSWORD);
+            return new UrlCredentials(Types.BASIC, new Object[] { username == null ? "" : username, password == null ? "" : password });
         }
 
-        if (authType == AuthType.CLIENT_CERT) {
-            String keystoreFile = getConfigStringValue(PROP_AUTHKEYFILE);
-            String keystorePass = getConfigStringValue(PROP_AUTHKEYPASS);
-            String truststoreFile = getConfigStringValue(PROP_AUTHTRUSTFILE);
-            String truststorePass = getConfigStringValue(PROP_AUTHTRUSTPASS);
+        if (authType == Types.CLIENTCERT) {
+            String keystoreFile = getConfigStringValue(CONFIG_CONNECTION_KEYFILE);
+            String keystorePass = getConfigStringValue(CONFIG_CONNECTION_KEYPASS);
+            String truststoreFile = getConfigStringValue(CONFIG_CONNECTION_TRUSTFILE);
+            String truststorePass = getConfigStringValue(CONFIG_CONNECTION_TRUSTPASS);
 
             // TODO This is expensive. Can we cache?
             try {
@@ -176,8 +132,7 @@ public class ConnectionHandlerImpl exten
                 TrustManager[] trustManagers = getTrustManagerFactory(truststoreFile, truststorePass);
                 SSLContext context = SSLContext.getInstance("TLS");
                 context.init(keyManagers, trustManagers, new SecureRandom());
-                return new UrlCredentials(AuthType.CLIENT_CERT,
-                    new Object[] { context });
+                return new UrlCredentials(Types.CLIENTCERT, new Object[] { context });
             }
             catch (Exception e) {
                 // TODO log
@@ -187,7 +142,7 @@ public class ConnectionHandlerImpl exten
     }
 
     private String getConfigStringValue(String key) {
-        return getAgentContext().getConfigurationHandler().get(key, null);
+        return getConfigurationHandler().get(key, null);
     }
 
     private static KeyManager[] getKeyManagerFactory(String keystoreFile, String storePass) throws IOException, GeneralSecurityException {
@@ -231,4 +186,33 @@ public class ConnectionHandlerImpl exten
             }
         }
     }
+
+    private static Types getType(String name) {
+        try {
+            return Types.valueOf(name.toUpperCase().trim());
+        }
+        catch (Exception e) {
+            return Types.NONE;
+        }
+    }
+
+    private static class UrlCredentials {
+
+        final static UrlCredentials EMPTY_CREDENTIALS = new UrlCredentials(Types.NONE, new Object[0]);
+        private final Types m_type;
+        private final Object[] m_credentials;
+
+        public UrlCredentials(Types type, Object... credentials) {
+            m_type = type;
+            m_credentials = (credentials == null) ? new Object[0] : credentials.clone();
+        }
+
+        public Object[] getCredentials() {
+            return m_credentials.clone();
+        }
+
+        public Types getType() {
+            return m_type;
+        }
+    }
 }

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionUtil.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionUtil.java?rev=1518177&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionUtil.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConnectionUtil.java Wed Aug 28 12:28:00 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.impl;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+
+import org.apache.ace.agent.RetryAfterException;
+
+/**
+ * Common utility functions for components that work with server connections.
+ */
+public class ConnectionUtil {
+
+    /**
+     * Check the server response code and throws exceptions if it is not 200.
+     * 
+     * @param connection The connection to check
+     * @throws RetryAfterException If the server response is 503
+     * @throws IOException If the server response is other
+     */
+    public static void checkConnectionResponse(URLConnection connection) throws RetryAfterException, IOException {
+
+        if (connection instanceof HttpURLConnection) {
+            int responseCode = ((HttpURLConnection) connection).getResponseCode();
+            switch (responseCode) {
+                case 200:
+                    return;
+                case 503:
+                    int retry = 30;
+                    String header = ((HttpURLConnection) connection).getHeaderField("Retry-After");
+                    if (header != null) {
+                        try {
+                            retry = Integer.parseInt(header);
+                        }
+                        catch (NumberFormatException e) {
+                        }
+                    }
+                    throw new RetryAfterException(retry);
+                default:
+                    throw new IOException("Unable to handle server responsecode: " + responseCode);
+            }
+        }
+    }
+
+    private ConnectionUtil() {
+
+    }
+}

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=1518177&r1=1518176&r2=1518177&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 Wed Aug 28 12:28:00 2013
@@ -18,6 +18,13 @@
  */
 package org.apache.ace.agent.impl;
 
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_DISABLED;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_FIXPACKAGES;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_RETRIES;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_STREAMING;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_SYNCDELAY;
+import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_SYNCINTERVAL;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,6 +42,7 @@ import org.apache.ace.agent.DownloadStat
 import org.apache.ace.agent.FeedbackChannel;
 import org.apache.ace.agent.RetryAfterException;
 import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentException;
 
 /**
  * Default configurable controller
@@ -43,55 +51,6 @@ import org.osgi.framework.Version;
 public class DefaultController extends ComponentBase implements Runnable {
 
     public static final String COMPONENT_IDENTIFIER = "controller";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + ".controller";
-
-    /**
-     */
-    public static final String CONFIG_KEY_DISABLED = CONFIG_KEY_BASE + ".disabled";
-    public static final boolean CONFIG_DEFAULT_DISABLED = false;
-
-    /**
-     * Sync delay; Number of seconds after startup until the initial sync is done.
-     */
-    public static final String CONFIG_KEY_SYNCDELAY = CONFIG_KEY_BASE + ".syncDelay";
-    public static final long CONFIG_DEFAULT_SYNCDELAY = 5l;
-
-    /**
-     * Sync interval; Number of seconds between regular syncs.
-     */
-    public static final String CONFIG_KEY_SYNCINTERVAL = CONFIG_KEY_BASE + ".syncInterval";
-    public static final long CONFIG_DEFAULT_SYNCINTERVAL = 30l;
-
-    /**
-     * SyncRetries value; When an install fails during a sync the agent can try to recover by ignoring optimization
-     * flags and potentially restarting a Deployment Package download. A value of 1 or less disables the retry behavior.
-     */
-    public static final String CONFIG_KEY_UPDATERETRIES = CONFIG_KEY_BASE + ".updateRetries";
-    public static final long CONFIG_DEFAULT_UPDATERETRIES = 2;
-
-    /**
-     * UpdateStreaming flag; When set Deployment Packages are installed directly from the download stream reducing
-     * overhead and disk usage, but disabling resume capabilities. This strategy is of interest to highly resource
-     * constraint devices and/or system with highly reliable connectivity and no need for resume semantics.
-     */
-    public static final String CONFIG_KEY_UPDATESTREAMING = CONFIG_KEY_BASE + ".updateStreaming";
-    public static final boolean CONFIG_DEFAULT_UPDATESTREAMING = false;
-
-    /**
-     * StopUnaffected flag; When set all target bundles of a Deployment Package will be restarted as part of the
-     * deployment session. Otherwise the agent tries to minimize the impact by only restarting bundles that are actually
-     * affected. Not stopping unaffected bundles reduces overhead, but may fail in complex wiring scenarios.
-     */
-    // FIXME Not considered yet
-    public static final String CONFIG_KEY_STOPUNAFFECTED = CONFIG_KEY_BASE + ".stopUnaffected";
-    public static final boolean CONFIG_DEFAULT_STOPUNAFFECTED = true; // spec behavior
-
-    /**
-     * FixPackages flag; When set the Agent will request the server for fix packages instead of full deployment
-     * packages. This behavior significantly reduces bandwidth consumption.
-     */
-    public static final String CONFIG_KEY_FIXPACKAGES = CONFIG_KEY_BASE + ".fixPackages";
-    public static final boolean CONFIG_DEFAULT_FIXPACKAGES = true;
 
     private volatile ScheduledFuture<?> m_scheduledFuture;
     private volatile UpdateInstaller m_updateInstaller;
@@ -102,7 +61,7 @@ public class DefaultController extends C
 
     @Override
     protected void onStart() throws Exception {
-        long delay = getConfigurationHandler().getLong(CONFIG_KEY_SYNCDELAY, CONFIG_DEFAULT_SYNCDELAY);
+        long delay = getConfigurationHandler().getLong(CONFIG_CONTROLLER_SYNCDELAY, 5);
         scheduleRun(delay);
         logDebug("Controller scheduled to run in %d seconds", delay);
     }
@@ -117,8 +76,8 @@ public class DefaultController extends C
 
     @Override
     public void run() {
-        boolean disabled = getConfigurationHandler().getBoolean(CONFIG_KEY_DISABLED, CONFIG_DEFAULT_DISABLED);
-        long interval = getConfigurationHandler().getLong(CONFIG_KEY_SYNCINTERVAL, CONFIG_DEFAULT_SYNCINTERVAL);
+        boolean disabled = getConfigurationHandler().getBoolean(CONFIG_CONTROLLER_DISABLED, false);
+        long interval = getConfigurationHandler().getLong(CONFIG_CONTROLLER_SYNCINTERVAL, 60);
         if (disabled) {
             logDebug("Controller disabled by configuration. Skipping..");
             scheduleRun(interval);
@@ -154,12 +113,12 @@ public class DefaultController extends C
             if (channel != null) {
                 try {
                     channel.sendFeedback();
-                    logDebug("Feedback send succesfully for channel %s", names);
+                    logDebug("Feedback send succesfully for channel: %s", name);
                 }
                 catch (IOException e) {
                     // Hopefully temporary problem due to remote IO or configuration. No cause to abort the sync so we
                     // just log it as a warning.
-                    logWarning("Exception while sending feedback on channel %s", e, names);
+                    logWarning("Exception while sending feedback on channel: %s", e, name);
                 }
             }
         }
@@ -244,9 +203,9 @@ public class DefaultController extends C
             return;
         }
 
-        boolean updateStreaming = getConfigurationHandler().getBoolean(CONFIG_KEY_UPDATESTREAMING, CONFIG_DEFAULT_UPDATESTREAMING);
-        boolean fixPackage = getConfigurationHandler().getBoolean(CONFIG_KEY_FIXPACKAGES, CONFIG_DEFAULT_FIXPACKAGES);
-        long maxRetries = getConfigurationHandler().getLong(CONFIG_KEY_UPDATERETRIES, CONFIG_DEFAULT_UPDATERETRIES);
+        boolean updateStreaming = getConfigurationHandler().getBoolean(CONFIG_CONTROLLER_STREAMING, true);
+        boolean fixPackage = getConfigurationHandler().getBoolean(CONFIG_CONTROLLER_FIXPACKAGES, true);
+        long maxRetries = getConfigurationHandler().getLong(CONFIG_CONTROLLER_RETRIES, 1);
 
         getUpdateInstaller(updateStreaming).installUpdate(current, highest, fixPackage, maxRetries);
     }
@@ -332,8 +291,14 @@ public class DefaultController extends C
                 throw (e);
 
             }
+            catch (DeploymentException e) {
+                getController().logWarning("Exception while deploying the package", e);
+                e.printStackTrace();
+                m_failureCount++;
+            }
             catch (IOException e) {
-                // Just increment the failure count and asume the concrete implementation logged.
+                getController().logWarning("Exception opening/streaming package inputstream", e);
+                e.printStackTrace();
                 m_failureCount++;
             }
         }
@@ -344,7 +309,7 @@ public class DefaultController extends C
             doReset();
         }
 
-        protected abstract void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, IOException;
+        protected abstract void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, DeploymentException, IOException;
 
         protected abstract void doReset();
     }
@@ -359,7 +324,7 @@ public class DefaultController extends C
         }
 
         @Override
-        public void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, IOException {
+        public void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, DeploymentException, IOException {
 
             getController().logInfo("Installing streaming deployment update %s => %s", from, to);
 
@@ -370,10 +335,6 @@ public class DefaultController extends C
                 deploymentHandler.deployPackage(inputStream);
                 return;
             }
-            catch (IOException e) {
-                getController().logWarning("Exception opening/streaming package inputstream", e);
-                throw e;
-            }
             finally {
                 if (inputStream != null) {
                     try {
@@ -409,7 +370,7 @@ public class DefaultController extends C
         }
 
         @Override
-        public void doInstallUpdate(Version fromVersion, Version toVersion, boolean fixPackage) throws RetryAfterException, IOException {
+        public void doInstallUpdate(Version fromVersion, Version toVersion, boolean fixPackage) throws RetryAfterException, DeploymentException, IOException {
 
             DeploymentHandler deploymentHandler = getController().getDeploymentHandler();
             if (m_downloadHandle != null && !m_downloadVersion.equals(toVersion)) {
@@ -442,11 +403,12 @@ public class DefaultController extends C
                 else if (m_downloadResult.getState() == DownloadState.SUCCESSFUL) {
                     getController().logInfo("Installing downloaded deployment update %s => %s", fromVersion, toVersion);
                     InputStream inputStream = new FileInputStream(m_downloadResult.getFile());
+                    System.out.println(m_downloadResult.getFile().getAbsolutePath());
                     try {
                         deploymentHandler.deployPackage(inputStream);
                     }
                     finally {
-                        m_downloadHandle.discard();
+                        // m_downloadHandle.discard();
                         m_downloadHandle = null;
                         inputStream.close();
                     }
@@ -472,8 +434,8 @@ public class DefaultController extends C
         @Override
         public void completed(DownloadResult result) {
             m_downloadResult = result;
-            getController().logInfo("Deployment package completed for version %s. Rescheduling the controller to run in %d seconds", m_downloadVersion, 5);
-            getController().scheduleRun(5);
+            getController().logInfo("Deployment package donwload completed for version %s. Rescheduling the controller to run in %d seconds", m_downloadVersion, 1);
+            getController().scheduleRun(1);
         }
 
         private void clearDownloadState() {

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java Wed Aug 28 12:28:00 2013
@@ -106,9 +106,6 @@ public class DependencyTrackerImpl {
         // As this is a simple internal implementation we assume we can safely invoke
         // callbacks while holding locks.
         synchronized (this) {
-            if (!m_tracking) {
-                return;
-            }
             if (dependenciesAvailable()) {
                 if (m_started) {
                     stopCallback();
@@ -117,8 +114,10 @@ public class DependencyTrackerImpl {
                 startCallback();
             }
             else {
-                stopCallback();
-                serviceCallbacks();
+                if (m_started) {
+                    stopCallback();
+                    serviceCallbacks();
+                }
             }
         }
     }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -20,31 +20,66 @@ package org.apache.ace.agent.impl;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.SortedSet;
 
 import org.apache.ace.agent.DeploymentHandler;
 import org.apache.ace.agent.DownloadHandle;
 import org.apache.ace.agent.RetryAfterException;
+import org.apache.felix.deploymentadmin.DeploymentAdminImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.osgi.framework.Version;
 import org.osgi.service.deploymentadmin.DeploymentAdmin;
 import org.osgi.service.deploymentadmin.DeploymentException;
 import org.osgi.service.deploymentadmin.DeploymentPackage;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.PackageAdmin;
 
 public class DeploymentHandlerImpl extends UpdateHandlerBase implements DeploymentHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "deployment";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
-
     private final DeploymentAdmin m_deploymentAdmin;
+    private final boolean m_ownDeploymentAdmin;
+
+    public DeploymentHandlerImpl(BundleContext bundleContext, PackageAdmin packageAdmin) {
+        super("deployment");
+        m_ownDeploymentAdmin = true;
+        m_deploymentAdmin = new DeploymentAdminImpl();
+        configureField(m_deploymentAdmin, BundleContext.class, bundleContext);
+        configureField(m_deploymentAdmin, PackageAdmin.class, packageAdmin);
+        configureField(m_deploymentAdmin, EventAdmin.class, new EventAdminBridge());
+        configureField(m_deploymentAdmin, LogService.class, new LogServiceBridge());
+    }
 
-    public DeploymentHandlerImpl(DeploymentAdmin deploymentAdmin) {
-        super(COMPONENT_IDENTIFIER);
+    DeploymentHandlerImpl(DeploymentAdmin deploymentAdmin) {
+        super("deployment");
+        m_ownDeploymentAdmin = false;
         m_deploymentAdmin = deploymentAdmin;
     }
 
     @Override
+    protected void onStart() throws Exception {
+        if (m_ownDeploymentAdmin) {
+            invokeMethod(m_deploymentAdmin, "start", new Class<?>[] {}, new Object[] {});
+        }
+    }
+
+    @Override
+    protected void onStop() throws Exception {
+        if (m_ownDeploymentAdmin) {
+            invokeMethod(m_deploymentAdmin, "stop", new Class<?>[] {}, new Object[] {});
+        }
+    }
+
+    @Override
     public Version getInstalledVersion() {
         Version highestVersion = Version.emptyVersion;
         DeploymentPackage[] installedPackages = m_deploymentAdmin.listDeploymentPackages();
@@ -58,14 +93,8 @@ public class DeploymentHandlerImpl exten
     }
 
     @Override
-    public void deployPackage(InputStream inputStream) {
-        // FIXME exceptions
-        try {
-            m_deploymentAdmin.installDeploymentPackage(inputStream);
-        }
-        catch (DeploymentException e) {
-            e.printStackTrace();
-        }
+    public void deployPackage(InputStream inputStream) throws DeploymentException {
+        m_deploymentAdmin.installDeploymentPackage(inputStream);
     }
 
     @Override
@@ -115,4 +144,98 @@ public class DeploymentHandlerImpl exten
             throw new IllegalStateException(e);
         }
     }
+
+    private static void configureField(Object object, Class<?> iface, Object instance) {
+        // Note: Does not check super classes!
+        Field[] fields = object.getClass().getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+        for (int j = 0; j < fields.length; j++) {
+            if (fields[j].getType().equals(iface)) {
+                try {
+                    fields[j].set(object, instance);
+                }
+                catch (Exception e) {
+                    e.printStackTrace();
+                    throw new IllegalStateException("Coudld not set field " + fields[j].getName() + " on " + object);
+                }
+            }
+        }
+    }
+
+    private static Object invokeMethod(Object object, String methodName, Class<?>[] signature, Object[] parameters) {
+        // Note: Does not check super classes!
+        Class<?> clazz = object.getClass();
+        try {
+            Method method = clazz.getDeclaredMethod(methodName, signature);
+            return method.invoke(object, parameters);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * Internal EventAdmin that delegates to actual InternalEvents. Used to inject into the DeploymentAdmin only.
+     */
+    class EventAdminBridge implements EventAdmin {
+
+        @Override
+        public void postEvent(Event event) {
+            getEventsHandler().postEvent(event.getTopic(), getPayload(event));
+        }
+
+        @Override
+        public void sendEvent(Event event) {
+            getEventsHandler().postEvent(event.getTopic(), getPayload(event));
+        }
+
+        private Map<String, String> getPayload(Event event) {
+            Map<String, String> payload = new HashMap<String, String>();
+            for (String propertyName : event.getPropertyNames()) {
+                payload.put(propertyName, event.getProperty(propertyName).toString());
+            }
+            return payload;
+        }
+    }
+
+    /**
+     * Internal LogService that wraps delegates to actual InternalLogger. Used to inject into the DeploymentAdmin only.
+     */
+    class LogServiceBridge implements LogService {
+
+        @Override
+        public void log(int level, String message) {
+            log(level, message, null);
+        }
+
+        @Override
+        public void log(int level, String message, Throwable exception) {
+            switch (level) {
+                case LogService.LOG_WARNING:
+                    logWarning(message, exception);
+                    break;
+                case LogService.LOG_INFO:
+                    logInfo(message, exception);
+                    break;
+                case LogService.LOG_DEBUG:
+                    logDebug(message, exception);
+                    break;
+                default:
+                    logError(message, exception);
+                    break;
+            }
+        }
+
+        @Override
+        public void log(ServiceReference sr, int level, String message) {
+            log(level, message, null);
+        }
+
+        @Override
+        public void log(ServiceReference sr, int level, String message, Throwable exception) {
+            log(level, message, exception);
+        }
+    }
+
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DiscoveryHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -18,52 +18,58 @@
  */
 package org.apache.ace.agent.impl;
 
+import static org.apache.ace.agent.AgentConstants.CONFIG_DISCOVERY_CHECKING;
+import static org.apache.ace.agent.AgentConstants.CONFIG_DISCOVERY_SERVERURLS;
+
 import java.io.IOException;
 import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.ace.agent.ConfigurationHandler;
 import org.apache.ace.agent.DiscoveryHandler;
 
 /**
- * Default discovery handler that reads the serverURL(s) from the configuration using key {@link DISCOVERY_CONFIG_KEY}.
- * 
+ * Default thread-safe {@link DiscoveryHandler} implementation that reads the serverURL(s) from the configuration using
+ * key {@link CONFIG_DISCOVERY_SERVERURLS}. If the {@link CONFIG_DISCOVERY_CHECKING} flag is a connection is opened to
+ * test whether a serverURL is available before it is returned.
  */
 public class DiscoveryHandlerImpl extends ComponentBase implements DiscoveryHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "discovery";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
+    private final Map<String, CheckedURL> m_availableURLs = new HashMap<String, DiscoveryHandlerImpl.CheckedURL>();
+    private final Map<String, CheckedURL> m_blacklistedURLs = new HashMap<String, DiscoveryHandlerImpl.CheckedURL>();
 
-    /**
-     * Configuration key for the default discovery handler. The value must be a comma-separated list of valid base
-     * server URLs.
-     */
-    public static final String CONFIG_KEY_SERVERURLS = CONFIG_KEY_BASE + ".serverUrls";
-    public static final String CONFIG_DEFAULT_SERVERURLS = "http://localhost:8080";
+    private static final long CACHE_TIME = 2000;
 
     public DiscoveryHandlerImpl() {
-        super(COMPONENT_IDENTIFIER);
+        super("discovery");
     }
 
+    @Override
+    protected void onStop() throws Exception {
+        m_availableURLs.clear();
+        m_blacklistedURLs.clear();
+    }
 
     // TODO Pretty naive implementation below. It always takes the first configured URL it can connect to and is not
     // thread-safe.
     @Override
     public URL getServerUrl() {
-        ConfigurationHandler configurationHandler = getAgentContext().getConfigurationHandler();
 
-        String configValue = configurationHandler.get(CONFIG_KEY_SERVERURLS, CONFIG_DEFAULT_SERVERURLS);
+        String configValue = getConfigurationHandler().get(CONFIG_DISCOVERY_SERVERURLS, "http://localhost:8080");
+        boolean checking = getConfigurationHandler().getBoolean(CONFIG_DISCOVERY_CHECKING, false);
+
         URL url = null;
         if (configValue.indexOf(",") == -1) {
-            url = checkURL(configValue.trim());
+            url = getURL(configValue.trim(), checking);
         }
         else {
             for (String configValuePart : configValue.split(",")) {
-                if (url == null) {
-                    url = checkURL(configValuePart.trim());
+                url = getURL(configValuePart.trim(), checking);
+                if (url != null) {
+                    break;
                 }
             }
         }
@@ -73,8 +79,6 @@ public class DiscoveryHandlerImpl extend
         return url;
     }
 
-    private static final long CACHE_TIME = 1000;
-
     private static class CheckedURL {
         URL url;
         long timestamp;
@@ -85,24 +89,40 @@ public class DiscoveryHandlerImpl extend
         }
     }
 
-    private final Map<String, CheckedURL> m_checkedURLs = new HashMap<String, DiscoveryHandlerImpl.CheckedURL>();
-
-    private URL checkURL(String serverURL) {
+    private URL getURL(String serverURL, boolean checking) {
 
-        CheckedURL checked = m_checkedURLs.get(serverURL);
-        if (checked != null && checked.timestamp > (System.currentTimeMillis() - CACHE_TIME)) {
-            logDebug("Returning cached serverURL: " + checked.url.toExternalForm());
-            return checked.url;
-        }
+        URL url = null;
         try {
-            URL url = new URL(serverURL);
+            CheckedURL blackListed = m_blacklistedURLs.get(serverURL);
+            if (blackListed != null && blackListed.timestamp > (System.currentTimeMillis() - CACHE_TIME)) {
+                logDebug("Ignoring blacklisted serverURL: " + serverURL);
+                return null;
+            }
+
+            url = new URL(serverURL);
+            if (!checking) {
+                return url;
+            }
+
+            CheckedURL available = m_availableURLs.get(serverURL);
+            if (available != null && available.timestamp > (System.currentTimeMillis() - CACHE_TIME)) {
+                logDebug("Returning available serverURL: " + available.url.toExternalForm());
+                return available.url;
+            }
+
             tryConnect(url);
             logDebug("Succesfully connected to  serverURL: %s", serverURL);
-            m_checkedURLs.put(serverURL, new CheckedURL(url, System.currentTimeMillis()));
+            m_availableURLs.put(serverURL, new CheckedURL(url, System.currentTimeMillis()));
             return url;
         }
+        catch (MalformedURLException e) {
+            logError("Temporarily blacklisting malformed serverURL: " + serverURL);
+            m_blacklistedURLs.put(serverURL, new CheckedURL(url, System.currentTimeMillis()));
+            return null;
+        }
         catch (IOException e) {
-            logDebug("Failed to connect to serverURL: " + serverURL);
+            logWarning("Temporarily blacklisting unavailable serverURL: " + serverURL);
+            m_blacklistedURLs.put(serverURL, new CheckedURL(url, System.currentTimeMillis()));
             return null;
         }
     }
@@ -110,7 +130,7 @@ public class DiscoveryHandlerImpl extend
     private void tryConnect(URL serverURL) throws IOException {
         URLConnection connection = null;
         try {
-            connection = getAgentContext().getConnectionHandler().getConnection(serverURL);
+            connection = getConnectionHandler().getConnection(serverURL);
             connection.connect();
         }
         finally {

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java Wed Aug 28 12:28:00 2013
@@ -158,11 +158,11 @@ class DownloadCallableImpl implements Ca
             }
 
             if (m_abort) {
-                m_handle.logDebug("Download stopped");
+                m_handle.logDebug("Download stopped: %s" + m_source.toExternalForm());
                 m_handle.stoppedCallback(statusCode, headerFields, null);
             }
             else {
-                m_handle.logDebug("Download completed");
+                m_handle.logDebug("Download completed: %s", m_source.toExternalForm());
                 m_handle.successfulCallback(statusCode, headerFields);
             }
         }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java?rev=1518177&r1=1518176&r2=1518177&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java Wed Aug 28 12:28:00 2013
@@ -26,11 +26,8 @@ import org.apache.ace.agent.DownloadHand
 
 public class DownloadHandlerImpl extends ComponentBase implements DownloadHandler {
 
-    public static final String COMPONENT_IDENTIFIER = "download";
-    public static final String CONFIG_KEY_BASE = ConfigurationHandlerImpl.CONFIG_KEY_NAMESPACE + "." + COMPONENT_IDENTIFIER;
-
     public DownloadHandlerImpl() {
-        super(COMPONENT_IDENTIFIER);
+        super("downloads");
     }
 
     @Override
@@ -47,6 +44,6 @@ public class DownloadHandlerImpl extends
      * handle support methods
      */
     ExecutorService getExecutor() {
-        return getAgentContext().getExecutorService();
+        return getExecutorService();
     }
 }



Mime
View raw message