You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2010/05/28 09:52:36 UTC

svn commit: r949127 [3/5] - in /camel/trunk: components/ components/camel-blueprint/ components/camel-blueprint/src/main/java/org/apache/camel/blueprint/ components/camel-blueprint/src/main/java/org/apache/camel/blueprint/handler/ components/camel-blue...

Added: camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTracker.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTracker.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTracker.java (added)
+++ camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTracker.java Fri May 28 07:52:33 2010
@@ -0,0 +1,464 @@
+/**
+ * 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.
+ */
+
+/*
+ * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ * 
+ * Licensed 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.tracker;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.SynchronousBundleListener;
+
+/**
+ * The <code>BundleTracker</code> class simplifies tracking bundles much like
+ * the <code>ServiceTracker</code> simplifies tracking services.
+ * <p>
+ * A <code>BundleTracker</code> is constructed with state criteria and a
+ * <code>BundleTrackerCustomizer</code> object. A <code>BundleTracker</code> can
+ * use the <code>BundleTrackerCustomizer</code> to select which bundles are
+ * tracked and to create a customized object to be tracked with the bundle. The
+ * <code>BundleTracker</code> can then be opened to begin tracking all bundles
+ * whose state matches the specified state criteria.
+ * <p>
+ * The <code>getBundles</code> method can be called to get the
+ * <code>Bundle</code> objects of the bundles being tracked. The
+ * <code>getObject</code> method can be called to get the customized object for
+ * a tracked bundle.
+ * <p>
+ * The <code>BundleTracker</code> class is thread-safe. It does not call a
+ * <code>BundleTrackerCustomizer</code> while holding any locks.
+ * <code>BundleTrackerCustomizer</code> implementations must also be
+ * thread-safe.
+ * 
+ * @ThreadSafe
+ * @version $Revision: 824648 $
+ * @since 1.4
+ */
+public class BundleTracker implements BundleTrackerCustomizer {
+    /* set this to true to compile in debug messages */
+    static final boolean DEBUG = false;
+ 
+    /**
+     * The Bundle Context used by this <code>BundleTracker</code>.
+     */
+    protected final BundleContext context;
+    
+    /**
+     * State mask for bundles being tracked. This field contains the ORed values
+     * of the bundle states being tracked.
+     */
+    final int mask;
+    
+    /**
+     * The <code>BundleTrackerCustomizer</code> object for this tracker.
+     */
+    final BundleTrackerCustomizer customizer;
+
+    /**
+     * Tracked bundles: <code>Bundle</code> object -> customized Object and
+     * <code>BundleListener</code> object
+     */
+    private volatile Tracked tracked;
+
+    /**
+     * Create a <code>BundleTracker</code> for bundles whose state is present in
+     * the specified state mask.
+     * <p>
+     * Bundles whose state is present on the specified state mask will be
+     * tracked by this <code>BundleTracker</code>.
+     * 
+     * @param context The <code>BundleContext</code> against which the tracking
+     *            is done.
+     * @param stateMask The bit mask of the <code>OR</code>ing of the bundle
+     *            states to be tracked.
+     * @param customizer The customizer object to call when bundles are added,
+     *            modified, or removed in this <code>BundleTracker</code>. If
+     *            customizer is <code>null</code>, then this
+     *            <code>BundleTracker</code> will be used as the
+     *            <code>BundleTrackerCustomizer</code> and this
+     *            <code>BundleTracker</code> will call the
+     *            <code>BundleTrackerCustomizer</code> methods on itself.
+     * @see Bundle#getState()
+     */
+    public BundleTracker(BundleContext context, int stateMask, BundleTrackerCustomizer customizer) {
+        this.context = context;
+        this.mask = stateMask;
+        this.customizer = (customizer == null) ? this : customizer;
+    }
+    
+    /**
+     * Accessor method for the current Tracked object. This method is only
+     * intended to be used by the unsynchronized methods which do not modify the
+     * tracked field.
+     * 
+     * @return The current Tracked object.
+     */
+    private Tracked tracked() {
+        return tracked;
+    }
+
+
+    /**
+     * Open this <code>BundleTracker</code> and begin tracking bundles.
+     * <p>
+     * Bundle which match the state criteria specified when this
+     * <code>BundleTracker</code> was created are now tracked by this
+     * <code>BundleTracker</code>.
+     * 
+     * @throws java.lang.IllegalStateException If the <code>BundleContext</code>
+     *             with which this <code>BundleTracker</code> was created is no
+     *             longer valid.
+     * @throws java.lang.SecurityException If the caller and this class do not
+     *             have the appropriate
+     *             <code>AdminPermission[context bundle,LISTENER]</code>, and
+     *             the Java Runtime Environment supports permissions.
+     */
+    public void open() {
+        final Tracked t;
+        synchronized (this) {
+            if (tracked != null) {
+                return;
+            }
+            if (DEBUG) {
+                System.out.println("BundleTracker.open"); //$NON-NLS-1$
+            }
+            t = new Tracked();
+            synchronized (t) {
+                context.addBundleListener(t);
+                Bundle[] bundles = context.getBundles();
+                if (bundles != null) {
+                    int length = bundles.length;
+                    for (int i = 0; i < length; i++) {
+                        int state = bundles[i].getState();
+                        if ((state & mask) == 0) {
+                            /* null out bundles whose states are not interesting */
+                            bundles[i] = null;
+                        }
+                    }
+                    /* set tracked with the initial bundles */
+                    t.setInitial(bundles);
+                }
+            }
+            tracked = t;
+        }
+        /* Call tracked outside of synchronized region */
+        t.trackInitial(); /* process the initial references */
+    }
+
+    /**
+     * Close this <code>BundleTracker</code>.
+     * <p>
+     * This method should be called when this <code>BundleTracker</code> should
+     * end the tracking of bundles.
+     * <p>
+     * This implementation calls {@link #getBundles()} to get the list of
+     * tracked bundles to remove.
+     */
+    public void close() {
+        final Bundle[] bundles;
+        final Tracked outgoing;
+        synchronized (this) {
+            outgoing = tracked;
+            if (outgoing == null) {
+                return;
+            }
+            if (DEBUG) {
+                System.out.println("BundleTracker.close"); //$NON-NLS-1$
+            }
+            outgoing.close();
+            bundles = getBundles();
+            tracked = null;
+            try {
+                context.removeBundleListener(outgoing);
+            } catch (IllegalStateException e) {
+                /* In case the context was stopped. */
+            }
+        }
+        if (bundles != null) {
+            for (int i = 0; i < bundles.length; i++) {
+                outgoing.untrack(bundles[i], null);
+            }
+        }
+    }
+
+    /**
+     * Default implementation of the
+     * <code>BundleTrackerCustomizer.addingBundle</code> method.
+     * <p>
+     * This method is only called when this <code>BundleTracker</code> has been
+     * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+     * <p>
+     * This implementation simply returns the specified <code>Bundle</code>.
+     * <p>
+     * This method can be overridden in a subclass to customize the object to be
+     * tracked for the bundle being added.
+     * 
+     * @param bundle The <code>Bundle</code> being added to this
+     *            <code>BundleTracker</code> object.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @return The specified bundle.
+     * @see BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)
+     */
+    public Object addingBundle(Bundle bundle, BundleEvent event) {
+        return bundle;
+    }
+
+    /**
+     * Default implementation of the
+     * <code>BundleTrackerCustomizer.modifiedBundle</code> method.
+     * <p>
+     * This method is only called when this <code>BundleTracker</code> has been
+     * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+     * <p>
+     * This implementation does nothing.
+     * 
+     * @param bundle The <code>Bundle</code> whose state has been modified.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The customized object for the specified Bundle.
+     * @see BundleTrackerCustomizer#modifiedBundle(Bundle, BundleEvent, Object)
+     */
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+        /* do nothing */
+    }
+
+    /**
+     * Default implementation of the
+     * <code>BundleTrackerCustomizer.removedBundle</code> method.
+     * <p>
+     * This method is only called when this <code>BundleTracker</code> has been
+     * constructed with a <code>null BundleTrackerCustomizer</code> argument.
+     * <p>
+     * This implementation does nothing.
+     * 
+     * @param bundle The <code>Bundle</code> being removed.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The customized object for the specified bundle.
+     * @see BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)
+     */
+    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+        /* do nothing */
+    }
+
+    /**
+     * Return an array of <code>Bundle</code>s for all bundles being tracked by
+     * this <code>BundleTracker</code>.
+     * 
+     * @return An array of <code>Bundle</code>s or <code>null</code> if no
+     *         bundles are being tracked.
+     */
+    public Bundle[] getBundles() {
+        final Tracked t = tracked();
+        if (t == null) { /* if BundleTracker is not open */
+            return null;
+        }
+        synchronized (t) {
+            int length = t.size();
+            if (length == 0) {
+                return null;
+            }
+            return (Bundle[])t.getTracked(new Bundle[length]);
+        }
+    }
+
+    /**
+     * Returns the customized object for the specified <code>Bundle</code> if
+     * the specified bundle is being tracked by this <code>BundleTracker</code>.
+     * 
+     * @param bundle The <code>Bundle</code> being tracked.
+     * @return The customized object for the specified <code>Bundle</code> or
+     *         <code>null</code> if the specified <code>Bundle</code> is not
+     *         being tracked.
+     */
+    public Object getObject(Bundle bundle) {
+        final Tracked t = tracked();
+        if (t == null) { /* if BundleTracker is not open */
+            return null;
+        }
+        synchronized (t) {
+            return t.getCustomizedObject(bundle);
+        }
+    }
+
+    /**
+     * Remove a bundle from this <code>BundleTracker</code>. The specified
+     * bundle will be removed from this <code>BundleTracker</code> . If the
+     * specified bundle was being tracked then the
+     * <code>BundleTrackerCustomizer.removedBundle</code> method will be called
+     * for that bundle.
+     * 
+     * @param bundle The <code>Bundle</code> to be removed.
+     */
+    public void remove(Bundle bundle) {
+        final Tracked t = tracked();
+        if (t == null) { /* if BundleTracker is not open */
+            return;
+        }
+        t.untrack(bundle, null);
+    }
+
+    /**
+     * Return the number of bundles being tracked by this
+     * <code>BundleTracker</code>.
+     * 
+     * @return The number of bundles being tracked.
+     */
+    public int size() {
+        final Tracked t = tracked();
+        if (t == null) { /* if BundleTracker is not open */
+            return 0;
+        }
+        synchronized (t) {
+            return t.size();
+        }
+    }
+
+    /**
+     * Returns the tracking count for this <code>BundleTracker</code>. The
+     * tracking count is initialized to 0 when this <code>BundleTracker</code>
+     * is opened. Every time a bundle is added, modified or removed from this
+     * <code>BundleTracker</code> the tracking count is incremented.
+     * <p>
+     * The tracking count can be used to determine if this
+     * <code>BundleTracker</code> has added, modified or removed a bundle by
+     * comparing a tracking count value previously collected with the current
+     * tracking count value. If the value has not changed, then no bundle has
+     * been added, modified or removed from this <code>BundleTracker</code>
+     * since the previous tracking count was collected.
+     * 
+     * @return The tracking count for this <code>BundleTracker</code> or -1 if
+     *         this <code>BundleTracker</code> is not open.
+     */
+    public int getTrackingCount() {
+        final Tracked t = tracked();
+        if (t == null) { /* if BundleTracker is not open */
+            return -1;
+        }
+        synchronized (t) {
+            return t.getTrackingCount();
+        }
+    }
+
+    /**
+     * Inner class which subclasses AbstractTracked. This class is the
+     * <code>SynchronousBundleListener</code> object for the tracker.
+     * 
+     * @ThreadSafe
+     * @since 1.4
+     */
+    class Tracked extends AbstractTracked implements SynchronousBundleListener {
+        /**
+         * Tracked constructor.
+         */
+        Tracked() {
+            super();
+        }
+
+        /**
+         * <code>BundleListener</code> method for the <code>BundleTracker</code>
+         * class. This method must NOT be synchronized to avoid deadlock
+         * potential.
+         * 
+         * @param event <code>BundleEvent</code> object from the framework.
+         */
+        public void bundleChanged(final BundleEvent event) {
+            /*
+             * Check if we had a delayed call (which could happen when we
+             * close).
+             */
+            if (closed) {
+                return;
+            }
+            final Bundle bundle = event.getBundle();
+            final int state = bundle.getState();
+            if (DEBUG) {
+                System.out.println("BundleTracker.Tracked.bundleChanged[" + state + "]: " + bundle); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+
+            if ((state & mask) != 0) {
+                track(bundle, event);
+                /*
+                 * If the customizer throws an unchecked exception, it is safe
+                 * to let it propagate
+                 */
+            } else {
+                untrack(bundle, event);
+                /*
+                 * If the customizer throws an unchecked exception, it is safe
+                 * to let it propagate
+                 */
+            }
+        }
+
+        /**
+         * Call the specific customizer adding method. This method must not be
+         * called while synchronized on this object.
+         * 
+         * @param item Item to be tracked.
+         * @param related Action related object.
+         * @return Customized object for the tracked item or <code>null</code>
+         *         if the item is not to be tracked.
+         */
+        Object customizerAdding(final Object item, final Object related) {
+            return customizer.addingBundle((Bundle)item, (BundleEvent)related);
+        }
+
+        /**
+         * Call the specific customizer modified method. This method must not be
+         * called while synchronized on this object.
+         * 
+         * @param item Tracked item.
+         * @param related Action related object.
+         * @param object Customized object for the tracked item.
+         */
+        void customizerModified(final Object item, final Object related, final Object object) {
+            customizer.modifiedBundle((Bundle)item, (BundleEvent)related, object);
+        }
+
+        /**
+         * Call the specific customizer removed method. This method must not be
+         * called while synchronized on this object.
+         * 
+         * @param item Tracked item.
+         * @param related Action related object.
+         * @param object Customized object for the tracked item.
+         */
+        void customizerRemoved(final Object item, final Object related, final Object object) {
+            customizer.removedBundle((Bundle)item, (BundleEvent)related, object);
+        }
+    }
+}

