Author: gnodet
Date: Mon Dec  6 12:58:27 2010
New Revision: 1042612

URL: http://svn.apache.org/viewvc?rev=1042612&view=rev
Log:
[CAMEL-3381][CAMEL-3382] Publish the CamelContext as an OSGi service and 
propagate camel events as EventAdmin events

Added:
    
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
    
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
Modified:
    camel/trunk/components/camel-blueprint/pom.xml
    
camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
    camel/trunk/components/camel-spring/pom.xml
    
camel/trunk/components/camel-spring/src/main/java/org/apache/camel/osgi/CamelContextFactoryBean.java

Modified: camel/trunk/components/camel-blueprint/pom.xml
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-blueprint/pom.xml?rev=1042612&r1=1042611&r2=1042612&view=diff
==============================================================================
--- camel/trunk/components/camel-blueprint/pom.xml (original)
+++ camel/trunk/components/camel-blueprint/pom.xml Mon Dec  6 12:58:27 2010
@@ -35,6 +35,7 @@
         <camel.osgi.import>
             !org.apache.camel.blueprint.*,
             org.apache.camel.*;${camel.osgi.import.strict.version},
+            org.osgi.service.event*;resolution:=optional,
             *
         </camel.osgi.import>
         <camel.osgi.export>

Modified: 
camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java?rev=1042612&r1=1042611&r2=1042612&view=diff
==============================================================================
--- 
camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
 (original)
+++ 
camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java
 Mon Dec  6 12:58:27 2010
@@ -31,6 +31,8 @@ import org.apache.camel.RoutesBuilder;
 import org.apache.camel.ShutdownRoute;
 import org.apache.camel.ShutdownRunningTask;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.core.osgi.OsgiCamelContextPublisher;
+import org.apache.camel.core.osgi.OsgiEventAdminNotifier;
 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean;
 import org.apache.camel.core.xml.CamelJMXAgentDefinition;
 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition;
@@ -50,6 +52,8 @@ import org.apache.camel.model.ThreadPool
 import org.apache.camel.model.config.PropertiesDefinition;
 import org.apache.camel.model.dataformat.DataFormatsDefinition;
 import org.apache.camel.spi.PackageScanFilter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 
@@ -64,6 +68,7 @@ import org.osgi.service.blueprint.contai
 @XmlRootElement(name = "camelContext")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class CamelContextFactoryBean extends 
