Repository: camel
Updated Branches:
  refs/heads/master a770bbb24 -> cdee7809b


[CAMEL-8000] Add global notion of CamelContextRegistry


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ab750c95
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ab750c95
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ab750c95

Branch: refs/heads/master
Commit: ab750c951cb4ec6d0aab5e56e862396f2b076049
Parents: a770bbb
Author: Thomas Diesler <thomas.dies...@jboss.com>
Authored: Fri Nov 7 10:48:15 2014 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Nov 7 17:16:37 2014 +0100

----------------------------------------------------------------------
 .../apache/camel/impl/DefaultCamelContext.java  |  16 ++-
 .../camel/impl/DefaultCamelContextRegistry.java | 123 +++++++++++++++++++
 .../apache/camel/spi/CamelContextRegistry.java  |  80 ++++++++++++
 .../java/org/apache/camel/spi/Container.java    |   3 +
 .../camel/spi/CamelContextRegistryTest.java     |  68 ++++++++++
 5 files changed, 289 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ab750c95/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java 
b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 1ca5e19..b3f6ff3 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -93,6 +93,7 @@ import org.apache.camel.processor.interceptor.HandleFault;
 import org.apache.camel.processor.interceptor.StreamCaching;
 import org.apache.camel.processor.interceptor.Tracer;
 import org.apache.camel.spi.CamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextRegistry;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.Container;
@@ -267,9 +268,14 @@ public class DefaultCamelContext extends ServiceSupport 
implements ModelCamelCon
         this.managementStrategy = createManagementStrategy();
         this.managementMBeanAssembler = createManagementMBeanAssembler();
 
+        // Register this context with the registry
+        // Note, this may register a partially constructed object
+       ((DefaultCamelContextRegistry) 
CamelContextRegistry.INSTANCE).afterCreate(this);
+       
+        // [TODO] Remove in 3.0
         Container.Instance.manage(this);
     }
