You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by ka...@apache.org on 2012/02/06 23:45:41 UTC

svn commit: r1241234 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java

Author: kaosko
Date: Mon Feb  6 22:45:40 2012
New Revision: 1241234

URL: http://svn.apache.org/viewvc?rev=1241234&view=rev
Log:
Incomplete - issue TAP5-1833: Merge functionality of Tynamo.org's
tapestry-exceptionpage module with the built-in ExceptionHandler 
- add tests for handleRequestException()

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java?rev=1241234&r1=1241233&r2=1241234&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.java Mon Feb  6 22:45:40 2012
@@ -18,8 +18,6 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URLEncoder;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -31,7 +29,6 @@ import org.apache.tapestry5.ExceptionHan
 import org.apache.tapestry5.Link;
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.structure.Page;
-import org.apache.tapestry5.ioc.ServiceResources;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.internal.OperationException;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -61,8 +58,6 @@ public class DefaultRequestExceptionHand
 
     private final Response response;
     
-    private final ServiceResources serviceResources;
-    
     private final ComponentClassResolver componentClassResolver;
     
     private final LinkSource linkSource;
@@ -70,16 +65,13 @@ public class DefaultRequestExceptionHand
     // should be Class<? extends Throwable>, Object but it's not allowed to configure subtypes
     private final Map<Class, Object> configuration;
     