AbstractCamelContextFactoryBean<BlueprintCamelContext> {
+    private static final Log LOG = 
LogFactory.getLog(CamelContextFactoryBean.class);
 
     @XmlAttribute(name = "depends-on", required = false)
     private String dependsOn;
@@ -198,6 +203,19 @@ public class CamelContextFactoryBean ext
     protected void findRouteBuildersByContextScan(PackageScanFilter filter, 
List<RoutesBuilder> builders) throws Exception {
     }
 
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        super.afterPropertiesSet();
+        getContext().getManagementStrategy().addEventNotifier(new 
OsgiCamelContextPublisher(bundleContext));
+        try {
+            
getClass().getClassLoader().loadClass("org.osgi.service.event.EventAdmin");
+            getContext().getManagementStrategy().addEventNotifier(new 
OsgiEventAdminNotifier(bundleContext));
+        } catch (Throwable t) {
+            // Ignore, if the EventAdmin package is not available, just don't 
use it
+            LOG.debug("EventAdmin package is not available, just don't use 
it");
+        }
+    }
+
     public String getDependsOn() {
         return dependsOn;
     }

Added: 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java?rev=1042612&view=auto
==============================================================================
--- 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
 (added)
+++ 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
 Mon Dec  6 12:58:27 2010
@@ -0,0 +1,90 @@
+/**
+ * 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.camel.core.osgi;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.management.EventNotifierSupport;
+import org.apache.camel.management.event.CamelContextStartedEvent;
+import org.apache.camel.management.event.CamelContextStoppingEvent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
+
+import java.util.Dictionary;
+import java.util.EventObject;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This EventNotifier is in charge of registerting CamelContext in the OSGi 
registry
+ */
+public class OsgiCamelContextPublisher extends EventNotifierSupport {
+
+    public static final String CONTEXT_SYMBOLIC_NAME_PROPERTY = 
"camel.context.symbolicname";
+
+    public static final String CONTEXT_VERSION_PROPERTY = 
"camel.context.version";
+
+    private final BundleContext bundleContext;
+    private final Map<CamelContext, ServiceRegistration> registrations = new 
ConcurrentHashMap<CamelContext, ServiceRegistration>();
+
+    public OsgiCamelContextPublisher(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public void notify(EventObject event) throws Exception {
+        if (event instanceof CamelContextStartedEvent) {
+            CamelContext context = ((CamelContextStartedEvent) 
event).getContext();
+            Properties props = new Properties();
+            props.put(CONTEXT_SYMBOLIC_NAME_PROPERTY,
+                      bundleContext.getBundle().getSymbolicName());
+            props.put(CONTEXT_VERSION_PROPERTY,
+                      getBundleVersion(bundleContext.getBundle()));
+            ServiceRegistration reg = bundleContext.registerService(
+                                          CamelContext.class.getName(),
+                                          context,
+                                          props);
+            registrations.put( context, reg );
+        } else if (event instanceof CamelContextStoppingEvent) {
+            CamelContext context = ((CamelContextStoppingEvent) 
event).getContext();
+            ServiceRegistration reg = registrations.get( context );
+            if (reg != null) {
+                reg.unregister();
+            }
+        }
+    }
+
+    public boolean isEnabled(EventObject event) {
+        return true;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+    }
+
+    public static Version getBundleVersion(Bundle bundle) {
+        Dictionary headers = bundle.getHeaders();
+        String version = (String)headers.get(Constants.BUNDLE_VERSION);
+        return (version != null) ? Version.parseVersion(version) : 
Version.emptyVersion;
+    }
+}

Added: 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java?rev=1042612&view=auto
==============================================================================
--- 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
 (added)
+++ 
camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
 Mon Dec  6 12:58:27 2010
@@ -0,0 +1,152 @@
+/**
+ * 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.camel.core.osgi;
+
+import org.apache.camel.management.EventNotifierSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.Dictionary;
+import java.util.EventObject;
+import java.util.Hashtable;
+
+/**
+ * This EventNotifier is in charge of propagating events to EventAdmin if 
present.
+ */
+public class OsgiEventAdminNotifier extends EventNotifierSupport {
+
+    public static final String TYPE = "type";
+
+    public static final String EVENT = "event";
+
+    public static final String TIMESTAMP = "timestamp";
+
+    public static final String BUNDLE = "bundle";
+
+    public static final String BUNDLE_ID = "bundle.id";
+
+    public static final String BUNDLE_SYMBOLICNAME = "bundle.symbolicName";
+
+    public static final String BUNDLE_VERSION = "bundle.version";
+
+    public static final String CAUSE = "cause";
+
+    public static final String TOPIC_CAMEL_EVENTS = "org/apache/camel/";
+    public static final String TOPIC_CAMEL_CONTEXT_EVENTS = TOPIC_CAMEL_EVENTS 
+ "context/";
+    public static final String TOPIC_CAMEL_EXCHANGE_EVENTS = 
TOPIC_CAMEL_EVENTS + "exchange/";
+    public static final String TOPIC_CAMEL_SERVICE_EVENTS = TOPIC_CAMEL_EVENTS 
+ "service/";
+    public static final String TOPIC_CAMEL_ROUTE_EVENTS = TOPIC_CAMEL_EVENTS + 
"route/";
+
+    private final BundleContext bundleContext;
+    private final ServiceTracker tracker;
+
+    public OsgiEventAdminNotifier(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        this.tracker = new ServiceTracker(bundleContext, 
EventAdmin.class.getName(), null);
+        setIgnoreExchangeEvents(true);
+    }
+
+    public void notify(EventObject event) throws Exception {
+        EventAdmin eventAdmin = (EventAdmin) tracker.getService();
+        if (eventAdmin == null) {
+            return;
+        }
+
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(TYPE, getType(event));
+        props.put(EVENT, event);
+        props.put(TIMESTAMP, System.currentTimeMillis());
+        props.put(BUNDLE, bundleContext.getBundle());
+        props.put(BUNDLE_SYMBOLICNAME, 
bundleContext.getBundle().getSymbolicName());
+        props.put(BUNDLE_ID, bundleContext.getBundle().getBundleId());
+        props.put(BUNDLE_VERSION, getBundleVersion(bundleContext.getBundle()));
+        try {
+            props.put(CAUSE, 
event.getClass().getMethod("getCause").invoke(event));
+        } catch (Throwable t) {
+            // ignore
+        }
+        eventAdmin.postEvent(new Event(getTopic(event), props));
+    }
+
+    public boolean isEnabled(EventObject event) {
+        return true;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        tracker.open();
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        tracker.close();
+    }
+
+    public static String toUpper(String text) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            if (Character.isUpperCase(c) && sb.length() > 0) {
+                sb.append('_');
+            }
+            sb.append(Character.toUpperCase(c));
+        }
+        return sb.toString();
+    }
+
+    public static String getType(EventObject event) {
+        String type = event.getClass().getSimpleName();
+        if (type.endsWith("Event")) {
+            type = type.substring(0, type.length() - "Event".length());
+        }
+        return type;
+    }
+
+    public static String getTopic(EventObject event) {
+        String topic;
+        String type = getType(event);
+        if (type.startsWith("CamelContext")) {
+            topic = TOPIC_CAMEL_CONTEXT_EVENTS;
+            type = type.substring("CamelContext".length());
+        } else if (type.startsWith("Exchange")) {
+            topic = TOPIC_CAMEL_EXCHANGE_EVENTS;
+            type = type.substring("Exchange".length());
+        } else if (type.startsWith("Route")) {
+            topic = TOPIC_CAMEL_ROUTE_EVENTS;
+            type = type.substring("Route".length());
+        } else if (type.startsWith("Service")) {
+            topic = TOPIC_CAMEL_SERVICE_EVENTS;
+            type = type.substring("Service".length());
+        } else {
+            topic = TOPIC_CAMEL_EVENTS + "unknown/";
+        }
+        topic += toUpper(type);
+        return topic;
+    }
+
+    public static Version getBundleVersion(Bundle bundle) {
+        Dictionary headers = bundle.getHeaders();
+        String version = (String)headers.get(Constants.BUNDLE_VERSION);
+        return (version != null) ? Version.parseVersion(version) : 
Version.emptyVersion;
+    }
+
+}

