Author: davsclaus
Date: Sat Apr  5 03:23:36 2008
New Revision: 645063

URL: http://svn.apache.org/viewvc?rev=645063&view=rev
Log:
CAMEL-410
- Fixed bug and applied part of patches from Dan Dudley. Thanks a lot Dan.
- Introduced ExceptionPolicyStrategy to configure if/how exceptintype should 
handle a thrown exception.
- Changed the default behaviour of Camel to be smarter, see javadoc for 
DefaultExceptionPolicyStrategy.

Added:
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
Modified:
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
    
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
    
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java

Modified: 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
 (original)
+++ 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
 Sat Apr  5 03:23:36 2008
@@ -23,6 +23,8 @@
 import org.apache.camel.processor.LoggingLevel;
 import org.apache.camel.processor.RecipientList;
 import org.apache.camel.processor.RedeliveryPolicy;
+import org.apache.camel.processor.ErrorHandlerSupport;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -35,6 +37,7 @@
  */
 public class DeadLetterChannelBuilder extends ErrorHandlerBuilderSupport {
     private RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
+    private ExceptionPolicyStrategy exceptionPolicyStrategy = 
ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
     private ProcessorFactory deadLetterFactory;
     private Processor defaultDeadLetterEndpoint;
     private Expression defaultDeadLetterEndpointExpression;
@@ -60,7 +63,7 @@
 
     public Processor createErrorHandler(Processor processor) throws Exception {
         Processor deadLetter = getDeadLetterFactory().createProcessor();
-        DeadLetterChannel answer = new DeadLetterChannel(processor, 
deadLetter, getRedeliveryPolicy(), getLogger());
+        DeadLetterChannel answer = new DeadLetterChannel(processor, 
deadLetter, getRedeliveryPolicy(), getLogger(), getExceptionPolicyStrategy());
         configure(answer);
         return answer;
     }
@@ -135,6 +138,14 @@
         return log(LogFactory.getLog(log));
     }
 
+    /**
+     * Sets the exception policy to use
+     */
+    public ErrorHandlerBuilderSupport 
exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
+        setExceptionPolicyStrategy(exceptionPolicyStrategy);
+        return this;
+    }
+
     // Properties
     // 
-------------------------------------------------------------------------
     public RedeliveryPolicy getRedeliveryPolicy() {
@@ -220,4 +231,17 @@
     public void setLogger(Logger logger) {
         this.logger = logger;
     }
+
+    /**
+     * Sets the exception policy strategy to use for resolving the [EMAIL 
PROTECTED] org.apache.camel.model.ExceptionType}
+     * to use for a given thrown exception
+     */
+    public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
+        return exceptionPolicyStrategy;
+    }
+
+    public void setExceptionPolicyStrategy(ExceptionPolicyStrategy 
exceptionPolicyStrategy) {
+        this.exceptionPolicyStrategy = exceptionPolicyStrategy;
+    }
+
 }

Modified: 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
 (original)
+++ 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
 Sat Apr  5 03:23:36 2008
@@ -23,6 +23,7 @@
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
 import org.apache.camel.model.ExceptionType;
 import org.apache.camel.util.AsyncProcessorHelper;
@@ -62,16 +63,18 @@
     private Logger logger;
 
     public DeadLetterChannel(Processor output, Processor deadLetter) {
-        this(output, deadLetter, new RedeliveryPolicy(), 
DeadLetterChannel.createDefaultLogger());
+        this(output, deadLetter, new RedeliveryPolicy(), 
DeadLetterChannel.createDefaultLogger(),
+            ErrorHandlerSupport.createDefaultExceptionPolicyStrategy());
     }
 
-    public DeadLetterChannel(Processor output, Processor deadLetter, 
RedeliveryPolicy redeliveryPolicy, Logger logger) {
+    public DeadLetterChannel(Processor output, Processor deadLetter, 
RedeliveryPolicy redeliveryPolicy, Logger logger, ExceptionPolicyStrategy 
exceptionPolicyStrategy) {
         this.deadLetter = deadLetter;
         this.output = output;
         this.outputAsync = AsyncProcessorTypeConverter.convert(output);
 
         this.redeliveryPolicy = redeliveryPolicy;
         this.logger = logger;
+        setExceptionPolicy(exceptionPolicyStrategy);
     }
 
     public static <E extends Exchange> Logger createDefaultLogger() {
@@ -163,7 +166,7 @@
                 callback.done(true);
                 return true;
             }
-            // error occured so loop back around.....
+            // error occurred so loop back around.....
         }
 
     }
