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/05/27 17:05:09 UTC

svn commit: r1486637 [1/2] - in /ace/trunk: org.apache.ace.agent.itest/.settings/ org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ org.apache.ace.agent.launcher/ org.apache.ace.agent.launcher/.settings/ org.apache.ace.agent.launcher/src/org/a...

Author: bramk
Date: Mon May 27 15:05:08 2013
New Revision: 1486637

URL: http://svn.apache.org/r1486637
Log:
ACE-347 Decoupled agent from CM

Added:
    ace/trunk/org.apache.ace.agent.itest/.settings/org.eclipse.jdt.core.prefs
    ace/trunk/org.apache.ace.agent.launcher/.settings/org.eclipse.jdt.core.prefs
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ManagementAgentFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHelper.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ManagementAgentFactoryImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Executer.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Scheduler.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/SchedulerTask.java
Removed:
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHandler.java
Modified:
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ManagementAgentTest.java
    ace/trunk/org.apache.ace.agent.launcher/bnd.bnd
    ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Main.java
    ace/trunk/org.apache.ace.agent/.classpath
    ace/trunk/org.apache.ace.agent/.settings/org.eclipse.jdt.core.prefs
    ace/trunk/org.apache.ace.agent/bnd.bnd
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/Constants.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryImpl.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentAdminDeployerFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentCheckTaskFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentServiceFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentUpdateTaskFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/discovery/PropertyBasedDiscoveryFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/IdentifierBasedIdentificationFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/PropertyBasedIdentificationFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/ifconfigBasedIdentificationFactory.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/agent-defaults.properties
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/EventLoggerFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogStoreFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogSyncTaskFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/spi/ComponentFactory.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/spi/ComponentFactoryBase.java
    ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/spi/OneComponentFactoryBase.java

Added: ace/trunk/org.apache.ace.agent.itest/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/.settings/org.eclipse.jdt.core.prefs?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/.settings/org.eclipse.jdt.core.prefs (added)
+++ ace/trunk/org.apache.ace.agent.itest/.settings/org.eclipse.jdt.core.prefs Mon May 27 15:05:08 2013
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

Modified: 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/ManagementAgentTest.java?rev=1486637&r1=1486636&r2=1486637&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/ManagementAgentTest.java Mon May 27 15:05:08 2013
@@ -18,19 +18,18 @@
  */
 package org.apache.ace.agent.itest;
 
-import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.Map;
 
 import junit.framework.Assert;
 
 import org.apache.ace.agent.ManagementAgent;