Added: camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTrackerCustomizer.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTrackerCustomizer.java (added)
+++ camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/tracker/BundleTrackerCustomizer.java Fri May 28 07:52:33 2010
@@ -0,0 +1,116 @@
+/**
+ * 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.
+ */
+
+/*
+ * Copyright (c) OSGi Alliance (2007, 2008). All Rights Reserved.
+ * 
+ * Licensed 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.tracker;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+
+/**
+ * The <code>BundleTrackerCustomizer</code> interface allows a
+ * <code>BundleTracker</code> to customize the <code>Bundle</code>s that are
+ * tracked. A <code>BundleTrackerCustomizer</code> is called when a bundle is
+ * being added to a <code>BundleTracker</code>. The
+ * <code>BundleTrackerCustomizer</code> can then return an object for the
+ * tracked bundle. A <code>BundleTrackerCustomizer</code> is also called when a
+ * tracked bundle is modified or has been removed from a
+ * <code>BundleTracker</code>.
+ * 
+ * <p>
+ * The methods in this interface may be called as the result of a
+ * <code>BundleEvent</code> being received by a <code>BundleTracker</code>.
+ * Since <code>BundleEvent</code>s are received synchronously by the
+ * <code>BundleTracker</code>, it is highly recommended that implementations of
+ * these methods do not alter bundle states while being synchronized on any
+ * object.
+ * 
+ * <p>
+ * The <code>BundleTracker</code> class is thread-safe. It does not call a
+ * <code>BundleTrackerCustomizer</code> while holding any locks.
+ * <code>BundleTrackerCustomizer</code> implementations must also be
+ * thread-safe.
+ * 
+ * @ThreadSafe
+ * @version $Revision: 824648 $
+ * @since 1.4
+ */
+public interface BundleTrackerCustomizer {
+    /**
+     * A bundle is being added to the <code>BundleTracker</code>.
+     * <p>
+     * This method is called before a bundle which matched the search parameters
+     * of the <code>BundleTracker</code> is added to the
+     * <code>BundleTracker</code>. This method should return the object to be
+     * tracked for the specified <code>Bundle</code>. The returned object is
+     * stored in the <code>BundleTracker</code> and is available from the
+     * {@link BundleTracker#getObject(Bundle) getObject} method.
+     * 
+     * @param bundle The <code>Bundle</code> being added to the
+     *            <code>BundleTracker</code>.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @return The object to be tracked for the specified <code>Bundle</code>
+     *         object or <code>null</code> if the specified <code>Bundle</code>
+     *         object should not be tracked.
+     */
+    Object addingBundle(Bundle bundle, BundleEvent event);
+
+    /**
+     * A bundle tracked by the <code>BundleTracker</code> has been modified.
+     * <p>
+     * This method is called when a bundle being tracked by the
+     * <code>BundleTracker</code> has had its state modified.
+     * 
+     * @param bundle The <code>Bundle</code> whose state has been modified.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The tracked object for the specified bundle.
+     */
+    void modifiedBundle(Bundle bundle, BundleEvent event, Object object);
+
+    /**
+     * A bundle tracked by the <code>BundleTracker</code> has been removed.
+     * <p>
+     * This method is called after a bundle is no longer being tracked by the
+     * <code>BundleTracker</code>.
+     * 
+     * @param bundle The <code>Bundle</code> that has been removed.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The tracked object for the specified bundle.
+     */
+    void removedBundle(Bundle bundle, BundleEvent event, Object object);
+}

