You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/09/23 19:47:40 UTC
svn commit: r1174916 - in /tapestry/tapestry5/trunk:
tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/
tapestry-core/src/main/java/org/apache/tapestry5/internal/services/
tapestry-core/src/test/java/org/apache/tapestry5/internal/serv...
Author: hlship
Date: Fri Sep 23 17:47:40 2011
New Revision: 1174916
URL: http://svn.apache.org/viewvc?rev=1174916&view=rev
Log:
TAP5-1369: ExceptionUtils.findCause() does not use the same approach as ExceptionAnalyzer
Added:
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionWrapper.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidationSupportImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidationSupportImplTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/util/ExceptionUtils.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionUtilsTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java?rev=1174916&r1=1174915&r2=1174916&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java Fri Sep 23 17:47:40 2011
@@ -31,6 +31,7 @@ import org.apache.tapestry5.ioc.annotati
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.ioc.util.ExceptionUtils;
import org.apache.tapestry5.ioc.util.IdAllocator;
import org.apache.tapestry5.json.JSONArray;
@@ -244,6 +245,9 @@ public class Form implements ClientEleme
@Inject
private ClientDataEncoder clientDataEncoder;
+ @Inject
+ private PropertyAccess propertyAccess;
+
private String clientId;
// Set during rendering or submit processing to be the
@@ -603,7 +607,7 @@ public class Form implements ClientEleme
resources.triggerContextEvent(eventName, context, callback);
} catch (RuntimeException ex)
{
- ValidationException ve = ExceptionUtils.findCause(ex, ValidationException.class);
+ ValidationException ve = ExceptionUtils.findCause(ex, ValidationException.class, propertyAccess);
if (ve != null)
{
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidationSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidationSupportImpl.java?rev=1174916&r1=1174915&r2=1174916&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidationSupportImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidationSupportImpl.java Fri Sep 23 17:47:40 2011
@@ -14,17 +14,11 @@
package org.apache.tapestry5.internal.services;
-import org.apache.tapestry5.ComponentEventCallback;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventConstants;
-import org.apache.tapestry5.FieldTranslator;
-import org.apache.tapestry5.FieldValidationSupport;
-import org.apache.tapestry5.FieldValidator;
-import org.apache.tapestry5.NullFieldStrategy;
-import org.apache.tapestry5.ValidationException;
+import org.apache.tapestry5.*;
import org.apache.tapestry5.corelib.internal.InternalMessages;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.ioc.util.ExceptionUtils;
@@ -33,13 +27,16 @@ public class FieldValidationSupportImpl
{
private final TypeCoercer typeCoercer;
- public FieldValidationSupportImpl(TypeCoercer typeCoercer)
+ private final PropertyAccess propertyAccess;
+
+ public FieldValidationSupportImpl(TypeCoercer typeCoercer, PropertyAccess propertyAccess)
{
this.typeCoercer = typeCoercer;
+ this.propertyAccess = propertyAccess;
}
public String toClient(Object value, ComponentResources componentResources, FieldTranslator<Object> translator,
- NullFieldStrategy nullFieldStrategy)
+ NullFieldStrategy nullFieldStrategy)
{
assert componentResources != null;
assert translator != null;
@@ -63,7 +60,7 @@ public class FieldValidationSupportImpl
};
componentResources.triggerEvent(EventConstants.TO_CLIENT, new Object[]
- { value }, callback);
+ {value}, callback);
if (resultHolder.hasValue())
return resultHolder.get();
@@ -89,7 +86,7 @@ public class FieldValidationSupportImpl
}
public Object parseClient(String clientValue, ComponentResources componentResources,
- FieldTranslator<Object> translator, NullFieldStrategy nullFieldStrategy) throws ValidationException
+ FieldTranslator<Object> translator, NullFieldStrategy nullFieldStrategy) throws ValidationException
{
assert componentResources != null;
assert translator != null;
@@ -118,9 +115,8 @@ public class FieldValidationSupportImpl
try
{
componentResources.triggerEvent(EventConstants.PARSE_CLIENT, new Object[]
- { effectiveValue }, callback);
- }
- catch (RuntimeException ex)
+ {effectiveValue}, callback);
+ } catch (RuntimeException ex)
{
rethrowValidationException(ex);
}
@@ -134,15 +130,13 @@ public class FieldValidationSupportImpl
/**
* Checks for a {@link org.apache.tapestry5.ValidationException} inside the outer exception and throws that,
* otherwise rethrows the runtime exception.
- *
- * @param outerException
- * initially caught exception
- * @throws ValidationException
- * if found
+ *
+ * @param outerException initially caught exception
+ * @throws ValidationException if found
*/
private void rethrowValidationException(RuntimeException outerException) throws ValidationException
{
- ValidationException ve = ExceptionUtils.findCause(outerException, ValidationException.class);
+ ValidationException ve = ExceptionUtils.findCause(outerException, ValidationException.class, propertyAccess);
if (ve != null)
throw ve;
@@ -151,7 +145,7 @@ public class FieldValidationSupportImpl
}
@SuppressWarnings(
- { "unchecked" })
+ {"unchecked"})
public void validate(Object value, ComponentResources componentResources, FieldValidator validator)
throws ValidationException
{
@@ -162,9 +156,8 @@ public class FieldValidationSupportImpl
try
{
componentResources.triggerEvent(EventConstants.VALIDATE, new Object[]
- { value }, null);
- }
- catch (RuntimeException ex)
+ {value}, null);
+ } catch (RuntimeException ex)
{
rethrowValidationException(ex);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidationSupportImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidationSupportImplTest.java?rev=1174916&r1=1174915&r2=1174916&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidationSupportImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidationSupportImplTest.java Fri Sep 23 17:47:40 2011
@@ -14,32 +14,29 @@
package org.apache.tapestry5.internal.services;
-import static org.easymock.EasyMock.eq;
-
-import org.apache.tapestry5.ComponentEventCallback;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventConstants;
-import org.apache.tapestry5.FieldTranslator;
-import org.apache.tapestry5.FieldValidationSupport;
-import org.apache.tapestry5.FieldValidator;
-import org.apache.tapestry5.NullFieldStrategy;
-import org.apache.tapestry5.ValidationException;
+import org.apache.tapestry5.*;
import org.apache.tapestry5.corelib.internal.InternalMessages;
import org.apache.tapestry5.internal.test.InternalBaseTestCase;
+import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import static org.easymock.EasyMock.eq;
+
public class FieldValidationSupportImplTest extends InternalBaseTestCase
{
private TypeCoercer typeCoercer;
+ private PropertyAccess propertyAccess;
+
@BeforeClass
public void setup()
{
typeCoercer = getService(TypeCoercer.class);
+ propertyAccess = getService(PropertyAccess.class);
}
@@ -69,14 +66,14 @@ public class FieldValidationSupportImplT
};
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.PARSE_CLIENT),
- EasyMock.isA(Object[].class),
- EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
Object actual = support.parseClient(clientValue, resources, translator, nullFieldStrategy);
@@ -102,7 +99,7 @@ public class FieldValidationSupportImplT
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
Object actual = support.parseClient(clientValue, resources, translator, nullFieldStrategy);
@@ -114,8 +111,8 @@ public class FieldValidationSupportImplT
private void ignoreEvent(ComponentResources resources, String event, Object... context)
{
EasyMock.expect(resources.triggerEvent(EasyMock.eq(event),
- EasyMock.aryEq(context),
- EasyMock.isA(ComponentEventCallback.class))).andReturn(false);
+ EasyMock.aryEq(context),
+ EasyMock.isA(ComponentEventCallback.class))).andReturn(false);
}
protected final void train_replaceFromClient(NullFieldStrategy nullFieldStrategy, String value)
@@ -135,22 +132,21 @@ public class FieldValidationSupportImplT
String clientValue = "abracadabra";
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.PARSE_CLIENT),
- EasyMock.isA(Object[].class),
- EasyMock.isA(ComponentEventCallback.class))).andThrow(
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventCallback.class))).andThrow(
new RuntimeException(ve));
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
try
{
support.parseClient(clientValue, resources, translator, nullFieldStrategy);
unreachable();
- }
- catch (ValidationException ex)
+ } catch (ValidationException ex)
{
assertSame(ex, ve);
}
@@ -172,21 +168,20 @@ public class FieldValidationSupportImplT
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.PARSE_CLIENT),
- EasyMock.isA(Object[].class),
- EasyMock.isA(ComponentEventCallback.class))).andThrow(re);
+ EasyMock.isA(Object[].class),
+ EasyMock.isA(ComponentEventCallback.class))).andThrow(re);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
try
{
support.parseClient(clientValue, resources, translator, nullFieldStrategy);
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertSame(ex, re);
}
@@ -210,7 +205,7 @@ public class FieldValidationSupportImplT
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
Object actual = support.parseClient(clientValue, resources, translator, nullFieldStrategy);
@@ -233,14 +228,14 @@ public class FieldValidationSupportImplT
String clientValue = "abracadabra";
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.TO_CLIENT),
- EasyMock.aryEq(new Object[] {value}),
- EasyMock.isA(ComponentEventCallback.class))).andReturn(false);
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventCallback.class))).andReturn(false);
expect(translator.toClient(value)).andReturn(clientValue);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
String actual = support.toClient(value, resources, translator, nullFieldStrategy);
@@ -273,13 +268,13 @@ public class FieldValidationSupportImplT
};
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.TO_CLIENT),
- EasyMock.aryEq(new Object[] {value}),
- EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(null);
+ FieldValidationSupport support = new FieldValidationSupportImpl(null, propertyAccess);
String actual = support.toClient(value, resources, translator, nullFieldStrategy);
@@ -310,13 +305,13 @@ public class FieldValidationSupportImplT
};
EasyMock.expect(resources.triggerEvent(EasyMock.eq(EventConstants.TO_CLIENT),
- EasyMock.aryEq(new Object[] {value}),
- EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
+ EasyMock.aryEq(new Object[]{value}),
+ EasyMock.isA(ComponentEventCallback.class))).andAnswer(answer);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(null);
+ FieldValidationSupport support = new FieldValidationSupportImpl(null, propertyAccess);
try
{
@@ -324,8 +319,7 @@ public class FieldValidationSupportImplT
support.toClient(value, resources, translator, null);
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertEquals(ex.getMessage(), InternalMessages.toClientShouldReturnString());
}
@@ -349,12 +343,12 @@ public class FieldValidationSupportImplT
ComponentEventCallback handler = null;
expect(resources.triggerEvent(EasyMock.eq(EventConstants.VALIDATE),
- EasyMock.aryEq(new Object[] {value}), EasyMock.eq(handler))).andReturn(true);
+ EasyMock.aryEq(new Object[]{value}), EasyMock.eq(handler))).andReturn(true);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
support.validate(value, resources, fv);
@@ -378,20 +372,19 @@ public class FieldValidationSupportImplT
fv.validate(value);
expect(resources.triggerEvent(eq(EventConstants.VALIDATE),
- EasyMock.aryEq(new Object[] {value}), eq(handler))).andThrow(re);
+ EasyMock.aryEq(new Object[]{value}), eq(handler))).andThrow(re);
replay();
- FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer);
+ FieldValidationSupport support = new FieldValidationSupportImpl(typeCoercer, propertyAccess);
try
{
support.validate(value, resources, fv);
unreachable();
- }
- catch (ValidationException ex)
+ } catch (ValidationException ex)
{
assertSame(ex, ve);
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/util/ExceptionUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/util/ExceptionUtils.java?rev=1174916&r1=1174915&r2=1174916&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/util/ExceptionUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/util/ExceptionUtils.java Fri Sep 23 17:47:40 2011
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,6 +14,9 @@
package org.apache.tapestry5.ioc.util;
+import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
+import org.apache.tapestry5.ioc.services.PropertyAccess;
+
/**
* Contains static methods useful for manipulating exceptions.
*/
@@ -33,7 +36,10 @@ public class ExceptionUtils
while (current != null)
{
- if (type.isInstance(current)) return type.cast(current);
+ if (type.isInstance(current))
+ {
+ return type.cast(current);
+ }
// Not a match, work down.
@@ -42,4 +48,48 @@ public class ExceptionUtils
return null;
}
+
+ /**
+ * Locates a particular type of exception, working its way down via any property that returns some type of Exception.
+ * This is more expensive, but more accurate, than {@link #findCause(Throwable, Class)} as it works with older exceptions
+ * that do not properly implement the (relatively new) {@linkplain Throwable#getCause() cause property}.
+ *
+ * @param t the outermost exception
+ * @param type the type of exception to search for
+ * @param access used to access properties
+ * @return the first exception of the given type, if found, or null
+ */
+ public static <T extends Throwable> T findCause(Throwable t, Class<T> type, PropertyAccess access)
+ {
+ Throwable current = t;
+
+ while (current != null)
+ {
+ if (type.isInstance(current))
+ {
+ return type.cast(current);
+ }
+
+ Throwable next = null;
+
+ ClassPropertyAdapter adapter = access.getAdapter(current);
+
+ for (String name : adapter.getPropertyNames())
+ {
+
+ Object value = adapter.getPropertyAdapter(name).get(current);
+
+ if (value != null && value != current && value instanceof Throwable)
+ {
+ next = (Throwable) value;
+ break;
+ }
+ }
+
+ current = next;
+ }
+
+
+ return null;
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionUtilsTest.java?rev=1174916&r1=1174915&r2=1174916&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionUtilsTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionUtilsTest.java Fri Sep 23 17:47:40 2011
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,12 +14,16 @@
package org.apache.tapestry5.ioc.util;
+import org.apache.tapestry5.ioc.internal.services.PropertyAccessImpl;
import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.testng.Assert;
import org.testng.annotations.Test;
public class ExceptionUtilsTest extends Assert
{
+ private final PropertyAccess access = new PropertyAccessImpl();
+
@Test
public void find_cause_with_match()
{
@@ -28,6 +32,8 @@ public class ExceptionUtilsTest extends
RuntimeException outer = new RuntimeException(inner);
assertSame(ExceptionUtils.findCause(outer, TapestryException.class), inner);
+ assertSame(ExceptionUtils.findCause(outer, TapestryException.class, access), inner);
+
}
@Test
@@ -36,5 +42,20 @@ public class ExceptionUtilsTest extends
RuntimeException re = new RuntimeException("No cause for you!");
assertNull(ExceptionUtils.findCause(re, TapestryException.class));
+ assertNull(ExceptionUtils.findCause(re, TapestryException.class, access));
}
+
+ @Test
+ public void find_hidden_exception()
+ {
+ RuntimeException inner = new RuntimeException();
+ Exception outer = new ExceptionWrapper(inner);
+
+ // TAP5-1639: The old code can't find inner
+ assertNull(ExceptionUtils.findCause(outer, RuntimeException.class));
+
+ // The new reflection-based code can:
+ assertSame(ExceptionUtils.findCause(outer, RuntimeException.class, access), inner);
+ }
+
}
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionWrapper.java?rev=1174916&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionWrapper.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/util/ExceptionWrapper.java Fri Sep 23 17:47:40 2011
@@ -0,0 +1,31 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// 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.tapestry5.ioc.util;
+
+
+public class ExceptionWrapper extends Exception
+{
+ private final Exception inner;
+
+ public ExceptionWrapper(Exception inner)
+ {
+ this.inner = inner;
+ }
+
+ public Exception getInner()
+ {
+ return inner;
+ }
+}