Return-Path: X-Original-To: apmail-ace-commits-archive@www.apache.org Delivered-To: apmail-ace-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BAA5510D0E for ; Mon, 26 Aug 2013 08:59:01 +0000 (UTC) Received: (qmail 24960 invoked by uid 500); 26 Aug 2013 08:59:01 -0000 Delivered-To: apmail-ace-commits-archive@ace.apache.org Received: (qmail 24931 invoked by uid 500); 26 Aug 2013 08:59:00 -0000 Mailing-List: contact commits-help@ace.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ace.apache.org Delivered-To: mailing list commits@ace.apache.org Received: (qmail 24918 invoked by uid 99); 26 Aug 2013 08:59:00 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 Aug 2013 08:59:00 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 Aug 2013 08:58:53 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 10E2F23889E0; Mon, 26 Aug 2013 08:58:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1517469 - in /ace/trunk/org.apache.ace.agent: ./ src/org/apache/ace/agent/impl/ Date: Mon, 26 Aug 2013 08:58:30 -0000 To: commits@ace.apache.org From: bramk@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20130826085831.10E2F23889E0@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bramk Date: Mon Aug 26 08:58:30 2013 New Revision: 1517469 URL: http://svn.apache.org/r1517469 Log: ACE-347 Extracted some inner classes / Replace DM Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java Modified: ace/trunk/org.apache.ace.agent/bnd.bnd 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/EventLoggerImpl.java Modified: ace/trunk/org.apache.ace.agent/bnd.bnd URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/bnd.bnd?rev=1517469&r1=1517468&r2=1517469&view=diff ============================================================================== --- ace/trunk/org.apache.ace.agent/bnd.bnd (original) +++ ace/trunk/org.apache.ace.agent/bnd.bnd Mon Aug 26 08:58:30 2013 @@ -15,14 +15,6 @@ Private-Package: org.apache.ace.range,\ org.apache.commons.codec.net,\ org.apache.felix.deploymentadmin,\ org.apache.felix.deploymentadmin.spi,\ - org.apache.felix.dm.impl.dependencies,\ - org.apache.felix.dm,\ - org.apache.felix.dm.impl,\ - org.apache.felix.dm.impl.index,\ - org.apache.felix.dm.impl.metatype,\ - org.apache.felix.dm.tracker,\ - org.osgi.service.metatype,\ - org.osgi.service.cm,\ org.osgi.service.event,\ org.osgi.service.log,\ org.osgi.util.tracker @@ -39,12 +31,12 @@ Export-Package: org.apache.ace.agent,\ org.osgi.service.deploymentadmin;-split-package:=merge-last,\ org.osgi.service.deploymentadmin.spi;-split-package:=merge-last + -buildpath: osgi.core;version=4.2,\ osgi.cmpn;version=4.2,\ javax.servlet;version=2.5,\ org.apache.felix.deploymentadmin;version=0.9.4,\ org.easymock,\ - org.apache.felix.dependencymanager,\ commons-codec;version=1.4.0,\ org.apache.felix.http.jetty;version=2.2.1,\ org.apache.ace.range.api;version=latest,\ 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=1517469&r1=1517468&r2=1517469&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 Aug 26 08:58:30 2013 @@ -21,11 +21,8 @@ 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.Date; import java.util.Dictionary; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; +import java.util.Hashtable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; @@ -34,224 +31,200 @@ import org.apache.ace.agent.AgentControl import org.apache.ace.agent.ConnectionHandler; import org.apache.ace.agent.DiscoveryHandler; import org.apache.ace.agent.IdentificationHandler; +import org.apache.ace.agent.impl.DependencyTrackerImpl.DependencyCallback; +import org.apache.ace.agent.impl.DependencyTrackerImpl.LifecycleCallbacks; import org.apache.felix.deploymentadmin.DeploymentAdminImpl; -import org.apache.felix.dm.Component; -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.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.event.EventHandler; import org.osgi.service.log.LogService; import org.osgi.service.packageadmin.PackageAdmin; -// TODO Decouple from DM to save 170k in agent size. Or: just include what we use -public class Activator extends DependencyActivatorBase { +/** + * + */ +public class Activator implements BundleActivator { // internal delegates - private final InternalEvents m_internalEvents = new InternalEvents(); - private final InternalLogger m_internalLogger = new InternalLogger(LogService.LOG_DEBUG); + private final EventsHandlerImpl m_internalEvents = new EventsHandlerImpl(); + private final LoggingHandlerImpl m_internalLogger = new LoggingHandlerImpl(LogService.LOG_DEBUG); // managed state private AgentContextImpl m_agentContext; - private AgentControl m_agentControl; + private AgentControlImpl m_agentControl; private ScheduledExecutorService m_executorService; - private DeploymentAdmin m_deploymentAdmin; - private Component m_agentControlComponent = null; private EventLoggerImpl m_eventLoggerImpl; private DefaultController m_defaultController; + private volatile DeploymentAdmin m_deploymentAdmin; + private ServiceRegistration m_agentControlRegistration; // injected services private volatile PackageAdmin m_packageAdmin; + private volatile IdentificationHandler m_identificationHandler; + private volatile DiscoveryHandler m_discoveryHandler; + private volatile ConnectionHandler m_connectionHandler; + + private volatile BundleContext m_bundleContext; + private DependencyTrackerImpl m_dependencyTracker; @Override - public void init(BundleContext context, DependencyManager manager) throws Exception { + public void start(final BundleContext bundleContext) throws Exception { + m_bundleContext = bundleContext; m_executorService = Executors.newScheduledThreadPool(1, new InternalThreadFactory()); - m_deploymentAdmin = new DeploymentAdminImpl(); - configureField(m_deploymentAdmin, BundleContext.class, context); - configureField(m_deploymentAdmin, PackageAdmin.class, null); - configureField(m_deploymentAdmin, EventAdmin.class, new InternalEventAdmin(m_internalEvents)); - configureField(m_deploymentAdmin, LogService.class, new InternalLogService(m_internalLogger, "deployment")); + m_dependencyTracker = new DependencyTrackerImpl(bundleContext, new LifecycleCallbacks() { - m_agentContext = new AgentContextImpl(context.getDataFile("")); - m_agentControl = new AgentControlImpl(m_agentContext); + @Override + public void started() { + try { + startAgent(); + } + catch (Exception e) { + e.printStackTrace(); + } + } - 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(context)); - m_agentContext.setFeedbackHandler(new FeedbackHandlerImpl()); + @Override + public void stopped() { + try { + stopAgent(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }); + + m_dependencyTracker.addDependency(PackageAdmin.class, null, new DependencyCallback() { - Component agentContextComponent = createComponent() - .setImplementation(m_agentContext) - .setCallbacks(this, null, "startAgent", "stopAgent", null) - .setAutoConfig(BundleContext.class, false) - .setAutoConfig(DependencyManager.class, false) - .setAutoConfig(Component.class, false) - .add(createServiceDependency() - .setService(PackageAdmin.class).setRequired(true) - .setCallbacks(this, "packageAdminAdded", "packageAdminRemoved")); + @Override + public void updated(Object service) { + m_packageAdmin = (PackageAdmin) service; + } + }); // FIXME fake config if (Boolean.parseBoolean(System.getProperty("agent.identificationhandler.disabled"))) { - m_internalLogger.logInfo("activator", "Initializing agent...", null); - agentContextComponent.add(createServiceDependency().setService(IdentificationHandler.class).setRequired(true)); + m_dependencyTracker.addDependency(IdentificationHandler.class, null, new DependencyCallback() { + @Override + public void updated(Object service) { + m_identificationHandler = (IdentificationHandler) service; + } + }); } // FIXME fake config if (Boolean.parseBoolean(System.getProperty("agent.discoveryhandler.disabled"))) { - m_internalLogger.logInfo("activator", "Initializing agent...", null); - agentContextComponent.add(createServiceDependency().setService(DiscoveryHandler.class).setRequired(true)); + m_dependencyTracker.addDependency(DiscoveryHandler.class, null, new DependencyCallback() { + @Override + public void updated(Object service) { + m_discoveryHandler = (DiscoveryHandler) service; + } + }); } // FIXME fake config if (Boolean.parseBoolean(System.getProperty("agent.connectionhandler.disabled"))) { - agentContextComponent.add(createServiceDependency().setService(ConnectionHandler.class).setRequired(true)); + m_dependencyTracker.addDependency(ConnectionHandler.class, null, new DependencyCallback() { + @Override + public void updated(Object service) { + m_connectionHandler = (ConnectionHandler) service; + } + }); } - manager.add(agentContextComponent); + + m_dependencyTracker.startTracking(); } @Override - public void destroy(BundleContext context, DependencyManager manager) throws Exception { + public void stop(BundleContext context) throws Exception { + m_dependencyTracker.stopTracking(); m_executorService.shutdownNow(); m_executorService = null; } - synchronized void packageAdminAdded(PackageAdmin packageAdmin) { - if (m_packageAdmin == null) { - m_packageAdmin = packageAdmin; - configureField(m_deploymentAdmin, PackageAdmin.class, packageAdmin); - } - } - - synchronized void packageAdminRemoved(PackageAdmin packageAdmin) { - if (m_packageAdmin == packageAdmin) { - m_packageAdmin = null; - configureField(m_deploymentAdmin, PackageAdmin.class, 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[] {}); + + 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_internalLogger.logInfo("activator", "Agent control service started", null); - m_agentControlComponent = createComponent() - .setInterface(AgentControl.class.getName(), null) - .setImplementation(m_agentControl); - getDependencyManager().add(m_agentControlComponent); + m_agentControl = new AgentControlImpl(m_agentContext); + m_agentControlRegistration = m_bundleContext.registerService(AgentControl.class.getName(), m_agentControl, null); + m_internalLogger.logInfo("activator", "AgentControl registered", null); - // FIXME fake config - if (!Boolean.parseBoolean(System.getProperty("agent.defaultcontroller.disabled"))) { - m_defaultController = new DefaultController(); - m_defaultController.start(m_agentContext); - m_internalLogger.logInfo("activator", "Default controller started", null); - } - else { - m_internalLogger.logInfo("activator", "Default controller disabled", 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, getDependencyManager().getBundleContext()); - BundleContext bundleContext = getDependencyManager().getBundleContext(); - bundleContext.addBundleListener(m_eventLoggerImpl); - bundleContext.addFrameworkListener(m_eventLoggerImpl); + 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); } else { m_internalLogger.logInfo("activator", "Audit logger disabled", null); } - - m_internalLogger.logInfo("activator", "Agent started", null); + m_internalLogger.logInfo("activator", "Agent statup complete", null); } void stopAgent() throws Exception { m_internalLogger.logInfo("activator", "Agent stopping..", null); - if (m_agentControlComponent != null) { - getDependencyManager().remove(m_agentControlComponent); - m_agentControlComponent = null; - } + m_agentControlRegistration.unregister(); + m_agentControlRegistration = null; - if (m_defaultController != null) { - m_defaultController.stop(); - m_defaultController = null; - } + m_defaultController.stop(); + m_defaultController = null; + + invokeMethod(m_deploymentAdmin, "stop", new Class[] {}, new Object[] {}); if (m_eventLoggerImpl != null) { - BundleContext bundleContext = getDependencyManager().getBundleContext(); - bundleContext.removeFrameworkListener(m_eventLoggerImpl); - bundleContext.removeBundleListener(m_eventLoggerImpl); + m_bundleContext.removeFrameworkListener(m_eventLoggerImpl); + m_bundleContext.removeBundleListener(m_eventLoggerImpl); m_internalEvents.unregisterHandler(m_eventLoggerImpl); } m_agentContext.stop(); - invokeMethod(m_deploymentAdmin, "stop", new Class[] {}, new Object[] {}); + m_agentContext = null; + m_internalLogger.logInfo("activator", "Agent stopped", null); } - /** - * InternalEvents that posts events to internal handlers and external admins. - */ - static class InternalEvents implements EventsHandler { - - private final Map m_eventHandlers = new HashMap(); - - public void postEvent(String topic, Dictionary payload) { - Event event = new Event(topic, payload); - postEvent(event); - } - - public void postEvent(Event event) { - sendInternal(event); - sendExternal(event); - } - - void registerHandler(EventHandler eventHandler, String[] topics) { - synchronized (m_eventHandlers) { - m_eventHandlers.put(eventHandler, topics); - } - } - - void unregisterHandler(EventHandler eventHandler) { - synchronized (m_eventHandlers) { - m_eventHandlers.remove(eventHandler); - } - } - - private void sendInternal(Event event) { - String topic = event.getTopic(); - synchronized (m_eventHandlers) { - for (Entry entry : m_eventHandlers.entrySet()) { - for (String interest : entry.getValue()) { - if ((interest.endsWith("*") && topic.startsWith(interest.substring(0, interest.length() - 1)) - || topic.equals(interest))) { - entry.getKey().handleEvent(event); - break; - } - } - } - } - } - - private void sendExternal(Event event) { - // TODO this requires looking for all service references and invoking any found admins using reflection - } - + 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[] {}); } /** @@ -259,64 +232,28 @@ public class Activator extends Dependenc */ static class InternalEventAdmin implements EventAdmin { - private final InternalEvents m_events; + private final EventsHandler m_events; - public InternalEventAdmin(InternalEvents events) { + public InternalEventAdmin(EventsHandler events) { m_events = events; } @Override public void postEvent(Event event) { - m_events.postEvent(event); + m_events.postEvent(event.getTopic(), getPayload(event)); } @Override public void sendEvent(Event event) { - m_events.postEvent(event); + m_events.postEvent(event.getTopic(), getPayload(event)); } - } - - /** - * Internal logger that writes to system out for now. It minimizes work until it is determined the loglevel is - * loggable. - */ - static class InternalLogger implements LoggingHandler { - - private final int m_level; - public InternalLogger(int level) { - m_level = level; - } - - private void log(String level, String component, String message, Throwable exception, Object... args) { - if (args.length > 0) - message = String.format(message, args); - String line = String.format("[%s] %TT (%s) %s", level, new Date(), component, message); - System.out.println(line); - if (exception != null) - exception.printStackTrace(System.out); - } - - public void logDebug(String component, String message, Throwable exception, Object... args) { - if (m_level < LogService.LOG_DEBUG) - return; - log("DEBUG", component, message, exception, args); - } - - public void logInfo(String component, String message, Throwable exception, Object... args) { - if (m_level < LogService.LOG_INFO) - return; - log("INFO", component, message, exception, args); - } - - public void logWarning(String component, String message, Throwable exception, Object... args) { - if (m_level < LogService.LOG_WARNING) - return; - log("WARNING", component, message, exception, args); - } - - public void logError(String component, String message, Throwable exception, Object... args) { - log("ERROR", component, message, exception, args); + private static Dictionary getPayload(Event event) { + Dictionary payload = new Hashtable(); + for (String propertyName : event.getPropertyNames()) { + payload.put(propertyName, event.getProperty(propertyName).toString()); + } + return payload; } } @@ -325,10 +262,10 @@ public class Activator extends Dependenc */ static class InternalLogService implements LogService { - private final InternalLogger m_logger; + private final LoggingHandler m_logger; private final String m_identifier; - public InternalLogService(InternalLogger logger, String identifier) { + public InternalLogService(LoggingHandler logger, String identifier) { m_logger = logger; m_identifier = identifier; } @@ -381,4 +318,5 @@ public class Activator extends Dependenc return thread; } } + } Added: 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=1517469&view=auto ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java (added) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DependencyTrackerImpl.java Mon Aug 26 08:58:30 2013 @@ -0,0 +1,291 @@ +/* + * 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.Set; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +/** + * Simple service dependency tracker that tracks a number of required dependencies and provides life-cycle. + */ +public class DependencyTrackerImpl { + + interface LifecycleCallbacks { + void started(); + + void stopped(); + } + + interface DependencyCallback { + void updated(Object service); + } + + private final Set m_dependencies = new HashSet(); + private final BundleContext m_bundleContext; + private final LifecycleCallbacks m_callbacks; + private volatile boolean m_tracking = false; + private volatile boolean m_started = false; + + public DependencyTrackerImpl(BundleContext bundleContext, LifecycleCallbacks callbacks) { + m_bundleContext = bundleContext; + m_callbacks = callbacks; + } + + public BundleContext getBundleContext() { + return m_bundleContext; + } + + public void addDependency(Class iface, String extraFilter, DependencyCallback inject) throws Exception { + synchronized (this) { + if (m_tracking) { + throw new IllegalStateException("Can not add dependecies while tracking"); + } + } + Filter filter = null; + if (extraFilter != null) { + filter = FrameworkUtil.createFilter("(&(" + Constants.OBJECTCLASS + "=" + iface.getName() + ")" + extraFilter + ")"); + } + else { + filter = FrameworkUtil.createFilter("(" + Constants.OBJECTCLASS + "=" + iface.getName() + ")"); + } + ServiceDependency dependency = new ServiceDependency(this, filter, inject); + m_dependencies.add(dependency); + } + + public void startTracking() throws Exception { + synchronized (this) { + if (m_tracking) { + throw new IllegalStateException("Allready started tracking"); + } + m_tracking = true; + } + for (ServiceDependency dependency : m_dependencies) { + dependency.startTracking(); + } + } + + public void stopTracking() { + synchronized (this) { + if (!m_tracking) { + throw new IllegalStateException("Did not start tracking yet"); + } + m_tracking = false; + } + for (ServiceDependency dependency : m_dependencies) { + dependency.stopTracking(); + } + } + + private void update() { + // 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(); + } + serviceCallbacks(); + startCallback(); + } + else { + stopCallback(); + serviceCallbacks(); + } + } + } + + private boolean dependenciesAvailable() { + boolean available = true; + for (ServiceDependency dependency : m_dependencies) { + if (dependency.getService() == null) { + available = false; + break; + } + } + return available; + } + + private void startCallback() { + try { + m_callbacks.started(); + m_started = true; + } + catch (Exception e) { + // really must not happen + e.printStackTrace(); + } + } + + private void stopCallback() { + try { + m_callbacks.stopped(); + m_started = false; + } + catch (Exception e) { + // really must not happen + e.printStackTrace(); + } + } + + private void serviceCallbacks() { + for (ServiceDependency dependency : m_dependencies) { + try { + dependency.invokeCallback(); + } + catch (Exception e) { + // really must not happen + e.printStackTrace(); + } + } + } + + private static class ServiceDependency { + + private final DependencyTrackerImpl m_manager; + private final Filter m_filter; + private final DependencyCallback m_calback; + private final ServiceTracker m_tracker; + private volatile Object m_service; + + public ServiceDependency(DependencyTrackerImpl manager, Filter filter, DependencyCallback callback) throws Exception { + m_manager = manager; + m_filter = filter; + m_calback = callback; + m_tracker = new ServiceDependencyTracker(this); + } + + public BundleContext getBundleContext() { + return m_manager.getBundleContext(); + } + + public Filter getFilter() { + return m_filter; + } + + public Object getService() { + return m_service; + } + + public void startTracking() { + if (m_tracker == null) { + } + m_tracker.open(); + } + + public void stopTracking() { + m_tracker.close(); + } + + void invokeCallback() { + if (m_calback != null) { + m_calback.updated(m_service); + } + } + + void changed(Object service) { + // Sync on manager to ensure all dependency updates happen in order + synchronized (m_manager) { + m_service = service; + m_manager.update(); + } + } + } + + /** + * Custom service tracker to simply construction. + * + */ + private static class ServiceDependencyTracker extends ServiceTracker { + + public ServiceDependencyTracker(ServiceDependency dependency) { + super(dependency.getBundleContext(), dependency.getFilter(), new ServiceDependencyTrackerCustomizer(dependency)); + + } + } + + /** + * Tracker customizer that calls AgentContextDependency#changed with the highest matching service whenever something + * changes. + */ + private static class ServiceDependencyTrackerCustomizer implements ServiceTrackerCustomizer { + + private final Map m_trackedServices = new HashMap(); + private final ServiceDependency m_dependency; + private volatile Object m_service; + + public ServiceDependencyTrackerCustomizer(ServiceDependency dependency) { + m_dependency = dependency; + } + + @Override + public Object addingService(ServiceReference reference) { + Object service = m_dependency.getBundleContext().getService(reference); + synchronized (m_trackedServices) { + m_trackedServices.put(reference, service); + checkForUpdate(); + return service; + } + } + + @Override + public void modifiedService(ServiceReference reference, Object service) { + synchronized (m_trackedServices) { + m_trackedServices.put(reference, service); + checkForUpdate(); + } + } + + @Override + public void removedService(ServiceReference reference, Object service) { + synchronized (m_trackedServices) { + m_trackedServices.remove(reference); + checkForUpdate(); + } + } + + private void checkForUpdate() { + ServiceReference highestReference = null; + if (!m_trackedServices.isEmpty()) { + for (ServiceReference reference : m_trackedServices.keySet()) { + if (highestReference == null || highestReference.compareTo(reference) < 1) { + highestReference = reference; + } + } + } + Object service = highestReference == null ? null : m_trackedServices.get(highestReference); + if (m_service == null || m_service != service) { + m_service = service; + m_dependency.changed(service); + } + } + } +} Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java?rev=1517469&r1=1517468&r2=1517469&view=diff ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java (original) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventLoggerImpl.java Mon Aug 26 08:58:30 2013 @@ -118,8 +118,7 @@ public class EventLoggerImpl implements } eventType = AuditEvent.DEPLOYMENTADMIN_COMPLETE; props.put(AuditEvent.KEY_NAME, deplPackName); - Boolean success = (Boolean) event.getProperty("successful"); - props.put(AuditEvent.KEY_SUCCESS, success.toString()); + props.put(AuditEvent.KEY_SUCCESS, (String) event.getProperty("successful")); } writeEvent(eventType, props); } Added: 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/impl/EventsHandler.java?rev=1517469&view=auto ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java (added) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandler.java Mon Aug 26 08:58:30 2013 @@ -0,0 +1,32 @@ +/* + * 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.Dictionary; + +import org.apache.ace.agent.AgentContext; + +/** + * 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. + */ +public interface EventsHandler { + + void postEvent(String topic, Dictionary payload); +} Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java?rev=1517469&view=auto ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java (added) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/EventsHandlerImpl.java Mon Aug 26 08:58:30 2013 @@ -0,0 +1,77 @@ +/* + * 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.Dictionary; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; + +/** + * InternalEvents that posts events to internal handlers and external admins. + */ +public class EventsHandlerImpl implements EventsHandler { + + private final Map m_eventHandlers = new HashMap(); + + public void postEvent(String topic, Dictionary payload) { + Event event = new Event(topic, payload); + postEvent(event); + } + + public void postEvent(Event event) { + sendInternal(event); + sendExternal(event); + } + + void registerHandler(EventHandler eventHandler, String[] topics) { + synchronized (m_eventHandlers) { + m_eventHandlers.put(eventHandler, topics); + } + } + + void unregisterHandler(EventHandler eventHandler) { + synchronized (m_eventHandlers) { + m_eventHandlers.remove(eventHandler); + } + } + + private void sendInternal(Event event) { + String topic = event.getTopic(); + synchronized (m_eventHandlers) { + for (Entry entry : m_eventHandlers.entrySet()) { + for (String interest : entry.getValue()) { + if ((interest.endsWith("*") && topic.startsWith(interest.substring(0, interest.length() - 1)) + || topic.equals(interest))) { + entry.getKey().handleEvent(event); + break; + } + } + } + } + } + + private void sendExternal(Event event) { + // TODO this requires looking for all service references and invoking any found admins using reflection + } + +} Added: 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/impl/LoggingHandler.java?rev=1517469&view=auto ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java (added) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandler.java Mon Aug 26 08:58:30 2013 @@ -0,0 +1,74 @@ +/* + * 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.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. + */ +public interface LoggingHandler { + + /** + * Log an debug message. If args are provided the message will be processed as a format using the + * standard {@link Formatter}. + * + * @param component The component identifier, not null + * @param message The log message or format, not null + * @param cause The cause, may be null + * @param args The optional formatter arguments + */ + void logDebug(String component, String message, Throwable exception, Object... args); + + /** + * Log an info message. If args are provided the message will be processed as a format using the + * standard {@link Formatter}. + * + * @param component The component identifier, not null + * @param message The log message or format, not null + * @param cause The cause, may be null + * @param args The optional formatter arguments + */ + void logInfo(String component, String message, Throwable exception, Object... args); + + /** + * Log an warning message. If args are provided the message will be processed as a format using the + * standard {@link Formatter}. + * + * @param component The component identifier, not null + * @param message The log message or format, not null + * @param cause The cause, may be null + * @param args The optional formatter arguments + */ + void logWarning(String component, String message, Throwable exception, Object... args); + + /** + * Log an error message. If args are provided the message will be processed as a format using the + * standard {@link Formatter}. + * + * @param component The component identifier, not null + * @param message The log message or format, not null + * @param cause The cause, may be null + * @param args The optional formatter arguments + */ + void logError(String component, String message, Throwable exception, Object... args); +} Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java?rev=1517469&view=auto ============================================================================== --- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java (added) +++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/LoggingHandlerImpl.java Mon Aug 26 08:58:30 2013 @@ -0,0 +1,71 @@ +/* + * 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.Date; + +import org.osgi.service.log.LogService; + +/** + * Internal logger that writes to system out for now. It minimizes work until it is determined the loglevel is loggable. + */ +public class LoggingHandlerImpl implements LoggingHandler { + + private final int m_level; + + public LoggingHandlerImpl(int level) { + m_level = level; + } + + private void log(String level, String component, String message, Throwable exception, Object... args) { + if (args.length > 0) + message = String.format(message, args); + String line = String.format("[%s] %TT (%s) %s", level, new Date(), component, message); + System.out.println(line); + if (exception != null) + exception.printStackTrace(System.out); + } + + @Override + public void logDebug(String component, String message, Throwable exception, Object... args) { + if (m_level < LogService.LOG_DEBUG) + return; + log("DEBUG", component, message, exception, args); + } + + @Override + public void logInfo(String component, String message, Throwable exception, Object... args) { + if (m_level < LogService.LOG_INFO) + return; + log("INFO", component, message, exception, args); + } + + @Override + public void logWarning(String component, String message, Throwable exception, Object... args) { + if (m_level < LogService.LOG_WARNING) + return; + log("WARNING", component, message, exception, args); + } + + @Override + public void logError(String component, String message, Throwable exception, Object... args) { + log("ERROR", component, message, exception, args); + } + +}