-    private final Map<Class<ExceptionHandlerAssistant>, ExceptionHandlerAssistant> handlerAssistants = Collections
-            .synchronizedMap(new HashMap<Class<ExceptionHandlerAssistant>, ExceptionHandlerAssistant>());
-
     @SuppressWarnings("rawtypes")
     public DefaultRequestExceptionHandler(RequestPageCache pageCache, PageResponseRenderer renderer, Logger logger,
 
     @Symbol(SymbolConstants.EXCEPTION_REPORT_PAGE)
     String pageName,
 
-    Request request, Response response, ServiceResources serviceResources, ComponentClassResolver componentClassResolver, LinkSource linkSource, Map<Class, Object> configuration)
+    Request request, Response response, ComponentClassResolver componentClassResolver, LinkSource linkSource, Map<Class, Object> configuration)
     {
         this.pageCache = pageCache;
         this.renderer = renderer;
@@ -87,7 +79,6 @@ public class DefaultRequestExceptionHand
         this.pageName = pageName;
         this.request = request;
         this.response = response;
-        this.serviceResources = serviceResources;
         this.componentClassResolver = componentClassResolver;
         this.linkSource = linkSource;
         
@@ -101,6 +92,12 @@ public class DefaultRequestExceptionHand
 
     public void handleRequestException(Throwable exception) throws IOException
     {
+        // skip handling of known exceptions if there are none configured 
+        if (configuration.isEmpty()) {
+            renderException(exception);
+            return;
+        }
+        
         Throwable cause = exception;
 
         // Depending on where the error was thrown, there could be several levels of wrappers..
@@ -129,30 +126,19 @@ public class DefaultRequestExceptionHand
         Object value = configuration.get(causeClass);
         Object page = null;
         ExceptionHandlerAssistant assistant = null;
-        if (value instanceof ExceptionHandlerAssistant) assistant = (ExceptionHandlerAssistant) value;
-        else if (!(value instanceof Class)) {
-            renderException(exception);
-            return;
-        } else if (ExceptionHandlerAssistant.class.isAssignableFrom((Class) value)) {
-            @SuppressWarnings("unchecked")
-            Class<ExceptionHandlerAssistant> handlerType = (Class<ExceptionHandlerAssistant>) value;
-            assistant = handlerAssistants.get(handlerType);
-            if (assistant == null) {
-                assistant = (ExceptionHandlerAssistant) serviceResources.autobuild(handlerType);
-                handlerAssistants.put(handlerType, assistant);
-            }
-        }
-
-        // the assistant may handle the exception directly or return a page
-        if (assistant != null) {
+        if (value instanceof ExceptionHandlerAssistant) {
+            assistant = (ExceptionHandlerAssistant) value;
             // in case the assistant changes the context
             List context = Arrays.asList(exceptionContext);
             page = assistant.handleRequestException(exception, context);
             exceptionContext = context.toArray();
         }
-        if (page == null) return;
+        else if (!(value instanceof Class)) {
+            renderException(exception);
+            return;
+        } else page = value;
 
-        exceptionContext = new Object[0];
+        if (page == null) return;
 
         try {
             if (page instanceof Class) page = componentClassResolver.resolvePageClassNameToPageName(((Class) page).getName());
@@ -163,7 +149,7 @@ public class DefaultRequestExceptionHand
                 os.close();
             } else response.sendRedirect(link);
         }
-        // This could throw exceptions if this is already a render request, but it's
+        // The above could throw an exception if we are already on a render request, but it's
         // user's responsibility not to abuse the mechanism
         catch (Exception e) {
             // Nothing to do but delegate

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java?rev=1241234&r1=1241233&r2=1241234&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandlerTest.java Mon Feb  6 22:45:40 2012
@@ -1,15 +1,34 @@
 package org.apache.tapestry5.internal.services;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import java.io.IOException;
+import java.security.AccessControlException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.tapestry5.ContextAwareException;
+import org.apache.tapestry5.ExceptionHandlerAssistant;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.internal.test.InternalBaseTestCase;
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.Request;
+import org.apache.tapestry5.services.Response;
+import org.easymock.EasyMock;
+import org.slf4j.Logger;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 @SuppressWarnings("serial")
-public class DefaultRequestExceptionHandlerTest {
-	private DefaultRequestExceptionHandler contextFormer = new DefaultRequestExceptionHandler(null, null, null, null, null, null,
-			null, null, null, null);
+public class DefaultRequestExceptionHandlerTest extends InternalBaseTestCase {
+    private Map<Class, Object> mockConfiguration = new HashMap<Class, Object>();
+    RequestPageCache pageCache = mockRequestPageCache();
+    PageResponseRenderer renderer = mockPageResponseRenderer();
+    Logger logger = mockLogger();
+    Request request = mockRequest();
+    Response response = mockResponse();
+    ComponentClassResolver componentClassResolver = mockComponentClassResolver();
+    LinkSource linkSource = mockLinkSource();
+	private DefaultRequestExceptionHandler exceptionHandler = new DefaultRequestExceptionHandler(pageCache, renderer, logger, "exceptionpage", request, response, componentClassResolver, linkSource, mockConfiguration);
 
 	private static class MyContextAwareException extends Throwable implements ContextAwareException {
 		private Object[] context;
@@ -23,17 +42,28 @@ public class DefaultRequestExceptionHand
 		}
 
 	}
+	
+	private static class MyPage {
+	    
+	}
+	
+    @BeforeClass
+    public void setup_tests() throws Exception
+    {
+        mockConfiguration.clear();
+    }
+	
 
 	@Test
 	public void noContextWhenExceptionDoesntContainMessage() {
-		Object[] context = contextFormer.formExceptionContext(new RuntimeException() {
+		Object[] context = exceptionHandler.formExceptionContext(new RuntimeException() {
 		});
 		assertEquals(context.length, 0);
 	}
 
 	@Test
 	public void contextIsExceptionMessage() {
-		Object[] context = contextFormer.formExceptionContext(new RuntimeException() {
+		Object[] context = exceptionHandler.formExceptionContext(new RuntimeException() {
 			public String getMessage() {
 				return "HelloWorld";
 			}
@@ -44,7 +74,7 @@ public class DefaultRequestExceptionHand
 
 	@Test
 	public void contextIsExceptionType() {
-		Object[] context = contextFormer.formExceptionContext(new IllegalArgumentException("Value not allowed"));
+		Object[] context = exceptionHandler.formExceptionContext(new IllegalArgumentException("Value not allowed"));
 		assertEquals(context.length, 1);
 		assertTrue(context[0] instanceof String);
 		assertTrue("illegalargument".equals(context[0]));
@@ -54,9 +84,41 @@ public class DefaultRequestExceptionHand
 	public void contextIsProvidedByContextAwareException() {
 		Object[] sourceContext = new Object[] { new Integer(10), this };
 
-		Object[] context = contextFormer.formExceptionContext(new MyContextAwareException(sourceContext) {
+		Object[] context = exceptionHandler.formExceptionContext(new MyContextAwareException(sourceContext) {
 		});
 		assertEquals(context, sourceContext);
 
 	}
+	
+	@Test
+	public void handleRequestExceptionWithConfiguredPage() throws IOException {
+	    mockConfiguration.put(AccessControlException.class, MyPage.class);
+	    train_resolvePageClassNameToPageName(componentClassResolver, MyPage.class.getName(), "mypage" );
+	    Link link = mockLink();
+        expect(linkSource.createPageRenderLink("mypage", false, new Object[]{"accesscontrol"})).andReturn(link);
+        expect(request.isXHR()).andReturn(false);
+        response.sendRedirect(link);
+        EasyMock.expectLastCall();
+        replay();
+	    
+	    exceptionHandler.handleRequestException(new AccessControlException("No permission"));
+	}
+	
+    @Test
+    public void handleRequestExceptionWithConfiguredAssistant() throws IOException {
+        ExceptionHandlerAssistant assistant = new ExceptionHandlerAssistant() {
+            @Override
+            public Object handleRequestException(Throwable exception, List<Object> exceptionContext)
+                    throws IOException
+            {
+                return null;
+            }
+        };
+        
+        mockConfiguration.put(MyContextAwareException.class, assistant);
+        replay();
+        
+        exceptionHandler.handleRequestException(new MyContextAwareException(new Object[]{}));
+    }
+	
 }