Added: camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java (added)
+++ camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java Fri May 28 07:52:33 2010
@@ -0,0 +1,87 @@
+/*
+ * 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.utils;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * A ClassLoader delegating to a given OSGi bundle.
+ *
+ * @version $Rev: 896324 $, $Date: 2010-01-06 07:05:04 +0100 (Wed, 06 Jan 2010) $
+ */
+public class BundleDelegatingClassLoader extends ClassLoader {
+
+    private final Bundle bundle;
+    private final ClassLoader classLoader;
+
+    public BundleDelegatingClassLoader(Bundle bundle) {
+        this(bundle, null);
+    }
+
+    public BundleDelegatingClassLoader(Bundle bundle, ClassLoader classLoader) {
+        this.bundle = bundle;
+        this.classLoader = classLoader;
+    }
+
+    protected Class findClass(String name) throws ClassNotFoundException {
+        return bundle.loadClass(name);
+    }
+
+    protected URL findResource(String name) {
+        URL resource = bundle.getResource(name);
+        if (classLoader != null && resource == null) {
+            resource = classLoader.getResource(name);
+        }
+        return resource;
+    }
+
+    protected Enumeration findResources(String name) throws IOException {
+        return bundle.getResources(name);
+    }
+
+    protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        Class clazz;
+        try {
+            clazz = findClass(name);
+        }
+        catch (ClassNotFoundException cnfe) {
+            if (classLoader != null) {
+                try {
+                    clazz = classLoader.loadClass(name);
+                } catch (ClassNotFoundException e) {
+                    throw new ClassNotFoundException(name + " from bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ")", cnfe);
+                }
+            } else {
+                throw new ClassNotFoundException(name + " from bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ")", cnfe);
+            }
+        }
+        if (resolve) {
+            resolveClass(clazz);
+        }
+        return clazz;
+    }
+
+    public Bundle getBundle() {
+        return bundle;
+    }
+}

Added: camel/trunk/components/camel-core-xml/pom.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/pom.xml?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-xml/pom.xml (added)
+++ camel/trunk/components/camel-core-xml/pom.xml Fri May 28 07:52:33 2010
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-parent</artifactId>
+    <version>2.4-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-core-xml</artifactId>
+  <name>Camel :: Core XML</name>
+  <description>Camel Core XML support</description>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <childDelegation>false</childDelegation>
+          <useFile>true</useFile>
+          <forkMode>pertest</forkMode>
+          <includes>
+             <include>**/*Test.java</include>
+          </includes>
+          <excludes>            
+            <!-- TODO FIXME ASAP -->
+            <exclude>**/XXXTest.*</exclude>            
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