Modified: camel/trunk/components/camel-spring/pom.xml
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/pom.xml?rev=1042612&r1=1042611&r2=1042612&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/pom.xml (original)
+++ camel/trunk/components/camel-spring/pom.xml Mon Dec  6 12:58:27 2010
@@ -42,6 +42,7 @@
         !org.apache.camel.component.xslt,
         org.apache.camel.*;${camel.osgi.import.strict.version},
         org.osgi.framework;version="[1.3,2)",
+        org.osgi.service.event;resolution:=optional,
         org.springframework.osgi.*;version="[1.2,2)",
         org.springframework.*;version="[2.5,4)",
         *

Modified: 
camel/trunk/components/camel-spring/src/main/java/org/apache/camel/osgi/CamelContextFactoryBean.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/osgi/CamelContextFactoryBean.java?rev=1042612&r1=1042611&r2=1042612&view=diff
==============================================================================
--- 
camel/trunk/components/camel-spring/src/main/java/org/apache/camel/osgi/CamelContextFactoryBean.java
 (original)
+++ 
camel/trunk/components/camel-spring/src/main/java/org/apache/camel/osgi/CamelContextFactoryBean.java
 Mon Dec  6 12:58:27 2010
@@ -21,6 +21,8 @@ import javax.xml.bind.annotation.XmlAcce
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 
+import org.apache.camel.core.osgi.OsgiCamelContextPublisher;
+import org.apache.camel.core.osgi.OsgiEventAdminNotifier;
 import org.apache.camel.spring.SpringCamelContext;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -58,5 +60,17 @@ public class CamelContextFactoryBean ext
     protected SpringCamelContext newCamelContext() {
         return new OsgiSpringCamelContext(getApplicationContext(), 
getBundleContext());
     }
-     
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        super.afterPropertiesSet();
+        getContext().getManagementStrategy().addEventNotifier(new 
OsgiCamelContextPublisher(bundleContext));
+        try {
+            
getClass().getClassLoader().loadClass("org.osgi.service.event.EventAdmin");
+            getContext().getManagementStrategy().addEventNotifier(new 
OsgiEventAdminNotifier(bundleContext));
+        } catch (Throwable t) {
+            // Ignore, if the EventAdmin package is not available, just don't 
use it
+            LOG.debug("EventAdmin package is not available, just don't use 
it");
+        }
+    }
 }


Reply via email to