-
+    
     /**
      * Creates the {@link CamelContext} using the given JNDI context as the 
registry
      *
@@ -1934,6 +1940,10 @@ public class DefaultCamelContext extends ServiceSupport 
implements ModelCamelCon
             setApplicationContextClassLoader(cl);
         }
 
+        // We register the context again just before start. This ensures that 
is is registered on restart
+        // Listeners should only see one call to 
Listener.contextAdded(CamelContext)
+               ((DefaultCamelContextRegistry) 
CamelContextRegistry.INSTANCE).beforeStart(this);
+               
         if (log.isDebugEnabled()) {
             log.debug("Using ClassResolver={}, PackageScanClassResolver={}, 
ApplicationContextClassLoader={}",
                     new Object[]{getClassResolver(), 
getPackageScanClassResolver(), getApplicationContextClassLoader()});
@@ -2184,7 +2194,11 @@ public class DefaultCamelContext extends ServiceSupport 
implements ModelCamelCon
         // and clear start date
         startDate = null;
 
+        // [TODO] Remove in 3.0
         Container.Instance.unmanage(this);
+
+        // Unregister this context from the registry
+        ((DefaultCamelContextRegistry) 
CamelContextRegistry.INSTANCE).afterStop(this);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/ab750c95/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContextRegistry.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContextRegistry.java
 
b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContextRegistry.java
new file mode 100644
index 0000000..9413050
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContextRegistry.java
@@ -0,0 +1,123 @@
+/**
+ * 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.impl;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.CamelContextRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The default {@link CamelContextRegistry}
+ */
+public final class DefaultCamelContextRegistry implements CamelContextRegistry 
{
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(DefaultCamelContextRegistry.class);
+    
+       private final Set<CamelContext> contexts = new 
LinkedHashSet<CamelContext>();
+    private final Set<Listener> listeners = new LinkedHashSet<Listener>();
+       
+    synchronized void afterCreate(CamelContext camelContext) {
+               registerContext(camelContext);
+    } 
+    
+    synchronized void beforeStart(CamelContext camelContext) {
+       if (!contexts.contains(camelContext)) {
+               registerContext(camelContext);
+       }
+    }
+
+    synchronized void afterStop(CamelContext camelContext) {
+               unregisterContext(camelContext);
+    }
+
+       private void registerContext(CamelContext camelContext) {
+               contexts.add(camelContext);
+               for (Listener listener : listeners) {
+                       try {
+                               listener.contextAdded(camelContext);
+                       } catch (Throwable th) {
+                               LOG.error("Error calling registry listener", 
th);
+                       }
+               }
+       }
+
+       private void unregisterContext(CamelContext camelContext) {
+               contexts.remove(camelContext);
+       for (Listener listener : listeners) {
+               try {
+                               listener.contextRemoved(camelContext);
+                       } catch (Throwable th) {
+                               LOG.error("Error calling registry listener", 
th);
+                       }
+       }
+       }
+
+    @Override
+       public synchronized void addListener(Listener listener, boolean 
withCallback) {
+       if (withCallback) {
+               for (CamelContext ctx : contexts) {
+                       listener.contextAdded(ctx);
+               }
+       }
+       listeners.add(listener);
+    } 
+    
+    @Override
+       public synchronized void removeListener(Listener listener, boolean 
withCallback) {
+       listeners.add(listener);
+       if (withCallback) {
+               for (CamelContext ctx : contexts) {
+                       listener.contextAdded(ctx);
+               }
+       }
+    } 
+    
+    @Override
+       public synchronized Set<CamelContext> getContexts() {
+       return new LinkedHashSet<CamelContext>(contexts);       
+    } 
+    
+    @Override
+       public synchronized Set<CamelContext> getContexts(String name) {
+       Set<CamelContext> result = new LinkedHashSet<CamelContext>();
+       for (CamelContext ctx : contexts) {
+               if (ctx.getName().equals(name)) {
+                       result.add(ctx);
+               }
+       }
+       return result;  
+    } 
+    
+    @Override
+       public synchronized CamelContext getRequiredContext(String name) {
+       Iterator<CamelContext> itctx = getContexts(name).iterator();
+       if (!itctx.hasNext())
+               throw new IllegalStateException("Cannot obtain context for 
name: " + name);
+       return itctx.next();
+    }
+    
+    @Override
+       public synchronized CamelContext getContext(String name) {
+       Iterator<CamelContext> itctx = getContexts(name).iterator();
+       return itctx.hasNext() ? itctx.next() : null;
+    } 
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/ab750c95/camel-core/src/main/java/org/apache/camel/spi/CamelContextRegistry.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/spi/CamelContextRegistry.java 
b/camel-core/src/main/java/org/apache/camel/spi/CamelContextRegistry.java
new file mode 100644
index 0000000..a27ca35
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/spi/CamelContextRegistry.java
@@ -0,0 +1,80 @@
+package org.apache.camel.spi;
+
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.DefaultCamelContextRegistry;
+
+/**
+ * A global registry for camel contexts.
+ *
+ * The runtime registeres all contexts that derive from {@link 
DefaultCamelContext} automatically.
+ */
+public interface CamelContextRegistry {
+
+       /**
+        * The registry singleton
+        */
+       static final CamelContextRegistry INSTANCE = new 
DefaultCamelContextRegistry();
+       
+       /**
+        * A listener that can be registered witht he registry
+        */
+       public class Listener {
+
+               /**
+                * Called when a context is added to the registry
+                */
+               public void contextAdded(CamelContext camelContext) {
+               }
+               
+               /**
+                * Called when a context is removed from the registry
+                */
+               public void contextRemoved(CamelContext camelContext) {
+               }
+       }
+
+       /**
+        * Add the given listener to the registry
+        * @param withCallback If true, the given listener is called with the 
set of already registered contexts
+        */
+       void addListener(Listener listener, boolean withCallback);
+
+       /**
+        * Remove the given listener from the registry
+        * @param withCallback If true, the given listener is called with the 
set of already registered contexts
+        */
+       void removeListener(Listener listener, boolean withCallback);
+
+       /**
+        * Get the set of registerd contexts
+        */
+       Set<CamelContext> getContexts();
+
+       /**
+        * Get the set of registered contexts for the given name.
+        * 
+        * Because the camel context name property is neither unique nor 
immutable
+        * the returned set may vary for the same name.
+        */
+       Set<CamelContext> getContexts(String name);
+
+       /**
+        * Get the registered context for the given name.
+        * 
+        * @return The first context in the set
+        * @throws IllegalStateException when there is no registered context 
for the given name
+        * @see CamelContextRegistry#getContexts(String)
+        */
+       CamelContext getRequiredContext(String name);
+       
+       /**
+        * Get the registered context for the given name.
+        * 
+        * @return The first context in the set or null
+        * @see CamelContextRegistry#getContexts(String)
+        */
+       CamelContext getContext(String name);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/ab750c95/camel-core/src/main/java/org/apache/camel/spi/Container.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/Container.java 
b/camel-core/src/main/java/org/apache/camel/spi/Container.java
index bcfc2da..ba0a258 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/Container.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/Container.java
@@ -34,7 +34,10 @@ import org.slf4j.LoggerFactory;
  * This implementation is <b>not</b> thread-safe. The {@link 
#manage(org.apache.camel.CamelContext)} method
  * may be invoked concurrently if multiple Camel applications is being started 
concurrently, such as from
  * application servers that may start deployments concurrently.
+ * 
+ * @deprecated use {@link CamelContextRegistry}
  */
+// [TODO] Remove in 3.0
 public interface Container {
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/ab750c95/camel-core/src/test/java/org/apache/camel/spi/CamelContextRegistryTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/spi/CamelContextRegistryTest.java 
b/camel-core/src/test/java/org/apache/camel/spi/CamelContextRegistryTest.java
new file mode 100644
index 0000000..d64ca8f
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/spi/CamelContextRegistryTest.java
@@ -0,0 +1,68 @@
+/**
+ * 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.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+
+public class CamelContextRegistryTest extends TestCase {
+
+    private final class MyListener extends CamelContextRegistry.Listener {
+
+        private List<String> names = new ArrayList<String>();
+
+        @Override
+               public void contextAdded(CamelContext camelContext) {
+            names.add(camelContext.getName());
+               }
+
+               @Override
+               public void contextRemoved(CamelContext camelContext) {
+            names.remove(camelContext.getName());
+               }
+    }
+
+    public void testContainerSet() throws Exception {
+        MyListener listener = new MyListener();
+        
+        CamelContext camel1 = new DefaultCamelContext();
+        CamelContext camel2 = new DefaultCamelContext();
+
+        assertEquals(0, listener.names.size());
+        
+        CamelContextRegistry.INSTANCE.addListener(listener, true);
+        
+        // after we set, then we should manage the 2 pending contexts
+        assertEquals(2, listener.names.size());
+
+        CamelContext camel3 = new DefaultCamelContext();
+        assertEquals(3, listener.names.size());
+        assertEquals(camel1.getName(), listener.names.get(0));
+        assertEquals(camel2.getName(), listener.names.get(1));
+        assertEquals(camel3.getName(), listener.names.get(2));
+
+        camel1.stop();
+        camel2.stop();
+        camel3.stop();
+        
+        assertEquals(0, listener.names.size());
+    }
+}

Reply via email to