Added: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelConsumerTemplateFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelConsumerTemplateFactoryBean.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelConsumerTemplateFactoryBean.java (added)
+++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelConsumerTemplateFactoryBean.java Fri May 28 07:52:33 2010
@@ -0,0 +1,112 @@
+/**
+ * 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.xml;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.impl.DefaultConsumerTemplate;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.util.ServiceHelper;
+
+/**
+ * A factory for creating a new {@link org.apache.camel.ConsumerTemplate}
+ * instance with a minimum of XML
+ *
+ * @version $Revision: 934375 $
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class AbstractCamelConsumerTemplateFactoryBean extends IdentifiedType implements CamelContextAware {
+    @XmlTransient
+    private ConsumerTemplate template;
+    @XmlAttribute
+    private String camelContextId;
+    @XmlTransient
+    private CamelContext camelContext;
+    @XmlAttribute
+    private Integer maximumCacheSize;
+
+    public void afterPropertiesSet() throws Exception {
+        if (camelContext == null && camelContextId != null) {
+            camelContext = getCamelContextWithId(camelContextId);
+        }
+        if (camelContext == null) {
+            throw new IllegalArgumentException("A CamelContext or a CamelContextId must be injected!");
+        }
+    }
+
+    protected abstract CamelContext getCamelContextWithId(String camelContextId);
+
+    public Object getObject() throws Exception {
+        template = new DefaultConsumerTemplate(camelContext);
+
+        // set custom cache size if provided
+        if (maximumCacheSize != null) {
+            template.setMaximumCacheSize(maximumCacheSize);
+        }
+
+        // must start it so its ready to use
+        ServiceHelper.startService(template);
+        return template;
+    }
+
+    public Class getObjectType() {
+        return DefaultConsumerTemplate.class;
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public void destroy() throws Exception {
+        ServiceHelper.stopService(template);
+    }
+
+    // Properties
+    // -------------------------------------------------------------------------
+
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public String getCamelContextId() {
+        return camelContextId;
+    }
+
+    public void setCamelContextId(String camelContextId) {
+        this.camelContextId = camelContextId;
+    }
+
+    public Integer getMaximumCacheSize() {
+        return maximumCacheSize;
+    }
+
+    public void setMaximumCacheSize(Integer maximumCacheSize) {
+        this.maximumCacheSize = maximumCacheSize;
+    }
+}
\ No newline at end of file

Added: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java (added)
+++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java Fri May 28 07:52:33 2010
@@ -0,0 +1,879 @@
+/**
+ * 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.xml;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelException;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.ShutdownRoute;
+import org.apache.camel.ShutdownRunningTask;
+import org.apache.camel.builder.ErrorHandlerBuilderRef;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.component.properties.PropertiesResolver;
+import org.apache.camel.management.DefaultManagementAgent;
+import org.apache.camel.management.DefaultManagementLifecycleStrategy;
+import org.apache.camel.management.DefaultManagementStrategy;
+import org.apache.camel.management.ManagedManagementStrategy;
+import org.apache.camel.model.*;
+import org.apache.camel.model.config.PropertiesDefinition;
+import org.apache.camel.model.dataformat.DataFormatsDefinition;
+import org.apache.camel.processor.interceptor.Delayer;
+import org.apache.camel.processor.interceptor.HandleFault;
+import org.apache.camel.processor.interceptor.TraceFormatter;
+import org.apache.camel.processor.interceptor.Tracer;
+import org.apache.camel.spi.*;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.EndpointHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.core.xml.scan.PatternBasedPackageScanFilter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A factory to create and initialize a
+ * {@link CamelContext} and install routes either explicitly configured
+ * or found by searching the classpath for Java classes which extend
+ * {@link org.apache.camel.builder.RouteBuilder}.
+ *
+ * @version $Revision: 938746 $
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class AbstractCamelContextFactoryBean<T extends CamelContext> extends IdentifiedType implements RouteContainer {
+
+    private static final Log LOG = LogFactory.getLog(AbstractCamelContextFactoryBean.class);
+
+//    @XmlAttribute(name = "depends-on", required = false)
+//    private String dependsOn;
+//    @XmlAttribute(required = false)
+//    private String trace;
+//    @XmlAttribute(required = false)
+//    private String streamCache = "false";
+//    @XmlAttribute(required = false)
+//    private String delayer;
+//    @XmlAttribute(required = false)
+//    private String handleFault;
+//    @XmlAttribute(required = false)
+//    private String errorHandlerRef;
+//    @XmlAttribute(required = false)
+//    private String autoStartup = "true";
+//    @XmlAttribute(required = false)
+//    private ShutdownRoute shutdownRoute;
+//    @XmlAttribute(required = false)
+//    private ShutdownRunningTask shutdownRunningTask;
+//    @XmlElement(name = "properties", required = false)
+//    private PropertiesDefinition properties;
+//    @XmlElement(name = "propertyPlaceholder", type = CamelPropertyPlaceholderDefinition.class, required = false)
+//    private CamelPropertyPlaceholderDefinition camelPropertyPlaceholder;
+//    @XmlElement(name = "package", required = false)
+//    private String[] packages = {};
+//    @XmlElement(name = "packageScan", type = PackageScanDefinition.class, required = false)
+//    private PackageScanDefinition packageScan;
+//    @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class, required = false)
+//    private CamelJMXAgentDefinition camelJMXAgent;
+////    @XmlElements({
+////        @XmlElement(name = "beanPostProcessor", type = CamelBeanPostProcessor.class, required = false),
+////        @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
+////        @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false),
+////        @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class, required = false),
+////        @XmlElement(name = "export", type = CamelServiceExporterDefinition.class, required = false),
+////        @XmlElement(name = "errorHandler", type = ErrorHandlerDefinition.class, required = false)})
+////    private List beans;
+//    @XmlElement(name = "routeBuilder", required = false)
+//    private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>();
+//    @XmlElement(name = "routeContextRef", required = false)
+//    private List<RouteContextRefDefinition> routeRefs = new ArrayList<RouteContextRefDefinition>();
+//    @XmlElement(name = "threadPoolProfile", required = false)
+//    private List<ThreadPoolProfileDefinition> threadPoolProfiles;
+////    @XmlElement(name = "threadPool", required = false)
+////    private List<AbstractCamelThreadPoolFactoryBean> threadPools;
+////    @XmlElement(name = "endpoint", required = false)
+////    private List<AbstractCamelEndpointFactoryBean> endpoints;
+//    @XmlElement(name = "dataFormats", required = false)
+//    private DataFormatsDefinition dataFormats;
+//    @XmlElement(name = "onException", required = false)
+//    private List<OnExceptionDefinition> onExceptions = new ArrayList<OnExceptionDefinition>();
+//    @XmlElement(name = "onCompletion", required = false)
+//    private List<OnCompletionDefinition> onCompletions = new ArrayList<OnCompletionDefinition>();
+//    @XmlElement(name = "intercept", required = false)
+//    private List<InterceptDefinition> intercepts = new ArrayList<InterceptDefinition>();
+//    @XmlElement(name = "interceptFrom", required = false)
+//    private List<InterceptFromDefinition> interceptFroms = new ArrayList<InterceptFromDefinition>();
+//    @XmlElement(name = "interceptSendToEndpoint", required = false)
+//    private List<InterceptSendToEndpointDefinition> interceptSendToEndpoints = new ArrayList<InterceptSendToEndpointDefinition>();
+//    @XmlElement(name = "route", required = false)
+//    private List<RouteDefinition> routes = new ArrayList<RouteDefinition>();
+//    @XmlTransient
+//    private T context;
+    @XmlTransient
+    private List<RoutesBuilder> builders = new ArrayList<RoutesBuilder>();
+    @XmlTransient
+    private ClassLoader contextClassLoaderOnStart;
+
+    public AbstractCamelContextFactoryBean() {
+        // Lets keep track of the class loader for when we actually do start things up
+        contextClassLoaderOnStart = Thread.currentThread().getContextClassLoader();
+    }
+
+    public Object getObject() throws Exception {
+        return getContext();
+    }
+
+    public Class getObjectType() {
+        return CamelContext.class;
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public ClassLoader getContextClassLoaderOnStart() {
+        return contextClassLoaderOnStart;
+    }
+
+    public void afterPropertiesSet() throws Exception {
+        if (ObjectHelper.isEmpty(getId())) {
+            throw new IllegalArgumentException("Id must be set");
+        }
+
+        if (getProperties() != null) {
+            getContext().setProperties(getProperties().asMap());
+        }
+
+        // set the resolvers first
+        PackageScanClassResolver packageResolver = getBeanForType(PackageScanClassResolver.class);
+        if (packageResolver != null) {
+            LOG.info("Using custom PackageScanClassResolver: " + packageResolver);
+            getContext().setPackageScanClassResolver(packageResolver);
+        }
+        ClassResolver classResolver = getBeanForType(ClassResolver.class);
+        if (classResolver != null) {
+            LOG.info("Using custom ClassResolver: " + classResolver);
+            getContext().setClassResolver(classResolver);
+        }
+        FactoryFinderResolver factoryFinderResolver = getBeanForType(FactoryFinderResolver.class);
+        if (factoryFinderResolver != null) {
+            LOG.info("Using custom FactoryFinderResolver: " + factoryFinderResolver);
+            getContext().setFactoryFinderResolver(factoryFinderResolver);
+        }
+        ExecutorServiceStrategy executorServiceStrategy = getBeanForType(ExecutorServiceStrategy.class);
+        if (executorServiceStrategy != null) {
+            LOG.info("Using custom ExecutorServiceStrategy: " + executorServiceStrategy);
+            getContext().setExecutorServiceStrategy(executorServiceStrategy);
+        }
+
+        // set the custom registry if defined
+        initCustomRegistry(getContext());
+
+        // setup property placeholder so we got it as early as possible
+        initPropertyPlaceholder();
+
+        // setup JMX agent at first
+        initJMXAgent();
+
+        Tracer tracer = getBeanForType(Tracer.class);
+        if (tracer != null) {
+            // use formatter if there is a TraceFormatter bean defined
+            TraceFormatter formatter = getBeanForType(TraceFormatter.class);
+            if (formatter != null) {
+                tracer.setFormatter(formatter);
+            }
+            LOG.info("Using custom Tracer: " + tracer);
+            getContext().addInterceptStrategy(tracer);
+        }
+
+        HandleFault handleFault = getBeanForType(HandleFault.class);
+        if (handleFault != null) {
+            LOG.info("Using custom HandleFault: " + handleFault);
+            getContext().addInterceptStrategy(handleFault);
+        }
+
+        Delayer delayer = getBeanForType(Delayer.class);
+        if (delayer != null) {
+            LOG.info("Using custom Delayer: " + delayer);
+            getContext().addInterceptStrategy(delayer);
+        }
+
+        InflightRepository inflightRepository = getBeanForType(InflightRepository.class);
+        if (delayer != null) {
+            LOG.info("Using custom InflightRepository: " + inflightRepository);
+            getContext().setInflightRepository(inflightRepository);
+        }
+
+        ManagementStrategy managementStrategy = getBeanForType(ManagementStrategy.class);
+        if (managementStrategy != null) {
+            LOG.info("Using custom ManagementStrategy: " + managementStrategy);
+            getContext().setManagementStrategy(managementStrategy);
+        }
+
+        EventFactory eventFactory = getBeanForType(EventFactory.class);
+        if (eventFactory != null) {
+            LOG.info("Using custom EventFactory: " + eventFactory);
+            getContext().getManagementStrategy().setEventFactory(eventFactory);
+        }
+
+        // set the event notifier strategies if defined
+        Map<String, EventNotifier> eventNotifiers = getContext().getRegistry().lookupByType(EventNotifier.class);
+        if (eventNotifiers != null && !eventNotifiers.isEmpty()) {
+            for (String id : eventNotifiers.keySet()) {
+                EventNotifier notifier = eventNotifiers.get(id);
+                // do not add if already added, for instance a tracer that is also an InterceptStrategy class
+                if (!getContext().getManagementStrategy().getEventNotifiers().contains(notifier)) {
+                    LOG.info("Using custom EventNotifier with id: " + id + " and implementation: " + notifier);
+                    getContext().getManagementStrategy().addEventNotifier(notifier);
+                }
+            }
+        }
+
+        ShutdownStrategy shutdownStrategy = getBeanForType(ShutdownStrategy.class);
+        if (shutdownStrategy != null) {
+            LOG.info("Using custom ShutdownStrategy: " + shutdownStrategy);
+            getContext().setShutdownStrategy(shutdownStrategy);
+        }
+
+        // add global interceptors
+        Map<String, InterceptStrategy> interceptStrategies = getContext().getRegistry().lookupByType(InterceptStrategy.class);
+        if (interceptStrategies != null && !interceptStrategies.isEmpty()) {
+            for (String id : interceptStrategies.keySet()) {
+                InterceptStrategy strategy = interceptStrategies.get(id);
+                // do not add if already added, for instance a tracer that is also an InterceptStrategy class
+                if (!getContext().getInterceptStrategies().contains(strategy)) {
+                    LOG.info("Using custom InterceptStrategy with id: " + id + " and implementation: " + strategy);
+                    getContext().addInterceptStrategy(strategy);
+                }
+            }
+        }
+
+        // set the lifecycle strategy if defined
+        Map<String, LifecycleStrategy> lifecycleStrategies = getContext().getRegistry().lookupByType(LifecycleStrategy.class);
+        if (lifecycleStrategies != null && !lifecycleStrategies.isEmpty()) {
+            for (String id : lifecycleStrategies.keySet()) {
+                LifecycleStrategy strategy = lifecycleStrategies.get(id);
+                // do not add if already added, for instance a tracer that is also an InterceptStrategy class
+                if (!getContext().getLifecycleStrategies().contains(strategy)) {
+                    LOG.info("Using custom LifecycleStrategy with id: " + id + " and implementation: " + strategy);
+                    getContext().addLifecycleStrategy(strategy);
+                }
+            }
+        }
+
+        // set the default thread pool profile if defined
+        initThreadPoolProfiles(getContext());
+
+        // Set the application context and camelContext for the beanPostProcessor
+        initBeanPostProcessor(getContext());
+
+        initCamelContext(getContext());
+
+        // must init route refs before we prepare the routes below
+        initRouteRefs();
+
+        // do special preparation for some concepts such as interceptors and policies
+        // this is needed as JAXB does not build exactly the same model definition as Spring DSL would do
+        // using route builders. So we have here a little custom code to fix the JAXB gaps
+        for (RouteDefinition route : getRoutes()) {
+
+            // abstracts is the cross cutting concerns
+            List<ProcessorDefinition> abstracts = new ArrayList<ProcessorDefinition>();
+
+            // upper is the cross cutting concerns such as interceptors, error handlers etc
+            List<ProcessorDefinition> upper = new ArrayList<ProcessorDefinition>();
+
+            // lower is the regular route
+            List<ProcessorDefinition> lower = new ArrayList<ProcessorDefinition>();
+
+            prepareRouteForInit(route, abstracts, lower);
+
+            // toAsync should fix up itself at first
+            initToAsync(lower);
+
+            // interceptors should be first for the cross cutting concerns
+            initInterceptors(route, upper);
+            // then on completion
+            initOnCompletions(abstracts, upper);
+            // then transactions
+            initTransacted(abstracts, lower);
+            // then on exception
+            initOnExceptions(abstracts, upper);
+
+            // rebuild route as upper + lower
+            route.clearOutput();
+            route.getOutputs().addAll(upper);
+            route.getOutputs().addAll(lower);
+
+            // configure parents
+            initParent(route);
+        }
+
+        if (getDataFormats() != null) {
+            getContext().setDataFormats(getDataFormats().asMap());
+        }
+
+        // lets force any lazy creation
+        getContext().addRouteDefinitions(getRoutes());
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Found JAXB created routes: " + getRoutes());
+        }
+        findRouteBuilders();
+        installRoutes();
+    }
+
+    protected abstract void initCustomRegistry(T context);
+
+    private void prepareRouteForInit(RouteDefinition route, List<ProcessorDefinition> abstracts,
+                                     List<ProcessorDefinition> lower) {
+        // filter the route into abstracts and lower
+        for (ProcessorDefinition output : route.getOutputs()) {
+            if (output.isAbstract()) {
+                abstracts.add(output);
+            } else {
+                lower.add(output);
+            }
+        }
+    }
+
+    private void initParent(RouteDefinition route) {
+        for (ProcessorDefinition output : route.getOutputs()) {
+            output.setParent(route);
+            if (output.getOutputs() != null) {
+                // recursive the outputs
+                initParent(output);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initParent(ProcessorDefinition parent) {
+        List<ProcessorDefinition> children = parent.getOutputs();
+        for (ProcessorDefinition child : children) {
+            child.setParent(parent);
+            if (child.getOutputs() != null) {
+                // recursive the children
+                initParent(child);
+            }
+        }
+    }
+
+    private void initToAsync(List<ProcessorDefinition> lower) {
+        List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
+        ToDefinition toAsync = null;
+
+        for (ProcessorDefinition output : lower) {
+            if (toAsync != null) {
+                // add this output on toAsync
+                toAsync.getOutputs().add(output);
+            } else {
+                // regular outputs
+                outputs.add(output);
+            }
+
+            if (output instanceof ToDefinition) {
+                ToDefinition to = (ToDefinition) output;
+                if (to.isAsync() != null && to.isAsync()) {
+                    // new current to async
+                    toAsync = to;
+                }
+            }
+        }
+
+        // rebuild outputs
+        lower.clear();
+        lower.addAll(outputs);
+    }
+
+    private void initOnExceptions(List<ProcessorDefinition> abstracts, List<ProcessorDefinition> upper) {
+        // add global on exceptions if any
+        List<OnExceptionDefinition> onExceptions = getOnExceptions();
+        if (onExceptions != null && !onExceptions.isEmpty()) {
+            abstracts.addAll(onExceptions);
+        }
+
+        // now add onExceptions to the route
+        for (ProcessorDefinition output : abstracts) {
+            if (output instanceof OnExceptionDefinition) {
+                // on exceptions must be added at top, so the route flow is correct as
+                // on exceptions should be the first outputs
+                upper.add(0, output);
+            }
+        }
+    }
+
+    private void initInterceptors(RouteDefinition route, List<ProcessorDefinition> upper) {
+        // configure intercept
+        for (InterceptDefinition intercept : getIntercepts()) {
+            intercept.afterPropertiesSet();
+            // add as first output so intercept is handled before the actual route and that gives
+            // us the needed head start to init and be able to intercept all the remaining processing steps
+            upper.add(0, intercept);
+        }
+
+        // configure intercept from
+        for (InterceptFromDefinition intercept : getInterceptFroms()) {
+
+            // should we only apply interceptor for a given endpoint uri
+            boolean match = true;
+            if (intercept.getUri() != null) {
+                match = false;
+                for (FromDefinition input : route.getInputs()) {
+                    if (EndpointHelper.matchEndpoint(input.getUri(), intercept.getUri())) {
+                        match = true;
+                        break;
+                    }
+                }
+            }
+
+            if (match) {
+                intercept.afterPropertiesSet();
+                // add as first output so intercept is handled before the actual route and that gives
+                // us the needed head start to init and be able to intercept all the remaining processing steps
+                upper.add(0, intercept);
+            }
+        }
+
+        // configure intercept send to endpoint
+        for (InterceptSendToEndpointDefinition intercept : getInterceptSendToEndpoints()) {
+            intercept.afterPropertiesSet();
+            // add as first output so intercept is handled before the actual route and that gives
+            // us the needed head start to init and be able to intercept all the remaining processing steps
+            upper.add(0, intercept);
+        }
+    }
+
+    private void initOnCompletions(List<ProcessorDefinition> abstracts, List<ProcessorDefinition> upper) {
+        List<OnCompletionDefinition> completions = new ArrayList<OnCompletionDefinition>();
+
+        // find the route scoped onCompletions
+        for (ProcessorDefinition out : abstracts) {
+            if (out instanceof OnCompletionDefinition) {
+                completions.add((OnCompletionDefinition) out);
+            }
+        }
+
+        // only add global onCompletion if there are no route already
+        if (completions.isEmpty()) {
+            completions = getOnCompletions();
+        }
+
+        // are there any completions to init at all?
+        if (completions.isEmpty()) {
+            return;
+        }
+
+        upper.addAll(completions);
+    }
+
+    private void initTransacted(List<ProcessorDefinition> abstracts, List<ProcessorDefinition> lower) {
+        TransactedDefinition transacted = null;
+
+        // add to correct type
+        for (ProcessorDefinition type : abstracts) {
+            if (type instanceof TransactedDefinition) {
+                if (transacted == null) {
+                    transacted = (TransactedDefinition) type;
+                } else {
+                    throw new IllegalArgumentException("The route can only have one transacted defined");
+                }
+            }
+        }
+
+        if (transacted != null) {
+            // the outputs should be moved to the transacted policy
+            transacted.getOutputs().addAll(lower);
+            // and add it as the single output
+            lower.clear();
+            lower.add(transacted);
+        }
+    }
+
+    private void initJMXAgent() throws Exception {
+        CamelJMXAgentDefinition camelJMXAgent = getCamelJMXAgent();
+        if (camelJMXAgent != null && camelJMXAgent.isAgentDisabled()) {
+            LOG.info("JMXAgent disabled");
+            // clear the existing lifecycle strategies define by the DefaultCamelContext constructor
+            getContext().getLifecycleStrategies().clear();
+            // no need to add a lifecycle strategy as we do not need one as JMX is disabled
+            getContext().setManagementStrategy(new DefaultManagementStrategy());
+        } else if (camelJMXAgent != null) {
+            LOG.info("JMXAgent enabled: " + camelJMXAgent);
+            DefaultManagementAgent agent = new DefaultManagementAgent(getContext());
+            agent.setConnectorPort(parseInteger(camelJMXAgent.getConnectorPort()));
+            agent.setCreateConnector(parseBoolean(camelJMXAgent.getCreateConnector()));
+            agent.setMBeanObjectDomainName(parseText(camelJMXAgent.getMbeanObjectDomainName()));
+            agent.setMBeanServerDefaultDomain(parseText(camelJMXAgent.getMbeanServerDefaultDomain()));
+            agent.setRegistryPort(parseInteger(camelJMXAgent.getRegistryPort()));
+            agent.setServiceUrlPath(parseText(camelJMXAgent.getServiceUrlPath()));
+            agent.setUsePlatformMBeanServer(parseBoolean(camelJMXAgent.getUsePlatformMBeanServer()));
+            agent.setOnlyRegisterProcessorWithCustomId(parseBoolean(camelJMXAgent.getOnlyRegisterProcessorWithCustomId()));
+
+            ManagementStrategy managementStrategy = new ManagedManagementStrategy(agent);
+            getContext().setManagementStrategy(managementStrategy);
+
+            // clear the existing lifecycle strategies define by the DefaultCamelContext constructor
+            getContext().getLifecycleStrategies().clear();
+            getContext().addLifecycleStrategy(new DefaultManagementLifecycleStrategy(getContext()));
+            // set additional configuration from camelJMXAgent
+            boolean onlyId = agent.getOnlyRegisterProcessorWithCustomId() != null && agent.getOnlyRegisterProcessorWithCustomId();
+            getContext().getManagementStrategy().onlyManageProcessorWithCustomId(onlyId);
+            getContext().getManagementStrategy().setStatisticsLevel(camelJMXAgent.getStatisticsLevel());
+        }
+    }
+
+    private void initPropertyPlaceholder() throws Exception {
+        if (getCamelPropertyPlaceholder() != null) {
+            CamelPropertyPlaceholderDefinition def = getCamelPropertyPlaceholder();
+
+            PropertiesComponent pc = new PropertiesComponent();
+            pc.setLocation(def.getLocation());
+
+            // if using a custom resolver
+            if (ObjectHelper.isNotEmpty(def.getPropertiesResolverRef())) {
+                PropertiesResolver resolver = CamelContextHelper.mandatoryLookup(getContext(), def.getPropertiesResolverRef(),
+                                                                                 PropertiesResolver.class);
+                pc.setPropertiesResolver(resolver);
+            }
+
+            // register the properties component
+            getContext().addComponent("properties", pc);
+        }
+    }
+
+    private void initRouteRefs() throws Exception {
+        // add route refs to existing routes
+        if (getRouteRefs() != null) {
+            for (RouteContextRefDefinition ref : getRouteRefs()) {
+                List<RouteDefinition> defs = ref.lookupRoutes(getContext());
+                for (RouteDefinition def : defs) {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Adding route from " + ref + " -> " + def);
+                    }
+                    // add in top as they are most likely to be common/shared
+                    // which you may want to start first
+                    getRoutes().add(0, def);
+                }
+            }
+        }
+    }
+
+    protected abstract <S> S getBeanForType(Class<S> clazz);
+
+    public void destroy() throws Exception {
+        getContext().stop();
+    }
+
+    private String parseText(String text) throws Exception {
+        // ensure we support property placeholders
+        return getContext().resolvePropertyPlaceholders(text);
+    }
+
+    private Integer parseInteger(String text) throws Exception {
+        // ensure we support property placeholders
+        String s = getContext().resolvePropertyPlaceholders(text);
+        if (s != null) {
+            try {
+                return new Integer(s);
+            } catch (NumberFormatException e) {
+                if (s.equals(text)) {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] as an Integer.", e);
+                } else {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as an Integer.", e);
+                }
+            }
+        }
+        return null;
+    }
+
+    private Long parseLong(String text) throws Exception {
+        // ensure we support property placeholders
+        String s = getContext().resolvePropertyPlaceholders(text);
+        if (s != null) {
+            try {
+                return new Long(s);
+            } catch (NumberFormatException e) {
+                if (s.equals(text)) {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] as a Long.", e);
+                } else {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Long.", e);
+                }
+            }
+        }
+        return null;
+    }
+
+    private Boolean parseBoolean(String text) throws Exception {
+        // ensure we support property placeholders
+        String s = getContext().resolvePropertyPlaceholders(text);
+        if (s != null) {
+            s = s.trim().toLowerCase();
+            if (s.equals("true") || s.equals("false")) {
+                return new Boolean(s);
+            } else {
+                if (s.equals(text)) {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] as a Boolean.");
+                } else {
+                    throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Boolean.");
+                }
+            }
+        }
+        return null;
+    }
+
+    // Properties
+    // -------------------------------------------------------------------------
+    public T getContext() {
+        return getContext(true);
+    }
+
+    public abstract T getContext(boolean create);
+
+    public abstract List<RouteDefinition> getRoutes();
+
+    public abstract List<InterceptDefinition> getIntercepts();
+
+    public abstract List<InterceptFromDefinition> getInterceptFroms();
+
+    public abstract List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints();
+
+    public abstract PropertiesDefinition getProperties();
+
+    public abstract String[] getPackages();
+
+    public abstract PackageScanDefinition getPackageScan();
+
+    public abstract void setPackageScan(PackageScanDefinition packageScan);
+
+    public abstract CamelPropertyPlaceholderDefinition getCamelPropertyPlaceholder();
+
+    public abstract String getTrace();
+
+    public abstract String getStreamCache();
+
+    public abstract String getDelayer();
+
+    public abstract String getHandleFault();
+
+    public abstract String getAutoStartup();
+
+    public abstract CamelJMXAgentDefinition getCamelJMXAgent();
+
+    public abstract List<RouteBuilderDefinition> getBuilderRefs();
+
+    public abstract List<RouteContextRefDefinition> getRouteRefs();
+
+    public abstract String getErrorHandlerRef();
+
+    public abstract DataFormatsDefinition getDataFormats();
+
+    public abstract List<OnExceptionDefinition> getOnExceptions();
+
+    public abstract List<OnCompletionDefinition> getOnCompletions();
+
+    public abstract ShutdownRoute getShutdownRoute();
+
+    public abstract ShutdownRunningTask getShutdownRunningTask();
+
+    public abstract List<ThreadPoolProfileDefinition> getThreadPoolProfiles();
+
+    public abstract String getDependsOn();
+
+    // Implementation methods
+    // -------------------------------------------------------------------------
+
+    /**
+     * Initializes the context
+     *
+     * @param ctx the context
+     * @throws Exception is thrown if error occurred
+     */
+    protected void initCamelContext(T ctx) throws Exception {
+        if (getStreamCache() != null) {
+            ctx.setStreamCaching(parseBoolean(getStreamCache()));
+        }
+        if (getTrace() != null) {
+            ctx.setTracing(parseBoolean(getTrace()));
+        }
+        if (getDelayer() != null) {
+            ctx.setDelayer(parseLong(getDelayer()));
+        }
+        if (getHandleFault() != null) {
+            ctx.setHandleFault(parseBoolean(getHandleFault()));
+        }
+        if (getErrorHandlerRef() != null) {
+            ctx.setErrorHandlerBuilder(new ErrorHandlerBuilderRef(getErrorHandlerRef()));
+        }
+        if (getAutoStartup() != null) {
+            ctx.setAutoStartup(parseBoolean(getAutoStartup()));
+        }
+        if (getShutdownRoute() != null) {
+            ctx.setShutdownRoute(getShutdownRoute());
+        }
+        if (getShutdownRunningTask() != null) {
+            ctx.setShutdownRunningTask(getShutdownRunningTask());
+        }
+    }
+
+    private void initThreadPoolProfiles(T context) {
+        Set<String> defaultIds = new HashSet<String>();
+
+        // lookup and use custom profiles from the registry
+        Map<String, ThreadPoolProfile> profiles = context.getRegistry().lookupByType(ThreadPoolProfile.class);
+        if (profiles != null && !profiles.isEmpty()) {
+            for (String id : profiles.keySet()) {
+                ThreadPoolProfile profile = profiles.get(id);
+                // do not add if already added, for instance a tracer that is also an InterceptStrategy class
+                if (profile.isDefaultProfile()) {
+                    LOG.info("Using custom default ThreadPoolProfile with id: " + id + " and implementation: " + profile);
+                    context.getExecutorServiceStrategy().setDefaultThreadPoolProfile(profile);
+                    defaultIds.add(id);
+                } else {
+                    context.getExecutorServiceStrategy().registerThreadPoolProfile(profile);
+                }
+            }
+        }
+
+        // use custom profiles defined in the CamelContext
+        if (getThreadPoolProfiles() != null && !getThreadPoolProfiles().isEmpty()) {
+            for (ThreadPoolProfileDefinition profile : getThreadPoolProfiles()) {
+                if (profile.isDefaultProfile()) {
+                    LOG.info("Using custom default ThreadPoolProfile with id: " + profile.getId() + " and implementation: " + profile);
+                    context.getExecutorServiceStrategy().setDefaultThreadPoolProfile(profile);
+                    defaultIds.add(profile.getId());
+                } else {
+                    context.getExecutorServiceStrategy().registerThreadPoolProfile(profile);
+                }
+            }
+        }
+
+        // validate at most one is defined
+        if (defaultIds.size() > 1) {
+            throw new IllegalArgumentException("Only exactly one default ThreadPoolProfile is allowed, was " + defaultIds.size() + " ids: " + defaultIds);
+        }
+    }
+
+    protected abstract void initBeanPostProcessor(T context);
+
+    /**
+     * Strategy to install all available routes into the context
+     */
+    protected void installRoutes() throws Exception {
+        List<RouteBuilder> builders = new ArrayList<RouteBuilder>();
+
+        // lets add route builders added from references
+        if (getBuilderRefs() != null) {
+            for (RouteBuilderDefinition builderRef : getBuilderRefs()) {
+                RouteBuilder builder = builderRef.createRouteBuilder(getContext());
+                if (builder != null) {
+                    builders.add(builder);
+                } else {
+                    // support to get the route here
+                    RoutesBuilder routes = builderRef.createRoutes(getContext());
+                    if (routes != null) {
+                        this.builders.add(routes);
+                    } else {
+                        // Throw the exception that we can't find any build here
+                        throw new CamelException("Cannot find any routes with this RouteBuilder reference: " + builderRef);
+                    }
+                }
+            }
+        }
+
+        // install already configured routes
+        for (RoutesBuilder routeBuilder : this.builders) {
+            getContext().addRoutes(routeBuilder);
+        }
+
+        // install builders
+        for (RouteBuilder builder : builders) {
+            // Inject the annotated resource
+            postProcessBeforeInit(builder);
+            getContext().addRoutes(builder);
+        }
+    }
+
+    protected abstract void postProcessBeforeInit(RouteBuilder builder);
+
+    /**
+     * Strategy method to try find {@link org.apache.camel.builder.RouteBuilder} instances on the classpath
+     */
+    protected void findRouteBuilders() throws Exception {
+        PackageScanClassResolver resolver = getContext().getPackageScanClassResolver();
+        addPackageElementContentsToScanDefinition();
+
+        PackageScanDefinition packageScanDef = getPackageScan();
+        if (packageScanDef != null && packageScanDef.getPackages().size() > 0) {
+            // use package scan filter
+            PatternBasedPackageScanFilter filter = new PatternBasedPackageScanFilter();
+            // support property placeholders in include and exclude
+            for (String include : packageScanDef.getIncludes()) {
+                include = getContext().resolvePropertyPlaceholders(include);
+                filter.addIncludePattern(include);
+            }
+            for (String exclude : packageScanDef.getExcludes()) {
+                exclude = getContext().resolvePropertyPlaceholders(exclude);
+                filter.addExcludePattern(exclude);
+            }
+            resolver.addFilter(filter);
+
+            String[] normalized = normalizePackages(getContext(), packageScanDef.getPackages());
+            findRouteBuilders(normalized, builders);
+        }
+    }
+
+    protected abstract void findRouteBuilders(String[] normalized, List<RoutesBuilder> builders) throws Exception;
+
+    private void addPackageElementContentsToScanDefinition() {
+        PackageScanDefinition packageScanDef = getPackageScan();
+
+        if (getPackages() != null && getPackages().length > 0) {
+            if (packageScanDef == null) {
+                packageScanDef = new PackageScanDefinition();
+                setPackageScan(packageScanDef);
+            }
+
+            for (String pkg : getPackages()) {
+                packageScanDef.getPackages().add(pkg);
+            }
+        }
+    }
+
+    private String[] normalizePackages(T context, List<String> unnormalized) throws Exception {
+        List<String> packages = new ArrayList<String>();
+        for (String name : unnormalized) {
+            // it may use property placeholders
+            name = context.resolvePropertyPlaceholders(name);
+            name = ObjectHelper.normalizeClassName(name);
+            if (ObjectHelper.isNotEmpty(name)) {
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Using package: " + name + " to scan for RouteBuilder classes");
+                }
+                packages.add(name);
+            }
+        }
+        return packages.toArray(new String[packages.size()]);
+    }
+
+}
\ No newline at end of file