@@ -261,7 +264,7 @@
                 Thread.sleep(redeliveryDelay);
             } catch (InterruptedException e) {
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("Thread interupted: " + e, e);
+                    LOG.debug("Thread interrupted: " + e, e);
                 }
             }
         }

Modified: 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
 (original)
+++ 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
 Sat Apr  5 03:23:36 2008
@@ -16,21 +16,25 @@
  */
 package org.apache.camel.processor;
 
-import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.impl.ServiceSupport;
 import org.apache.camel.model.ExceptionType;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import 
org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy;
 
 /**
+ * Support class for [EMAIL PROTECTED] ErrorHandler} implementations.
+ *
  * @version $Revision$
  */
 public abstract class ErrorHandlerSupport extends ServiceSupport implements 
ErrorHandler {
-    private Map<Class, ExceptionType> exceptionPolicices = new 
IdentityHashMap<Class, ExceptionType>();
+    private Map<Class, ExceptionType> exceptionPolicies = new 
LinkedHashMap<Class, ExceptionType>();
+    private ExceptionPolicyStrategy exceptionPolicy = 
createDefaultExceptionPolicyStrategy();
 
     public void addExceptionPolicy(ExceptionType exception) {
         Processor processor = exception.getErrorHandler();
@@ -39,7 +43,7 @@
         List<Class> list = exception.getExceptionClasses();
 
         for (Class exceptionType : list) {
-            exceptionPolicices.put(exceptionType, exception);
+            exceptionPolicies.put(exceptionType, exception);
         }
     }
 
@@ -48,22 +52,44 @@
      */
     protected boolean customProcessorForException(Exchange exchange, Throwable 
exception) throws Exception {
         ExceptionType policy = getExceptionPolicy(exchange, exception);
-        Processor processor = policy.getErrorHandler();
-        if (processor != null) {
-            processor.process(exchange);
-            return true;
+        if (policy != null) {
+            Processor processor = policy.getErrorHandler();
+            if (processor != null) {
+                processor.process(exchange);
+                return true;
+            }
         }
         return false;
     }
 
+    /**
+     * Attempts to find the best suited [EMAIL PROTECTED] ExceptionType} to be 
used for handling the given thrown exception.
+     *
+     * @param exchange  the exchange
+     * @param exception the exception that was thrown
+     * @return the best exception type to handle this exception, <tt>null</tt> 
if none found.
+     */
     protected ExceptionType getExceptionPolicy(Exchange exchange, Throwable 
exception) {
-        Set<Map.Entry<Class, ExceptionType>> entries = 
exceptionPolicices.entrySet();
-        for (Map.Entry<Class, ExceptionType> entry : entries) {
-            Class type = entry.getKey();
-            if (type.isInstance(exception)) {
-                return entry.getValue();
-            }
+        if (exceptionPolicy == null) {
+            throw new IllegalStateException("The exception policy has not been 
set");
         }
-        return null;
+
+        return exceptionPolicy.getExceptionPolicy(exceptionPolicies, exchange, 
exception);
+    }
+
+    /**
+     * Sets the strategy to use for resolving the [EMAIL PROTECTED] 
ExceptionType} to use
+     * for handling thrown exceptions.
+     */
+    public void setExceptionPolicy(ExceptionPolicyStrategy exceptionPolicy) {
+        this.exceptionPolicy = exceptionPolicy;
     }
+
+    /**
+     * Creates the default exception policy strategy to use.
+     */
+    public static ExceptionPolicyStrategy 
createDefaultExceptionPolicyStrategy() {
+        return new DefaultExceptionPolicyStrategy();
+    }
+
 }

Added: 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,85 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The default strategy used in Camel to resolve the [EMAIL PROTECTED] 
org.apache.camel.model.ExceptionType} that should
+ * handle the thrown exception.
+ * <p/>
+ * This strategy applies the following rules:
+ * <ul>
+ *   <li>The exception type must be configured with an Exception that is an 
instance of the thrown exception</li>
+ *   <li>If the exception type has exactly the thrown exception then its 
selected</li>
+ *   <li>Otherwise the type that has an exception that is super of the thrown 
exception is selected
+ *       (recurring up the exception hierarchy)
+ *  </ul>
+ */
+public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy 
{
+
+    private static final transient Log LOG = 
LogFactory.getLog(DefaultExceptionPolicyStrategy.class);
+
+    public ExceptionType getExceptionPolicy(Map<Class, ExceptionType> 
exceptionPolicices, Exchange exchange,
+                                            Throwable exception) {
+        // the goal is to find the exception with the same/closet inheritance 
level as the target exception being thrown
+        int targetLevel = getInheritanceLevel(exception.getClass());
+        // candidate is the best candidate found so far
+        ExceptionType candidate = null;
+        // difference in inheritance level between the current candidate and 
the thrown exception (target level)
+        int candidateDiff = Integer.MAX_VALUE;
+
+        // loop through all the entries and find the best candidates to use
+        Set<Map.Entry<Class, ExceptionType>> entries = 
exceptionPolicices.entrySet();
+        for (Map.Entry<Class, ExceptionType> entry : entries) {
+            Class clazz = entry.getKey();
+            ExceptionType type = entry.getValue();
+
+            // must be instance of check to ensure that the clazz is one type 
of the thrown exception
+            if (clazz.isInstance(exception)) {
+                int level = getInheritanceLevel(clazz);
+                int diff = targetLevel - level;
+
+                if (diff < candidateDiff) {
+                    // replace with a much better candidate
+                    candidate = type;
+                    candidateDiff = diff;
+                }
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Using " + candidate + " as the exception policy");
+        }
+        return candidate;
+
+    }
+
+    private static int getInheritanceLevel(Class clazz) {
+        if (clazz == null || "java.lang.Object".equals(clazz.getName())) {
+            return 0;
+        }
+        return 1 + getInheritanceLevel(clazz.getSuperclass());
+    }
+
+}

Added: 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,43 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * A strategy to determine witch [EMAIL PROTECTED] 
org.apache.camel.model.ExceptionType} should handle the thrown
+ * exception.
+ *
+ * @see 
org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy 
DefaultExceptionPolicy
+ */
+public interface ExceptionPolicyStrategy {
+
+    /**
+     * Resolves the [EMAIL PROTECTED] org.apache.camel.model.ExceptionType} 
that should handle the thrown exception.
+     *
+     * @param exceptionPolicices the configured exception policies to resolve 
from
+     * @param exchange           the exchange
+     * @param exception          the exception that was thrown
+     * @return the resolved exception type to handle this exception, 
<tt>null</tt> if none found.
+     */
+    public ExceptionType getExceptionPolicy(Map<Class, ExceptionType> 
exceptionPolicices, Exchange exchange,
+                                            Throwable exception);
+
+}

Modified: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
 (original)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
 Sat Apr  5 03:23:36 2008
@@ -60,7 +60,7 @@
         }
     }
 