+import org.apache.ace.agent.ManagementAgentFactory;
 import org.apache.ace.it.IntegrationTestBase;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ManagedService;
 
 /**
  * Integration test for Management Agent Configuration
@@ -45,24 +44,24 @@ public class ManagementAgentTest extends
     public void testOneAgentConfiguration() throws Exception {
 
         // agent factory should be up
-        ManagedService agentConfiguration = getService(ManagedService.class, "(" + Constants.SERVICE_PID + "=" + org.apache.ace.agent.Constants.CONFIG_PID + ")");
-        Assert.assertNotNull(agentConfiguration);
+        ManagementAgentFactory agentFactory = getService(ManagementAgentFactory.class);
+        Assert.assertNotNull(agentFactory);
 
         assertAgentDown("007");
 
         // configure an agent
-        Dictionary<String, String> config = new Hashtable<String, String>();
+        Map<String, String> config = new Hashtable<String, String>();
         config.put("verbose", "true");
         config.put("agents", "007");
         config.put("serverurl", "http://localhost:8080");
         config.put("logstores", "auditlog");
-        agentConfiguration.updated(config);
+        agentFactory.updated(config);
 
         assertAgentUp("007");
 
         config = new Hashtable<String, String>();
         config.put("verbose", "true");
-        agentConfiguration.updated(config);
+        agentFactory.updated(config);
 
         assertAgentDown("007");
     }
@@ -74,26 +73,26 @@ public class ManagementAgentTest extends
     public void testTwoAgentsConfiguration() throws Exception {
 
         // agent factory should be up
-        ManagedService agentConfiguration = getService(ManagedService.class, "(" + Constants.SERVICE_PID + "=" + org.apache.ace.agent.Constants.CONFIG_PID + ")");
-        Assert.assertNotNull(agentConfiguration);
+        ManagementAgentFactory agentFactory = getService(ManagementAgentFactory.class);
+        Assert.assertNotNull(agentFactory);
 
         assertAgentDown("007");
         assertAgentDown("009");
 
         // configure an agent
-        Dictionary<String, String> config = new Hashtable<String, String>();
+        Map<String, String> config = new Hashtable<String, String>();
         config.put("verbose", "true");
         config.put("agents", "007,009");
         config.put("serverurl", "http://localhost:8080");
         config.put("logstores", "auditlog");
-        agentConfiguration.updated(config);
+        agentFactory.updated(config);
 
         assertAgentUp("007");
         assertAgentUp("009");
 
         config = new Hashtable<String, String>();
         config.put("verbose", "true");
-        agentConfiguration.updated(config);
+        agentFactory.updated(config);
 
         assertAgentDown("007");
         assertAgentDown("009");

Added: ace/trunk/org.apache.ace.agent.launcher/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/.settings/org.eclipse.jdt.core.prefs?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/.settings/org.eclipse.jdt.core.prefs (added)
+++ ace/trunk/org.apache.ace.agent.launcher/.settings/org.eclipse.jdt.core.prefs Mon May 27 15:05:08 2013
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

Modified: ace/trunk/org.apache.ace.agent.launcher/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/bnd.bnd?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent.launcher/bnd.bnd Mon May 27 15:05:08 2013
@@ -1,5 +1,4 @@
 -buildpath: osgi.core,\
-	osgi.cmpn,\
 	org.apache.felix.framework,\
 	org.apache.ace.agent;version=latest,\
 	commons-codec,\
@@ -11,10 +10,9 @@ Private-Package: org.apache.ace.*;-split
 	org.apache.commons.codec;-split-package:=merge-last,\
 	org.apache.commons.codec.binary;-split-package:=merge-last,\
 	org.osgi.framework.*;-split-package:=merge-last,\
-	org.osgi.service.*;-split-package:=merge-last,\
 	org.osgi.util.tracker;-split-package:=merge-last,\
+	org.osgi.service.*;-split-package:=merge-last,\
 	org.apache.commons.cli
-#	META-INF.org\.apache\.ace\.agent.*
 
 # This is not a real bundle
 Import-Package: 

Modified: ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Main.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Main.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Main.java (original)
+++ ace/trunk/org.apache.ace.agent.launcher/src/org/apache/ace/agent/launcher/Main.java Mon May 27 15:05:08 2013
@@ -24,15 +24,14 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 
-import org.apache.ace.agent.Constants;
+import org.apache.ace.agent.ManagementAgentFactory;
 import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
@@ -43,7 +42,6 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.launch.Framework;
 import org.osgi.framework.launch.FrameworkFactory;
-import org.osgi.service.cm.ManagedService;
 
 /**
  * A simple launcher, that launches the embedded Felix together with a management agent.
@@ -79,7 +77,7 @@ public class Main {
             }
         }
 
-        Dictionary<String, String> configuration = new Hashtable<String, String>();
+        Map<String, String> configuration = new Hashtable<String, String>();
 
         // first map all default properties
         for (Object key : defaultProperties.keySet()) {
@@ -137,10 +135,10 @@ public class Main {
         return properties;
     }
 
-    private final Dictionary<String, String> m_configuration;
+    private final Map<String, String> m_configuration;
     private final boolean m_verbose;
 
-    public Main(Dictionary<String, String> configuration) {
+    public Main(Map<String, String> configuration) {
         m_configuration = configuration;
         m_verbose = (m_configuration.get("verbose") != null) && Boolean.parseBoolean(m_configuration.get("verbose"));
     }
@@ -158,9 +156,9 @@ public class Main {
             if (m_verbose)
                 System.out.println("Configuring Management Agent.. " + m_configuration);
             BundleContext context = framework.getBundleContext();
-            ServiceReference[] references = context.getServiceReferences(ManagedService.class.getName(), "(" + org.osgi.framework.Constants.SERVICE_PID + "=" + Constants.CONFIG_PID + ")");
+            ServiceReference[] references = context.getServiceReferences(ManagementAgentFactory.class.getName(), null);
             if (references != null) {
-                ManagedService service = (ManagedService) context.getService(references[0]);
+                ManagementAgentFactory service = (ManagementAgentFactory) context.getService(references[0]);
                 service.updated(m_configuration);
                 context.ungetService(references[0]);
             }
@@ -195,12 +193,10 @@ public class Main {
     private Map<String, Object> createFrameworkProperties() throws Exception {
 
         Map<String, Object> frameworkProperties = new HashMap<String, Object>();
-        Enumeration<String> keyEnumeration = m_configuration.keys();
-        while (keyEnumeration.hasMoreElements()) {
-            String key = keyEnumeration.nextElement();
-            if (key.startsWith("framework.")) {
-                String frameworkKey = key.replaceFirst("framework.", "");
-                String frameworkValue = m_configuration.get(key);
+        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());
                 frameworkProperties.put(frameworkKey, frameworkValue);
             }
         }

Modified: ace/trunk/org.apache.ace.agent/.classpath
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/.classpath?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/.classpath (original)
+++ ace/trunk/org.apache.ace.agent/.classpath Mon May 27 15:05:08 2013
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

Modified: ace/trunk/org.apache.ace.agent/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/.settings/org.eclipse.jdt.core.prefs?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/.settings/org.eclipse.jdt.core.prefs (original)
+++ ace/trunk/org.apache.ace.agent/.settings/org.eclipse.jdt.core.prefs Mon May 27 15:05:08 2013
@@ -1,5 +1,9 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
 org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
 org.eclipse.jdt.core.compiler.problem.deadCode=warning
@@ -8,6 +12,7 @@ org.eclipse.jdt.core.compiler.problem.de
 org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
 org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
 org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
 org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
 org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
@@ -69,3 +74,4 @@ org.eclipse.jdt.core.compiler.problem.un
 org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6

Modified: ace/trunk/org.apache.ace.agent/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/bnd.bnd?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.agent/bnd.bnd Mon May 27 15:05:08 2013
@@ -29,11 +29,12 @@ Bundle-Version: 1.0.0
 # Management Agent can run in any plain vanilla framework.
 #	
 Private-Package: org.apache.ace.agent.connection,\
+	org.apache.ace.agent.scheduler.impl,\
+	org.apache.ace.agent.scheduler.impl,\
 	org.apache.felix.dm,\
 	org.apache.felix.dm.tracker,\
 	org.apache.felix.dm.tracker,\
 	org.osgi.service.log,\
-	org.osgi.service.useradmin,\
 	org.apache.ace.agent,\
 	org.apache.ace.agent.spi,\
 	org.apache.ace.deployment,\
@@ -45,7 +46,6 @@ Private-Package: org.apache.ace.agent.co
 	org.apache.ace.log.target.store,\
 	org.apache.ace.log.target.task,\
 	org.apache.ace.range,\
-	org.apache.ace.scheduler,\
 	org.apache.ace.agent.identification,\
 	org.apache.ace.consolelogger,\
 	org.apache.ace.connectionfactory.impl,\
@@ -75,11 +75,15 @@ Private-Package: org.apache.ace.agent.co
 #
 Export-Package: org.osgi.service.deploymentadmin;version=1.0;-split-package:=first,\
 	org.osgi.service.deploymentadmin.spi;version=1.0;-split-package:=first,\
-	org.osgi.service.event;version=1.2,\
-	org.osgi.service.cm;version=1.3,\
+	org.osgi.service.event;version=1.2;-split-package:=first,\
+	org.osgi.service.log;version=1.3;-split-package:=first,\
+	org.osgi.service.useradmin;version=1.2;-split-package:=first,\
 	org.apache.ace.agent
     
 # 
 # Make sure the apropriate imports are generated for the exported packages.
 #
-Import-Package:	*
+Import-Package:	\
+	!org.osgi.service.cm,\
+	*
+		
\ No newline at end of file

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/Constants.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/Constants.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/Constants.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/Constants.java Mon May 27 15:05:08 2013
@@ -18,24 +18,23 @@
  */
 package org.apache.ace.agent;
 