Added: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java (added)
+++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelEndpointFactoryBean.java Fri May 28 07:52:33 2010
@@ -0,0 +1,97 @@
+package org.apache.camel.core.xml;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Endpoint;
+import org.apache.camel.NoSuchEndpointException;
+import org.apache.camel.model.IdentifiedType;
+
+import static org.apache.camel.util.ObjectHelper.notNull;
+
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class AbstractCamelEndpointFactoryBean extends IdentifiedType implements CamelContextAware {
+    @XmlAttribute
+    @Deprecated
+    private Boolean singleton = Boolean.FALSE;
+    @XmlAttribute
+    private String uri;
+    @XmlAttribute
+    private String camelContextId;
+    @XmlTransient
+    private CamelContext context;
+    @XmlTransient
+    private Endpoint endpoint;
+
+    public Object getObject() throws Exception {
+        if (endpoint == null || !endpoint.isSingleton()) {
+            if (context == null && camelContextId != null) {
+                context = getCamelContextWithId(camelContextId);
+            }
+
+            notNull(context, "context");
+            notNull(uri, "uri");
+
+            endpoint = context.getEndpoint(uri);
+            if (endpoint == null) {
+                throw new NoSuchEndpointException(uri);
+            }
+        }
+        return endpoint;
+    }
+
+    protected abstract CamelContext getCamelContextWithId(String camelContextId);
+
+    public Class getObjectType() {
+        return Endpoint.class;
+    }
+
+    public boolean isSingleton() {
+        return false;
+    }
+
+    public void setSingleton(boolean singleton) {
+    }
+
+    public CamelContext getCamelContext() {
+        return context;
+    }
+
+
+    /**
+     * Sets the context to use to resolve endpoints
+     *
+     * @param context the context used to resolve endpoints
+     */
+    public void setCamelContext(CamelContext context) {
+        this.context = context;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * Sets the URI to use to resolve the endpoint
+     *
+     * @param uri the URI used to set the endpoint
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getCamelContextId() {
+        return camelContextId;
+    }
+
+    public void setCamelContextId(String camelContextId) {
+        this.camelContextId = camelContextId;
+    }
+
+}

Added: camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelProducerTemplateFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelProducerTemplateFactoryBean.java?rev=949127&view=auto
==============================================================================
--- camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelProducerTemplateFactoryBean.java (added)
+++ camel/trunk/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelProducerTemplateFactoryBean.java Fri May 28 07:52:33 2010
@@ -0,0 +1,136 @@
+/**
+ * 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.xml;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Endpoint;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.impl.DefaultProducerTemplate;
+import org.apache.camel.model.IdentifiedType;
+import org.apache.camel.util.ServiceHelper;
+
+/**
+ * A factory for creating a new {@link org.apache.camel.ProducerTemplate}
+ * instance with a minimum of XML
+ *
+ * @version $Revision: 934375 $
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class AbstractCamelProducerTemplateFactoryBean extends IdentifiedType implements CamelContextAware {
+    @XmlTransient
+    private ProducerTemplate template;
+    @XmlAttribute(required = false)
+    private String defaultEndpoint;
+    @XmlAttribute
+    private String camelContextId;
+    @XmlTransient
+    private CamelContext camelContext;
+    @XmlAttribute
+    private Integer maximumCacheSize;
+
+    public void afterPropertiesSet() throws Exception {
+        if (camelContext == null && camelContextId != null) {
+            camelContext = getCamelContextWithId(camelContextId);
+        }
+        if (camelContext == null) {
+            throw new IllegalArgumentException("A CamelContext or a CamelContextId must be injected!");
+        }
+    }
+
+    protected abstract CamelContext getCamelContextWithId(String camelContextId);
+
+    public Object getObject() throws Exception {
+        CamelContext context = getCamelContext();
+        if (defaultEndpoint != null) {
+            Endpoint endpoint = context.getEndpoint(defaultEndpoint);
+            if (endpoint == null) {
+                throw new IllegalArgumentException("No endpoint found for URI: " + defaultEndpoint);
+            } else {
+                template = new DefaultProducerTemplate(context, endpoint);
+            }
+        } else {
+            template = new DefaultProducerTemplate(context);
+        }
+
+        // set custom cache size if provided
+        if (maximumCacheSize != null) {
+            template.setMaximumCacheSize(maximumCacheSize);
+        }
+
+        // must start it so its ready to use
+        ServiceHelper.startService(template);
+        return template;
+    }
+
+    public Class getObjectType() {
+        return DefaultProducerTemplate.class;
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public void destroy() throws Exception {
+        ServiceHelper.stopService(template);
+    }
+
+    // Properties
+    // -------------------------------------------------------------------------
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public String getDefaultEndpoint() {
+        return defaultEndpoint;
+    }
+
+    /**
+     * Sets the default endpoint URI used by default for sending message exchanges
+     */
+    public void setDefaultEndpoint(String defaultEndpoint) {
+        this.defaultEndpoint = defaultEndpoint;
+    }
+
+    public String getCamelContextId() {
+        return camelContextId;
+    }
+
+    public void setCamelContextId(String camelContextId) {
+        this.camelContextId = camelContextId;
+    }
+
+    public Integer getMaximumCacheSize() {
+        return maximumCacheSize;
+    }
+
+    public void setMaximumCacheSize(Integer maximumCacheSize) {
+        this.maximumCacheSize = maximumCacheSize;
+    }
+
+
+}