-    public void   testOverloadingTheHandlerOnASingleRoute() throws Exception {
+    public void testOverloadingTheHandlerOnASingleRoute() throws Exception {
 
         // START SNIPPET: e2
         RouteBuilder builder = new RouteBuilder() {
@@ -174,4 +174,5 @@
             log.debug("Found sendProcessor: " + sendProcessor);
         }
     }
+
 }

Added: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,156 @@
+/**
+ * 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.builder;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.security.GeneralSecurityException;
+import java.security.KeyException;
+import java.security.KeyManagementException;
+
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.component.mock.MockEndpoint;
+
+/**
+ * Unit test to test exception configuration
+ */
+public class ExceptionBuilderTest extends ContextTestSupport {
+
+    private static final String MESSAGE_INFO = "messageInfo";
+    private static final String errorQueue = "mock:error";
+    private static final String businessErrorQueue = "mock:badBusiness";
+    private static final String securityErrorQueue = "mock:securitError";
+
+    public void testNPE() throws Exception {
+        MockEndpoint mock = getMockEndpoint(errorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm a NPE");
+
+        template.sendBody("direct:a", "Hello NPE");
+
+        mock.assertIsSatisfied();
+    }
+
+    public void testIOException() throws Exception {
+        MockEndpoint mock = getMockEndpoint(errorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm somekind of IO 
exception");
+
+        template.sendBody("direct:a", "Hello IO");
+
+        mock.assertIsSatisfied();
+    }
+
+    public void testException() throws Exception {
+        MockEndpoint mock = getMockEndpoint(errorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm just exception");
+
+        template.sendBody("direct:a", "Hello Exception");
+
+        mock.assertIsSatisfied();
+    }
+
+    public void testMyBusinessException() throws Exception {
+        MockEndpoint mock = getMockEndpoint(businessErrorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm my business is not 
going to well");
+
+        template.sendBody("direct:a", "Hello business");
+
+        mock.assertIsSatisfied();
+    }
+
+    public void testSecurityConfiguredWithTwoExceptions() throws Exception {
+        // test that we also handles a configuration with 2 or more exceptions
+        MockEndpoint mock = getMockEndpoint(securityErrorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm some security error");
+
+        template.sendBody("direct:a", "I am not allowed to do this");
+
+        mock.assertIsSatisfied();
+    }
+
+    public static class MyBaseBusinessException extends Exception {
+    }
+
+    public static class MyBusinessException extends MyBaseBusinessException {
+    }
+
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                // START SNIPPET: exceptionBuilder1
+                exception(NullPointerException.class)
+                    .maximumRedeliveries(1)
+                    .setHeader(MESSAGE_INFO, "Damm a NPE")
+                    .to(errorQueue);
+
+                exception(IOException.class)
+                    .initialRedeliveryDelay(5000L)
+                    .maximumRedeliveries(3)
+                    .backOffMultiplier(1.0)
+                    .useExponentialBackOff()
+                    .setHeader(MESSAGE_INFO, "Damm somekind of IO exception")
+                    .to(errorQueue);
+
+                exception(Exception.class)
+                    .initialRedeliveryDelay(1000L)
+                    .maximumRedeliveries(2)
+                    .setHeader(MESSAGE_INFO, "Damm just exception")
+                    .to(errorQueue);
+                // END SNIPPET: exceptionBuilder1
+
+                exception(MyBaseBusinessException.class)
+                    .initialRedeliveryDelay(1000L)
+                    .maximumRedeliveries(3)
+                    .setHeader(MESSAGE_INFO, "Damm my business is not going to 
well")
+                    .to(businessErrorQueue);
+
+                
exception(GeneralSecurityException.class).exception(KeyException.class)
+                    .maximumRedeliveries(1)
+                    .setHeader(MESSAGE_INFO, "Damm some security error")
+                    .to(securityErrorQueue);
+
+
+                from("direct:a").process(new Processor() {
+                    public void process(Exchange exchange) throws Exception {
+                        String s = exchange.getIn().getBody(String.class);
+                        if ("Hello NPE".equals(s)) {
+                            throw new NullPointerException();
+                        } else if ("Hello IO".equals(s)) {
+                            throw new ConnectException("Forced for testing - 
can not connect to remote server");
+                        } else if ("Hello Exception".equals(s)) {
+                            throw new CamelExchangeException("Forced for 
testing", exchange);
+                        } else if ("Hello business".equals(s)) {
+                            throw new MyBusinessException();
+                        } else if ("I am not allowed to do this".equals(s)) {
+                            throw new KeyManagementException();
+                        }
+                        exchange.getOut().setBody("Hello World");
+                    }
+                }).to("mock:result");
+            }
+        };
+    }
+
+}
+

Modified: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
 (original)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
 Sat Apr  5 03:23:36 2008
@@ -23,14 +23,12 @@
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 
-import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
-
 /**
  * @version $Revision$
  */
 public class DeadLetterChannelTest extends ContextTestSupport {
     protected Endpoint<Exchange> startEndpoint;
-    protected MockEndpoint deadEndpoint; 
+    protected MockEndpoint deadEndpoint;
     protected MockEndpoint successEndpoint;
     protected int failUntilAttempt = 2;
     protected String body = "<hello>world!</hello>";
@@ -88,18 +86,13 @@
         return new RouteBuilder() {
             public void configure() {
                 from("direct:start").errorHandler(
-                                                  
deadLetterChannel("mock:failed").maximumRedeliveries(2)
-                                                      
.initialRedeliveryDelay(1)
-                                                      
.loggingLevel(LoggingLevel.DEBUG)
+                    deadLetterChannel("mock:failed").maximumRedeliveries(2)
+                        .initialRedeliveryDelay(1)
+                        .loggingLevel(LoggingLevel.DEBUG)
 
                 ).process(processor);
-
-                /*
-                 * TODO - currently process().to() results in two separate
-                 * operations which have their own error handler
-                 * 
-                 * .to("mock:success");
-                 */
+                // TODO - currently process().to() results in two separate 
operations which have their own error handler
+                // to("mock:success");
             }
         };
     }

Added: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,94 @@
+/**
+ * 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.processor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+
+public class ErrorHandlerSupportTest extends TestCase {
+
+    public void testOnePolicyChildFirst() {
+        List<Class> exceptions = new ArrayList<Class>();
+        exceptions.add(ChildException.class);
+        exceptions.add(ParentException.class);
+
+        ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+        support.addExceptionPolicy(new ExceptionType(exceptions));
+
+        assertEquals(ChildException.class, getExceptionPolicyFor(support, new 
ChildException(), 0));
+        assertEquals(ParentException.class, getExceptionPolicyFor(support, new 
ParentException(), 1));
+    }
+
+    public void testOnePolicyChildLast() {
+        List<Class> exceptions = new ArrayList<Class>();
+        exceptions.add(ParentException.class);
+        exceptions.add(ChildException.class);
+
+        ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+        support.addExceptionPolicy(new ExceptionType(exceptions));
+
+        assertEquals(ChildException.class, getExceptionPolicyFor(support, new 
ChildException(), 1));
+        assertEquals(ParentException.class, getExceptionPolicyFor(support, new 
ParentException(), 0));
+    }
+
+    public void testTwoPolicyChildFirst() {
+        ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+        support.addExceptionPolicy(new ExceptionType(ChildException.class));
+        support.addExceptionPolicy(new ExceptionType(ParentException.class));
+
+        assertEquals(ChildException.class, getExceptionPolicyFor(support, new 
ChildException(), 0));
+        assertEquals(ParentException.class, getExceptionPolicyFor(support, new 
ParentException(), 0));
+    }
+
+    public void testTwoPolicyChildLast() {
+        ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+        support.addExceptionPolicy(new ExceptionType(ParentException.class));
+        support.addExceptionPolicy(new ExceptionType(ChildException.class));
+
+        assertEquals(ChildException.class, getExceptionPolicyFor(support, new 
ChildException(), 0));
+        assertEquals(ParentException.class, getExceptionPolicyFor(support, new 
ParentException(), 0));
+    }
+
+    private static Class getExceptionPolicyFor(ErrorHandlerSupport support, 
Throwable childException,
+                                               int index) {
+        return support.getExceptionPolicy(null, 
childException).getExceptionClasses().get(index);
+    }
+
+    private static class ParentException extends Exception {
+    }
+
+    private static class ChildException extends ParentException {
+    }
+
+    private static class ShuntErrorHandlerSupport extends ErrorHandlerSupport {
+
+        protected void doStart() throws Exception {
+        }
+
+        protected void doStop() throws Exception {
+        }
+
+        public void process(Exchange exchange) throws Exception {
+        }
+    }
+
+}

Added: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,95 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+
+import org.apache.camel.CamelException;
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * Unit test with a user plugged in exception policy to use instead of default.
+ */
+public class CustomExceptionPolicyStrategyTest extends ContextTestSupport {
+
+    private static final String MESSAGE_INFO = "messageInfo";
+    private static final String errorQueue = "mock:error";
+
+    public static class MyPolicyException extends Exception {
+    }
+
+    public static class MyPolicy implements ExceptionPolicyStrategy {
+
+        public ExceptionType getExceptionPolicy(Map<Class, ExceptionType> 
exceptionPolicices,
+                                                Exchange exchange,
+                                                Throwable exception) {
+            // We forced a CamelException in the test below but our custom 
policy will
+            // override and let MyPolicyException handle it instead
+            return exceptionPolicices.get(MyPolicyException.class);
+        }
+    }
+
+
+
+    public void testCustomPolicy() throws Exception {
+        MockEndpoint mock = getMockEndpoint(errorQueue);
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(MESSAGE_INFO, "Damm my policy exception");
+
+        template.sendBody("direct:a", "Hello Camel");
+
+        mock.assertIsSatisfied();
+    }
+
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                // START SNIPPET customExceptionPolicyStrategy
+                // configure the error handler to use my policy instead of the 
default from Camel
+                errorHandler(deadLetterChannel().exceptionPolicyStrategy(new 
MyPolicy()));
+
+                exception(MyPolicyException.class)
+                    .maximumRedeliveries(1)
+                    .setHeader(MESSAGE_INFO, "Damm my policy exception")
+                    .to(errorQueue);
+
+                exception(CamelException.class)
+                    .maximumRedeliveries(3)
+                    .setHeader(MESSAGE_INFO, "Damm a Camel exception")
+                    .to(errorQueue);
+                // END SNIPPET customExceptionPolicyStrategy
+
+                from("direct:a").process(new Processor() {
+                    public void process(Exchange exchange) throws Exception {
+                        String s = exchange.getIn().getBody(String.class);
+                        if ("Hello Camel".equals(s)) {
+                            throw new CamelExchangeException("Forced for 
testing", exchange);
+                        }
+                        exchange.getOut().setBody("Hello World");
+                    }
+                }).to("mock:result");
+            }
+        };
+    }
+
+}

Added: 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
URL: 
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java?rev=645063&view=auto
==============================================================================
--- 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
 (added)
+++ 
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
 Sat Apr  5 03:23:36 2008
@@ -0,0 +1,128 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.SocketException;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+import org.apache.camel.AlreadyStoppedException;
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ExchangeTimedOutException;
+import org.apache.camel.ValidationException;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * Unit test for DefaultExceptionPolicy 
+ */
+public class DefaultExceptionPolicyStrategyTest extends TestCase {
+
+    private DefaultExceptionPolicyStrategy strategy;
+    private HashMap<Class, ExceptionType> policies;
+    private ExceptionType type1;
+    private ExceptionType type2;
+    private ExceptionType type3;
+
+    private void setupPolicies() {
+        strategy = new DefaultExceptionPolicyStrategy();
+        policies = new HashMap<Class, ExceptionType>();
+        type1 = new ExceptionType(CamelExchangeException.class);
+        type2 = new ExceptionType(Exception.class);
+        type3 = new ExceptionType(IOException.class);
+        policies.put(CamelExchangeException.class, type1);
+        policies.put(Exception.class, type2);
+        policies.put(IOException.class, type3);
+    }
+
+    private void setupPoliciesNoTopLevelException() {
+        // without the top level exception that can be used as fallback
+        strategy = new DefaultExceptionPolicyStrategy();
+        policies = new HashMap<Class, ExceptionType>();
+        type1 = new ExceptionType(CamelExchangeException.class);
+        type3 = new ExceptionType(IOException.class);
+        policies.put(CamelExchangeException.class, type1);
+        policies.put(IOException.class, type3);
+    }
+
+    public void testDirectMatch1() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
CamelExchangeException("", null));
+        assertEquals(type1, result);
+    }
+
+    public void testDirectMatch2() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
Exception(""));
+        assertEquals(type2, result);
+    }
+
+    public void testDirectMatch3() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
IOException(""));
+        assertEquals(type3, result);
+    }
+
+    public void testClosetMatch3() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
ConnectException(""));
+        assertEquals(type3, result);
+
+        result = strategy.getExceptionPolicy(policies, null, new 
SocketException(""));
+        assertEquals(type3, result);
+
+        result = strategy.getExceptionPolicy(policies, null, new 
FileNotFoundException());
+        assertEquals(type3, result);
+    }
+
+    public void testClosetMatch2() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
ClassCastException(""));
+        assertEquals(type2, result);
+
+        result = strategy.getExceptionPolicy(policies, null, new 
NumberFormatException(""));
+        assertEquals(type2, result);
+
+        result = strategy.getExceptionPolicy(policies, null, new 
NullPointerException());
+        assertEquals(type2, result);
+    }
+
+    public void testClosetMatch1() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
ValidationException(null, ""));
+        assertEquals(type1, result);
+
+        result = strategy.getExceptionPolicy(policies, null, new 
ExchangeTimedOutException(null, 0));
+        assertEquals(type1, result);
+    }
+
+    public void testNoMatch1ThenMatchingJustException() {
+        setupPolicies();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
AlreadyStoppedException());
+        assertEquals(type2, result);
+    }
+
+    public void testNoMatch1ThenNull() {
+        setupPoliciesNoTopLevelException();
+        ExceptionType result = strategy.getExceptionPolicy(policies, null, new 
AlreadyStoppedException());
+        assertNull("Should not find an exception policy to use", result);
+    }
+
+}


Reply via email to