-import org.apache.ace.agent.impl.AgentFactory;
 
 /**
- * Compile time constants for the bundle. Only located in the API package for development time visbility.
+ * Compile time constants for the bundle. Only located in the API package for development time visibility.
  * 
  */
 public interface Constants {
 
     /**
-     * Configuration PID for the {@link AgentFactory}
+     * Configuration key for the list of agents.
      */
-    String FACTORY_PID = "org.apache.ace.agent.factory";
-
+    String CONFIG_AGENTS_KEY = "agents";
+    
     /**
-     * Configuration PID for the {@link ConfigurationHandler}
+     * Configuration key for the agent.
      */
-    String CONFIG_PID = "org.apache.ace.agent.config";
-
+    String CONFIG_AGENT_KEY = "agent";
+    
     /**
      * Configuration key for the list of component factories.
      */

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ManagementAgentFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ManagementAgentFactory.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ManagementAgentFactory.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/ManagementAgentFactory.java Mon May 27 15:05:08 2013
@@ -0,0 +1,30 @@
+/*
+ * 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.util.Map;
+
+/**
+ * Service interface for configuring the management agent.
+ *
+ */
+public interface ManagementAgentFactory {
+
+    void updated(Map<String, String> configuration) throws Exception;
+}

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryFactory.java Mon May 27 15:05:08 2013
@@ -20,6 +20,7 @@ package org.apache.ace.agent.connection;
 
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.Map;
 import java.util.Properties;
 
 import org.apache.ace.agent.connection.UrlCredentialsFactory.MissingValueException;
@@ -28,7 +29,6 @@ import org.apache.ace.connectionfactory.
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.log.LogService;
 
 /**
@@ -50,7 +50,7 @@ public class ConnectionFactoryFactory ex
         UrlCredentialsFactory.KEY_AUTH_USER_PASSWORD };
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         Properties properties = getAgentproperties(configuration);
         properties.put("impl.type", "jdk");
@@ -69,7 +69,7 @@ public class ConnectionFactoryFactory ex
                 credentials = UrlCredentialsFactory.getCredentials(urlCredentials);
             }
             catch (MissingValueException e) {
-                throw new ConfigurationException("authorization", e.getMessage(), e);
+                throw new Exception(e.getMessage(), e);
             }
         }
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryImpl.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/connection/ConnectionFactoryImpl.java Mon May 27 15:05:08 2013
@@ -35,8 +35,6 @@ import org.apache.ace.agent.connection.U
 import org.apache.ace.agent.connection.UrlCredentialsFactory.MissingValueException;
 import org.apache.ace.connectionfactory.ConnectionFactory;
 import org.apache.commons.codec.binary.Base64;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
 import org.osgi.service.useradmin.User;
 
 // FIXME This is a temporary modified copy of the org.apache.ace.connectionfactory.impl because it is private and does not
@@ -48,7 +46,7 @@ import org.osgi.service.useradmin.User;
  * Provides a default implementation for {@link ConnectionFactory} based on the standard <code>java.net</code>
  * implementation of {@link URLConnection}.
  */
-public class ConnectionFactoryImpl implements ConnectionFactory, ManagedServiceFactory {
+public class ConnectionFactoryImpl implements ConnectionFactory {
 
     public static final String FACTORY_PID = "org.apache.ace.connectionfactory";
 
@@ -129,7 +127,7 @@ public class ConnectionFactoryImpl imple
     /**
      * {@inheritDoc}
      */
-    public void updated(String pid, Dictionary properties) throws ConfigurationException {
+    public void updated(String pid, Dictionary properties) throws IllegalArgumentException {
         UrlCredentials creds;
         synchronized (m_credentialMapping) {
             creds = m_credentialMapping.get(pid);
@@ -143,7 +141,7 @@ public class ConnectionFactoryImpl imple
             }
         }
         catch (MissingValueException e) {
-            throw new ConfigurationException(e.getProperty(), e.getMessage());
+            throw new IllegalArgumentException(e.getMessage(), e);
         }
     }
 

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentAdminDeployerFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentAdminDeployerFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentAdminDeployerFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentAdminDeployerFactory.java Mon May 27 15:05:08 2013
@@ -18,14 +18,13 @@
  */
 package org.apache.ace.agent.deployment;
 
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.deployment.Deployment;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.deploymentadmin.DeploymentAdmin;
 import org.osgi.service.log.LogService;
 
@@ -36,7 +35,7 @@ import org.osgi.service.log.LogService;
 public class DeploymentAdminDeployerFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         return manager.createComponent()
             .setInterface(Deployment.class.getName(), getAgentproperties(configuration))

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentCheckTaskFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentCheckTaskFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentCheckTaskFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentCheckTaskFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.deployment;
 
-import java.util.Dictionary;
+import java.util.Map;
 import java.util.Properties;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
@@ -27,7 +27,6 @@ import org.apache.ace.scheduler.constant
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.event.EventAdmin;
 import org.osgi.service.log.LogService;
 
@@ -38,7 +37,7 @@ import org.osgi.service.log.LogService;
 public class DeploymentCheckTaskFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         Properties properties = getAgentproperties(configuration);
         properties.put(SchedulerConstants.SCHEDULER_NAME_KEY, DeploymentCheckTask.class.getSimpleName());

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentServiceFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentServiceFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentServiceFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentServiceFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.deployment;
 
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.connectionfactory.ConnectionFactory;
@@ -29,7 +29,6 @@ import org.apache.ace.identification.Ide
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.event.EventAdmin;
 import org.osgi.service.log.LogService;
 
@@ -40,7 +39,7 @@ import org.osgi.service.log.LogService;
 public class DeploymentServiceFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         return manager.createComponent()
             .setInterface(DeploymentService.class.getName(), getAgentproperties(configuration))

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentUpdateTaskFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentUpdateTaskFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentUpdateTaskFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/deployment/DeploymentUpdateTaskFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.deployment;
 
-import java.util.Dictionary;
+import java.util.Map;
 import java.util.Properties;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
@@ -27,7 +27,6 @@ import org.apache.ace.scheduler.constant
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.log.LogService;
 
 /**
@@ -37,7 +36,7 @@ import org.osgi.service.log.LogService;
 public class DeploymentUpdateTaskFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         Properties properties = getAgentproperties(configuration);
         properties.put(SchedulerConstants.SCHEDULER_NAME_KEY, DeploymentUpdateTask.class.getSimpleName());

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/discovery/PropertyBasedDiscoveryFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/discovery/PropertyBasedDiscoveryFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/discovery/PropertyBasedDiscoveryFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/discovery/PropertyBasedDiscoveryFactory.java Mon May 27 15:05:08 2013
@@ -20,14 +20,13 @@ package org.apache.ace.agent.discovery;
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.discovery.Discovery;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.log.LogService;
 
 /**
@@ -40,11 +39,11 @@ public class PropertyBasedDiscoveryFacto
     public static final String DISCOVERY_PROPERTY_VALUE = "serverurl";
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         final String urlStr = (String) configuration.get(DISCOVERY_PROPERTY_VALUE);
         if (urlStr == null || urlStr.equals("")) {
-            throw new ConfigurationException(DISCOVERY_PROPERTY_VALUE, "Missing a valid discovery value");
+            throw new IllegalArgumentException("Missing a valid discovery value");
         }
 
         try {
@@ -61,7 +60,7 @@ public class PropertyBasedDiscoveryFacto
                 .setInterface(Discovery.class.getName(), getAgentproperties(configuration)).setImplementation(impl);
         }
         catch (MalformedURLException e) {
-            throw new ConfigurationException(DISCOVERY_PROPERTY_VALUE, "Discovery URL is bad: " + urlStr);
+            throw new IllegalArgumentException("Discovery URL is bad: " + urlStr);
         }
     }
 }

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/IdentifierBasedIdentificationFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/IdentifierBasedIdentificationFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/IdentifierBasedIdentificationFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/IdentifierBasedIdentificationFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.identification;
 
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.identification.Identification;
@@ -35,7 +35,7 @@ import org.osgi.service.log.LogService;
 public class IdentifierBasedIdentificationFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         final String value = getAgentIdentifier(configuration);
         Identification impl = new Identification() {

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/PropertyBasedIdentificationFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/PropertyBasedIdentificationFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/PropertyBasedIdentificationFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/PropertyBasedIdentificationFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.identification;
 
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.discovery.Discovery;
@@ -39,7 +39,7 @@ public class PropertyBasedIdentification
     public static final String IDENTIFICATION_PROPERTY_VALUE = "identification";
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) throws ConfigurationException {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) throws Exception {
 
         final String value = configuration.get(IDENTIFICATION_PROPERTY_VALUE);
         if (value == null || value.equals("")) {

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/ifconfigBasedIdentificationFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/ifconfigBasedIdentificationFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/ifconfigBasedIdentificationFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/identification/ifconfigBasedIdentificationFactory.java Mon May 27 15:05:08 2013
@@ -18,7 +18,7 @@
  */
 package org.apache.ace.agent.identification;
 
-import java.util.Dictionary;
+import java.util.Map;
 
 import org.apache.ace.agent.spi.OneComponentFactoryBase;
 import org.apache.ace.identification.Identification;
@@ -34,7 +34,7 @@ import org.osgi.service.log.LogService;
 public class ifconfigBasedIdentificationFactory extends OneComponentFactoryBase {
 
     @Override
-    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Component createComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         Identification impl = new IfconfigIdentification();
         return manager.createComponent()

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=1486637&r1=1486636&r2=1486637&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 Mon May 27 15:05:08 2013
@@ -18,18 +18,16 @@
  */
 package org.apache.ace.agent.impl;
 
-import static org.apache.ace.agent.Constants.CONFIG_PID;
-import static org.apache.ace.agent.Constants.FACTORY_PID;
-
 import java.util.Properties;
 
+import org.apache.ace.agent.ManagementAgentFactory;
+import org.apache.ace.agent.scheduler.impl.Scheduler;
+import org.apache.ace.scheduler.constants.SchedulerConstants;
 import org.apache.felix.dm.DependencyActivatorBase;
 import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
 
 /**
@@ -38,28 +36,57 @@ import org.osgi.service.log.LogService;
  */
 public class Activator extends DependencyActivatorBase {
 
+    private Scheduler m_scheduler;
+
     @Override
     public void init(BundleContext context, DependencyManager manager) throws Exception {
 
         Properties properties = new Properties();
-        properties.put(Constants.SERVICE_PID, FACTORY_PID);
-        AgentFactory factory = new AgentFactory();
+        m_scheduler = new Scheduler();
         manager.add(createComponent()
-            .setInterface(ManagedServiceFactory.class.getName(), properties)
-            .setImplementation(factory)
-            .add(createServiceDependency().setService(LogService.class).setRequired(false)));
+            .setImplementation(m_scheduler)
+            .add(createServiceDependency()
+                .setService(LogService.class).setRequired(false))
+            .add(createServiceDependency()
+                .setService(Runnable.class).setRequired(false)
+                .setAutoConfig(false)
+                .setCallbacks(this, "addRunnable", "addRunnable", "removeRunnable")));
 
         properties = new Properties();
-        properties.put(Constants.SERVICE_PID, CONFIG_PID);
-        ConfigurationHandler handler = new ConfigurationHandler();
+        ManagementAgentFactoryImpl factory = new ManagementAgentFactoryImpl();
         manager.add(createComponent()
-            .setInterface(ManagedService.class.getName(), properties)
-            .setImplementation(handler)
-            .add(createServiceDependency().setService(ManagedServiceFactory.class, "(" + Constants.SERVICE_PID + "=" + FACTORY_PID + ")").setRequired(true))
+            .setInterface(ManagementAgentFactory.class.getName(), properties)
+            .setImplementation(factory)
             .add(createServiceDependency().setService(LogService.class).setRequired(false)));
+
     }
 
     @Override
     public void destroy(BundleContext context, DependencyManager manager) throws Exception {
     }
+
+    /**
+     * Handler for both adding and updating runnable service registrations.
+     * 
+     * @throws Exception
+     *             Is thrown when the <code>SCHEDULER_RECIPE</code> contained in <code>ref</code>'s service dictionary
+     *             cannot be parsed by the scheduler.
+     */
+    public void addRunnable(ServiceReference ref, Runnable task) throws Exception {
+        String name = (String) ref.getProperty(SchedulerConstants.SCHEDULER_NAME_KEY);
+        if (name != null) {
+            String description = (String) ref.getProperty(SchedulerConstants.SCHEDULER_DESCRIPTION_KEY);
+            Object recipe = ref.getProperty(SchedulerConstants.SCHEDULER_RECIPE);
+            boolean recipeOverride = Boolean.valueOf((String) ref.getProperty(SchedulerConstants.SCHEDULER_RECIPE_OVERRIDE)).booleanValue();
+            m_scheduler.addRunnable(name, task, description, recipe, recipeOverride);
+        }
+    }
+
+    public synchronized void removeRunnable(ServiceReference ref, Runnable task) {
+        String name = (String) ref.getProperty(SchedulerConstants.SCHEDULER_NAME_KEY);
+        if (name != null) {
+            m_scheduler.removeRunnable(name);
+        }
+    }
+
 }

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHelper.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHelper.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHelper.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ConfigurationHelper.java Mon May 27 15:05:08 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.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.ace.agent.Constants;
+import org.apache.ace.agent.spi.ComponentFactory;
+import org.osgi.framework.BundleActivator;
+
+/**
+ * Handles management agent configuration system properties and subsequently calls
+ * {@link ManagementAgentFactoryImpl#updated(String, Dictionary)} for every agent specific configuration.
+ * 
+ */
+public class ConfigurationHelper {
+
+    private static final String DEFAULTS_RESOURCE = "org/apache/ace/agent/impl/agent-defaults.properties";
+    private final Map<String, String> m_configuration;
+    private final boolean m_verbose;
+
+    private final BundleActivator[] m_bundleActivators;
+    private final String[] m_agentIds;
+    private final Map<String, Map<String, String>> m_agentConfigurations;
+    private final Map<String, ComponentFactory[]> m_agentComponentFactories;
+
+    public ConfigurationHelper(Map<String, String> configuration) throws Exception {
+
+        m_configuration = loadDefaultConfiguration();
+        m_configuration.putAll(configuration);
+        m_verbose = configuration.get("verbose") != null && Boolean.parseBoolean((String) configuration.get("verbose"));
+
+        // eager loading for failfast
+        m_agentIds = loadAgentIds();
+        m_bundleActivators = loadBundleActivators();
+        m_agentConfigurations = new HashMap<String, Map<String, String>>();
+        m_agentComponentFactories = new HashMap<String, ComponentFactory[]>();
+        for (String agentId : m_agentIds) {
+            m_agentConfigurations.put(agentId, loadAgentConfiguration(agentId));
+            m_agentComponentFactories.put(agentId, loadComponentFactories(agentId));
+        }
+    }
+
+    public boolean isVerbose() {
+        return m_verbose;
+    }
+
+    public String[] getAgentIds() {
+        return m_agentIds;
+    }
+
+    public BundleActivator[] getBundleActivators() throws Exception {
+        return m_bundleActivators;
+    }
+
+    public ComponentFactory[] getComponentFactories(String agentId) throws Exception {
+        return m_agentComponentFactories.get(agentId);
+    }
+
+    public Map<String, String> getAgentConfiguration(String agentId) throws Exception {
+        return m_agentConfigurations.get(agentId);
+    }
+
+    private String[] loadAgentIds() {
+        List<String> agentList = getStringListProperty(m_configuration, Constants.CONFIG_AGENTS_KEY);
+        return agentList.toArray(new String[agentList.size()]);
+    }
+
+    private BundleActivator[] loadBundleActivators() throws Exception {
+        List<String> bundleActivatorList = getStringListProperty(m_configuration, Constants.CONFIG_ACTIVATORS_KEY);
+        BundleActivator[] bundleActivators = new BundleActivator[bundleActivatorList.size()];
+        int i = 0;
+        for (String bundleActivatorName : bundleActivatorList) {
+            bundleActivators[i++] = loadBundleActivator(bundleActivatorName);
+        }
+        return bundleActivators;
+    }
+
+    private ComponentFactory[] loadComponentFactories(String agentId) throws Exception {
+        Map<String, String> agentConfiguration = getAgentConfiguration(agentId);
+        List<String> componentFactryList = getStringListProperty(agentConfiguration, Constants.CONFIG_FACTORIES_KEY);
+        ComponentFactory[] componentFactories = new ComponentFactory[componentFactryList.size()];
+        int i = 0;
+        for (String componentFactory : componentFactryList) {
+            componentFactories[i++] = loadComponentFactory(componentFactory);
+        }
+        return componentFactories;
+    }
+
+    private Map<String, String> loadAgentConfiguration(String agentId) throws Exception {
+
+        String agentPrefix = agentId + ".";
+        Map<String, String> agentConfiguration = new HashMap<String, String>();
+        // first map all global properties
+        for (Entry<String, String> entry : m_configuration.entrySet()) {
+            if (!entry.getKey().startsWith(agentPrefix)) {
+                agentConfiguration.put(entry.getKey(), entry.getValue());
+            }
+        }
+        // overwrite with agent specific properties
+        for (Entry<String, String> entry : m_configuration.entrySet()) {
+            if (entry.getKey().startsWith(agentPrefix)) {
+                agentConfiguration.put(entry.getKey().replaceFirst(agentPrefix, ""), entry.getValue());
+            }
+        }
+        agentConfiguration.put("agent", agentId);
+        return agentConfiguration;
+    }
+
+    private List<String> getStringListProperty(Map<String, String> configuration, String key) {
+        List<String> values = new ArrayList<String>();
+        String value = (String) m_configuration.get(key);
+        if (value != null && !value.equals("")) {
+            String[] parts = value.split(",");
+            for (String part : parts) {
+                values.add(part.trim());
+            }
+        }
+        return values;
+    }
+
+    private Map<String, String> loadDefaultConfiguration() throws IOException {
+        Properties properties = new Properties();
+        ClassLoader classloader = getClass().getClassLoader();
+        InputStream inStream = classloader.getResourceAsStream(DEFAULTS_RESOURCE);
+        if (inStream != null) {
+            try {
+                properties.load(inStream);
+            }
+            finally {
+                inStream.close();
+            }
+        }
+        Map<String, String> configuration = new HashMap<String, String>();
+        for (Object key : properties.keySet()) {
+            configuration.put((String) key, (String) properties.getProperty((String) key));
+        }
+        return configuration;
+    }
+
+    private BundleActivator loadBundleActivator(String bundleActivatorName) throws Exception {
+        try {
+            Class<?> clazz = ConfigurationHelper.class.getClassLoader().loadClass(bundleActivatorName);
+            if (!BundleActivator.class.isAssignableFrom(clazz)) {
+                throw new Exception("Factory class does not implement ComponentFactory interface: " + bundleActivatorName);
+            }
+            try {
+                Object instance = clazz.newInstance();
+                return (BundleActivator) instance;
+            }
+            catch (InstantiationException e) {
+                throw new Exception("BundleActivator class does not have a default constructor: " + bundleActivatorName);
+            }
+            catch (IllegalAccessException e) {
+                throw new Exception("BundleActivator class does not have a default constructor: " + bundleActivatorName);
+            }
+        }
+        catch (ClassNotFoundException e) {
+            throw new Exception("BundleActivator class not found: " + bundleActivatorName);
+        }
+    }
+
+    private ComponentFactory loadComponentFactory(String componentFactoryName) throws Exception {
+        try {
+            Class<?> clazz = ManagementAgentFactoryImpl.class.getClassLoader().loadClass(componentFactoryName);
+            if (!ComponentFactory.class.isAssignableFrom(clazz)) {
+                throw new Exception("Factory class does not implement ComponentFactory interface: " + componentFactoryName);
+            }
+            try {
+                Object instance = clazz.newInstance();
+                return (ComponentFactory) instance;
+            }
+            catch (InstantiationException e) {
+                throw new Exception("Factory class does not have a default constructor: " + componentFactoryName);
+            }
+            catch (IllegalAccessException e) {
+                throw new Exception("Factory class does not have a default constructor: " + componentFactoryName);
+            }
+        }
+        catch (Exception e) {
+            throw new Exception("Factory class not found: " + componentFactoryName);
+        }
+    }
+
+}

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ManagementAgentFactoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ManagementAgentFactoryImpl.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ManagementAgentFactoryImpl.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/ManagementAgentFactoryImpl.java Mon May 27 15:05:08 2013
@@ -0,0 +1,182 @@
+/*
+ * 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.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.ace.agent.ManagementAgent;
+import org.apache.ace.agent.ManagementAgentFactory;
+import org.apache.ace.agent.spi.ComponentFactory;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+/**
+ * Factory that handles configuration of management agents services. For every subsystem a {@link ComponentFactory} is
+ * used to instantiate the actual components. Factories can be specified through configuration using a
+ * <code>&lt;subsystem&gt;.factory</code> property.
+ */
+public class ManagementAgentFactoryImpl implements ManagementAgentFactory {
+
+    private final Set<BundleActivator> m_startedActivators = new HashSet<BundleActivator>();
+    private final Map<String, Set<Component>> m_agentComponents = new HashMap<String, Set<Component>>();
+
+    // guards all state against concurrent updates without locking
+    private final AtomicBoolean m_updating = new AtomicBoolean(false);
+
+    private volatile BundleContext m_context;
+    private volatile DependencyManager m_manager;
+    private volatile LogService m_logService;
+    private volatile boolean m_verbose;
+
+    @Override
+    public void updated(Map<String, String> configuration) throws Exception {
+
+        if (!m_updating.compareAndSet(false, true)) {
+            m_logService.log(LogService.LOG_WARNING, "Receiving updated while updating! Ignoring...");
+            return;
+        }
+        try {
+
+            ConfigurationHelper configurationHelper = new ConfigurationHelper(configuration);
+            m_verbose = configurationHelper.isVerbose();
+            m_logService.log(LogService.LOG_DEBUG, "Receiving updated configuration");
+            if (m_verbose) {
+                System.out.println("Receiving updated configuration");
+            }
+
+            removeAgents();
+            stopBundleActivators();
+            startBundleActivators(configurationHelper);
+            createAgents(configurationHelper);
+        }
+        catch (Exception e) {
+            m_logService.log(LogService.LOG_ERROR, "Agent update failed! ", e);
+        }
+        finally {
+            m_updating.set(false);
+        }
+    }
+
+    private void createAgents(ConfigurationHelper configurationHelper) throws Exception {
+        for (String agentId : configurationHelper.getAgentIds()) {
+            Map<String, String> agentConfiguration = configurationHelper.getAgentConfiguration(agentId);
+            ComponentFactory[] componentFactories = configurationHelper.getComponentFactories(agentId);
+            createAgent(agentId, componentFactories, agentConfiguration);
+        }
+    }
+
+    private void createAgent(String agentId, ComponentFactory[] componentFactories, Map<String, String> agentConfiguration) throws Exception {
+        try {
+            Set<Component> components = new HashSet<Component>();
+            for (ComponentFactory componentFactory : componentFactories) {
+                components.addAll(componentFactory.createComponents(m_context, m_manager, m_logService, agentConfiguration));
+            }
+
+            Properties agentProperties = new Properties();
+            agentProperties.put("agent", agentId);
+            Component agentComponent = m_manager.createComponent()
+                .setInterface(ManagementAgent.class.getName(), agentProperties)
+                .setImplementation(new ManagementAgent() {
+                });
+            components.add(agentComponent);
+
+            m_agentComponents.put(agentId, components);
+            for (Component component : components) {
+                m_manager.add(component);
+            }
+        }
+        catch (Exception e) {
+            if (m_verbose) {
+                System.err.println("Failed to create agent component!");
+                e.printStackTrace();
+            }
+            m_logService.log(LogService.LOG_ERROR, "Failed to create agent component: " + e.getMessage(), e);
+            throw e;
+        }
+    }
+
+    private void removeAgents() {
+        for (Entry<String, Set<Component>> entry : m_agentComponents.entrySet()) {
+            for (Component component : entry.getValue()) {
+                try {
+                    System.err.println("Removing " + entry.getKey() + " " + component);
+                    m_manager.remove(component);
+                }
+                catch (Exception e) {
+                    if (m_verbose) {
+                        System.err.println("Failed to remove agent component!");
+                        e.printStackTrace();
+                    }
+                    m_logService.log(LogService.LOG_ERROR, "Failed to remove agent component: " + e.getMessage(), e);
+                }
+            }
+        }
+        m_agentComponents.clear();
+    }
+
+    private void startBundleActivators(ConfigurationHelper configurationHelper) throws Exception {
+        System.out.println("Starting system activators.. ");
+        for (BundleActivator bundleActivator : configurationHelper.getBundleActivators()) {
+            System.out.println("Starting system activator.. " + bundleActivator.getClass().getName());
+            if (m_verbose) {
+                System.out.println("Starting system activator.. " + bundleActivator.getClass().getName());
+            }
+            try {
+                bundleActivator.start(m_context);
+                m_startedActivators.add(bundleActivator);
+            }
+            catch (Exception e) {
+                if (m_verbose) {
+                    System.err.println("Activator start exception!");
+                    e.printStackTrace();
+                }
+                m_logService.log(LogService.LOG_ERROR, "Activator stop exception!", e);
+                throw e;
+            }
+        }
+        System.out.println("Started system activators.. ");
+    }
+
+    private void stopBundleActivators() throws Exception {
+        for (BundleActivator activator : m_startedActivators) {
+            if (m_verbose)
+                System.out.println("Stopping system activator.. " + activator.getClass().getName());
+            try {
+                activator.stop(m_context);
+            }
+            catch (Exception e) {
+                if (m_verbose) {
+                    System.err.println("Activator stop exception!");
+                    e.printStackTrace();
+                }
+                m_logService.log(LogService.LOG_ERROR, "Activator stop exception!", e);
+            }
+            m_startedActivators.clear();
+        }
+    }
+}

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/agent-defaults.properties
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/agent-defaults.properties?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/agent-defaults.properties (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/agent-defaults.properties Mon May 27 15:05:08 2013
@@ -29,5 +29,4 @@ system.factories= org.apache.ace.agent.i
 # handled by the management agent configuration component once, before configuring any agents. 
 # All classes MUST be on the (system)bundle class-path.
 #
-system.activators= org.apache.ace.scheduler.Activator,\
-	org.apache.felix.deploymentadmin.Activator	
+system.activators= org.apache.felix.deploymentadmin.Activator	

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/EventLoggerFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/EventLoggerFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/EventLoggerFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/EventLoggerFactory.java Mon May 27 15:05:08 2013
@@ -18,8 +18,8 @@
  */
 package org.apache.ace.agent.logging;
 
-import java.util.Dictionary;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -48,7 +48,7 @@ public class EventLoggerFactory extends 
     public static final String LOG_NAME = "name";
 
     @Override
-    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         Set<Component> components = new HashSet<Component>();
         String value = configuration.get(LOG_STORES);
@@ -59,7 +59,7 @@ public class EventLoggerFactory extends 
         return components;
     }
 
-    private Component createEventLoggerComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration, String store) {
+    private Component createEventLoggerComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration, String store) {
 
         Properties properties = getAgentproperties(configuration);
         properties.put("name", store);

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogFactory.java Mon May 27 15:05:08 2013
@@ -18,8 +18,8 @@
  */
 package org.apache.ace.agent.logging;
 
-import java.util.Dictionary;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -41,7 +41,7 @@ public class LogFactory extends Componen
     public static final String LOG_NAME = "name";
 
     @Override
-    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         Set<Component> components = new HashSet<Component>();
         String value = configuration.get(LOG_STORES);
@@ -52,11 +52,11 @@ public class LogFactory extends Componen
         return components;
     }
 
-    private Component createLogComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration, String store) {
+    private Component createLogComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration, String store) {
 
         Properties properties = getAgentproperties(configuration);
         properties.put("name", store);
-        
+
         return manager.createComponent()
             .setInterface(Log.class.getName(), properties)
             .setImplementation(new LogImpl())

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogStoreFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogStoreFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogStoreFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogStoreFactory.java Mon May 27 15:05:08 2013
@@ -19,8 +19,8 @@
 package org.apache.ace.agent.logging;
 
 import java.io.File;
-import java.util.Dictionary;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -39,7 +39,7 @@ import org.osgi.service.log.LogService;
 public class LogStoreFactory extends ComponentFactoryBase {
 
     @Override
-    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         Set<Component> components = new HashSet<Component>();
         String value = configuration.get(LogFactory.LOG_STORES);
@@ -50,7 +50,7 @@ public class LogStoreFactory extends Com
         return components;
     }
 
-    private Component createLogStoreComponent(BundleContext context, DependencyManager manager, Dictionary<String, String> configuration, LogService logService, String store) {
+    private Component createLogStoreComponent(BundleContext context, DependencyManager manager, Map<String, String> configuration, LogService logService, String store) {
 
         Properties properties = getAgentproperties(configuration);
         properties.put(LogFactory.LOG_NAME, store);

Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogSyncTaskFactory.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogSyncTaskFactory.java?rev=1486637&r1=1486636&r2=1486637&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogSyncTaskFactory.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/logging/LogSyncTaskFactory.java Mon May 27 15:05:08 2013
@@ -18,8 +18,8 @@
  */
 package org.apache.ace.agent.logging;
 
-import java.util.Dictionary;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -42,7 +42,7 @@ import org.osgi.service.log.LogService;
 public class LogSyncTaskFactory extends ComponentFactoryBase {
 
     @Override
-    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration) {
+    public Set<Component> createComponents(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration) {
 
         Set<Component> components = new HashSet<Component>();
         String value = configuration.get(LogFactory.LOG_STORES);
@@ -61,7 +61,7 @@ public class LogSyncTaskFactory extends 
         return components;
     }
 
-    private Component createLogSyncComponent(BundleContext context, DependencyManager manager, LogService logService, Dictionary<String, String> configuration, String store) {
+    private Component createLogSyncComponent(BundleContext context, DependencyManager manager, LogService logService, Map<String, String> configuration, String store) {
 
         Properties props = getAgentproperties(configuration);
         props.put(LogFactory.LOG_NAME, store);

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Executer.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Executer.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Executer.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Executer.java Mon May 27 15:05:08 2013
@@ -0,0 +1,102 @@
+/*
+ * 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.scheduler.impl;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * This class wraps a <code>Runnable</code> in a <code>TimerTask</code> that allows
+ * it to be periodically run and to be stopped as soon as possible.
+ */
+public class Executer extends TimerTask {
+    private final Timer m_timer = new Timer();
+    private final Runnable m_task;
+    private boolean m_stop = false;
+    private boolean m_stopped = true;
+
+    /**
+     * Creates a new instance of this class.
+     *
+     * @param task The task that should be periodically run.
+     */
+    public Executer(Runnable task) {
+        m_task = task;
+    }
+
+    /**
+     * Start executing the task repeatedly with an interval as specified.
+     *
+     * @param interval The interval between executions of the task, in milliseconds.
+     */
+    void start(long interval) {
+        if (interval > 0) {
+            m_timer.schedule(this, 0, interval);
+        }
+    }
+
+    /**
+     * Stop periodically executing this task. If the task is currently executing it
+     * will never be run again after the current execution, otherwise it will simply
+     * never run (again).
+     */
+    void stop() {
+        synchronized (m_timer) {
+            if (!m_stop) {
+                m_stop = true;
+                cancel();
+                m_timer.cancel();
+            }
+
+            boolean interrupted = false;
+            while (!m_stopped) {
+                try {
+                    m_timer.wait();
+                }
+                catch (InterruptedException e) {
+                    interrupted = true;
+                }
+            }
+            if (interrupted) {
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    public void run() {
+        synchronized (m_timer) {
+            m_stopped = false;
+            if (m_stop) {
+                m_stopped = true;
+                m_timer.notifyAll();
+                return;
+            }
+        }
+        try {
+            m_task.run();
+        }
+        catch (Exception e) {
+            // TODO we should log this somehow
+        }
+        synchronized (m_timer) {
+            m_stopped = true;
+            m_timer.notifyAll();
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Scheduler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Scheduler.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Scheduler.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/Scheduler.java Mon May 27 15:05:08 2013
@@ -0,0 +1,143 @@
+/*
+ * 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.scheduler.impl;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+
+/**
+ * The scheduler periodically runs tasks based on a scheduling recipe. Tasks can be added and
+ * removed using the <code>addRunnable</code> and <code>removeRunnable</code> methods. Recipes are
+ * supplied using configuration properties using the <code>updated</code> method, or are
+ * passed in the task's properties.<br>
+ *
+ * A task will be scheduled if both a <code>Runnable</code> and a <code>recipe</code> are available
+ * for it.
+ */
+public class Scheduler {
+    
+    protected Map m_tasks = new HashMap/*<String, SchedulerTask>*/();
+    private volatile LogService m_log;
+
+    /**
+     * Makes sure that all tasks are indeed stopped when the scheduler is stopped.
+     */
+    public void stop() {
+        for (Iterator i = m_tasks.keySet().iterator(); i.hasNext();) {
+            String name = (String) i.next();
+            SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+            schedTask.stop();
+        }
+    }
+
+    /**
+     * Adds a new runnable to this scheduler. The runnable will be created if necessary, registered, and processed.
+     * @param name A name for this task.
+     * @param task A runnable to run for this task.
+     * @param description A description of the task.
+     * @param recipe Optionally, a recipe for running this task.
+     * @param recipeOverride Indicates whether or not the <code>recipe</code> passed in prevails over
+     * any recipe provided by the <code>Scheduler</code>'s configuration.
+     * @throws ConfigurationException When <code>recipe</code> is not <code>null</code>, and cannot
+     * be decoded into a recipe.
+     */
+    public synchronized void addRunnable(String name, Runnable task, String description, Object recipe, boolean recipeOverride) throws Exception {
+        SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+        if (schedTask == null) {
+            schedTask = new SchedulerTask(name);
+            m_tasks.put(name, schedTask);
+        }
+        schedTask.updateTask(task, description, recipe, recipeOverride);
+        schedTask.process();
+    }
+
+    /**
+     * Removes a runnable from this scheduler.
+     * @param name The name of the runnable. If the name does not indicate a valid runnable,
+     * nothing is done.
+     */
+    public synchronized void removeRunnable(String name) {
+        SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+        if (schedTask != null) {
+            try {
+                schedTask.updateTask(null, null, null, false);
+            }
+            catch (Exception e) {
+                // Will not occur; a null recipe will not cause an exception.
+            }
+            if (!schedTask.process()) {
+                m_tasks.remove(name);
+            }
+        }
+    }
+
+    /**
+     * Updates the configuration of the scheduler. The scheduler expects the configuration
+     * to contain recipes for scheduling. The key of a property should be the name identifying
+     * a task and the value should be a string describing the scheduling recipe for this task.
+     */
+    public void updated(Dictionary properties) throws Exception {
+        if (properties != null) {
+            // first remove all the old schedules.
+            for (Iterator i = m_tasks.keySet().iterator(); i.hasNext();) {
+                String name = (String) i.next();
+                SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+                schedTask.updateConfigurationRecipe(null);
+            }
+
+            // then apply the new ones
+            properties.remove(Constants.SERVICE_PID);
+            Enumeration keys = properties.keys();
+            while (keys.hasMoreElements()) {
+                String name = (String) keys.nextElement();
+                SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+                if (schedTask == null) {
+                    schedTask = new SchedulerTask(name);
+                    m_tasks.put(name, schedTask);
+                }
+                try {
+                    schedTask.updateConfigurationRecipe(properties.get(name));
+                }
+                catch (Exception ce) {
+                    // This is most likely an illegal recipe, caused by an config property we don't understand.
+                    // So, no problem.
+                    m_log.log(LogService.LOG_INFO,
+                            name + "=" + properties.get(name) + " does not look like a valid schedule recipe.");
+                }
+            }
+
+            // and remove all tasks that now have no schedule or runnable
+            for (Iterator i = m_tasks.keySet().iterator(); i.hasNext();) {
+                String name = (String) i.next();
+                SchedulerTask schedTask = (SchedulerTask) m_tasks.get(name);
+                if (!schedTask.process()) {
+                    i.remove();
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/SchedulerTask.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/SchedulerTask.java?rev=1486637&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/SchedulerTask.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/scheduler/impl/SchedulerTask.java Mon May 27 15:05:08 2013
@@ -0,0 +1,185 @@
+/*
+ * 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.scheduler.impl;
+
+
+/**
+ * Wrapper class for collecting a <code>Runnable</code> and its corresponding <code>recipe</code>(s).
+ * Will schedule the task when both a schedule and a <code>Runnable</code> are available.<br>
+ */
+public class SchedulerTask {
+    private final String m_name;
+    private Runnable m_task;
+    private String m_description;
+    private Object m_configurationRecipe;
+    private Object m_taskRecipe;
+    private boolean m_recipeOverride;
+    private Object m_currentRecipe;
+    private Executer m_executer;
+
+    /**
+     * Creates instance of this class.
+     * @param name The name of the runnable task.
+     */
+    SchedulerTask(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("A SchedulerTask's name cannot be null.");
+        }
+        m_name = name;
+    }
+
+    public String getName() {
+        return m_name;
+    }
+
+    public String getDescription() {
+        return m_description;
+    }
+
+    public Runnable getTask() {
+        return m_task;
+    }
+
+    /**
+     * Returns the currently most suited recipe, if any. This function not returning
+     * <code>null</code> does not mean that the task is scheduled (it may still be missing
+     * a <code>Runnable</code>).
+     */
+    public Object getCurrentRecipe() {
+        return m_currentRecipe;
+    }
+
+    /**
+     * Indicates whether this task is actually scheduled, and thus will run at some time
+     * in the future, unless the schedule is set to <code>null</code>, or the <code>Runnable</code>
+     * is removed.
+     */
+    public boolean isScheduled() {
+        return m_executer != null;
+    }
+
+    /**
+     * States a new set of properties for this task.
+     * @param task A runnable to run for this task.
+     * @param description A description of the task.
+     * @param taskRecipe Optionally, a recipe for running this task.
+     * @param recipeOverride Indicates whether or not the <code>recipe</code> passed in prevails over
+     * any recipe provided by the <code>Scheduler</code>'s configuration.
+     * @throws ConfigurationException When <code>recipe</code> is not <code>null</code>, and cannot
+     * be decoded into a recipe.
+     */
+    public void updateTask(Runnable task, String description, Object taskRecipe, boolean recipeOverride) throws Exception {
+        checkRecipe(taskRecipe);
+        m_task = task;
+        m_description = description;
+        m_taskRecipe = taskRecipe;
+        m_recipeOverride = recipeOverride;
+    }
+
+    /**
+     * States a new recipe as coming from a configuration.
+     * @param recipe Optionally, a recipe for running this task.
+     * @throws ConfigurationException When <code>recipe</code> is not <code>null</code>, and cannot
+     * be decoded into a recipe.
+     */
+    public void updateConfigurationRecipe(Object recipe) throws Exception {
+        checkRecipe(recipe);
+        m_configurationRecipe = recipe;
+    }
+
+    public void stop() {
+        if (m_executer != null) {
+            m_executer.stop();
+            m_executer = null;
+        }
+    }
+
+    public boolean process() {
+        Object recipe = findRecipe();
+        if ((recipe != null) && (m_task != null)) {
+            if (!recipe.equals(m_currentRecipe) && (m_executer != null)) {
+                m_executer.stop();
+                m_executer = null;
+            }
+            if (m_executer == null) {
+                m_executer = new Executer(m_task);
+                m_executer.start(parseScheduleRecipe(recipe));
+            }
+        }
+        else {
+            // there is nothing to do, since there is no recipe or task
+            stop();
+        }
+        m_currentRecipe = recipe;
+        return ((recipe != null) || (m_task != null));
+    }
+
+    /**
+     * Finds the most suitable recipe for the given task, using both the properties published
+     * with the task, and the scheduler service's properties.
+     * @return An <code>Object</code> representing the scheduler recipe, if any. If no suitable recipe can be found,
+     * <code>null</code> will be returned.
+     */
+    private Object findRecipe() {
+        if (m_recipeOverride) {
+            if (m_taskRecipe != null) {
+                return m_taskRecipe;
+            }
+            else if (m_configurationRecipe != null) {
+                return m_configurationRecipe;
+            }
+        }
+        else {
+            if (m_configurationRecipe != null) {
+                return m_configurationRecipe;
+            }
+            else if (m_taskRecipe != null) {
+                return m_taskRecipe;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Decodes an Object into a schedule.
+     * @param recipe An object representing a recipe.
+     * @return A decoded representation of the recipe.
+     */
+    private long parseScheduleRecipe(Object recipe) {
+        // For now assume just the number of milliseconds is in the string, we may want to do a
+        // more 'cron-like' scheduling in the future
+        return Long.valueOf(recipe.toString()).longValue();
+    }
+
+    /**
+     * Helper method that checks whether a recipe is valid.
+     * @throws ConfigurationException When <code>recipe</code> is not <code>null</code>, and cannot
+     * be decoded into a recipe.
+     */
+    private void checkRecipe(Object recipe) throws Exception {
+        if (recipe != null) {
+            try {
+                parseScheduleRecipe(recipe);
+            }
+            catch (NumberFormatException nfe) {
+                throw new Exception("Could not parse scheduling recipe for task", nfe);
+            }
+        }
+    }
+}
\ No newline at end of file