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:20:38 UTC
svn commit: r1174893 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
Author: hlship
Date: Fri Sep 23 17:20:38 2011
New Revision: 1174893
URL: http://svn.apache.org/viewvc?rev=1174893&view=rev
Log:
TAP5-1555: Property Expression Array Disallows null and this
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java?rev=1174893&r1=1174892&r2=1174893&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java Fri Sep 23 17:20:38 2011
@@ -14,34 +14,6 @@
package org.apache.tapestry5.internal.services;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.DECIMAL;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.DEREF;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.FALSE;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.IDENTIFIER;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.INTEGER;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.INVOKE;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.LIST;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.MAP;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.NOT;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.NULL;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.RANGEOP;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.SAFEDEREF;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.STRING;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.THIS;
-import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.TRUE;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.Tree;
@@ -56,26 +28,28 @@ import org.apache.tapestry5.ioc.internal
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.GenericsUtils;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
-import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
-import org.apache.tapestry5.ioc.services.PropertyAccess;
-import org.apache.tapestry5.ioc.services.PropertyAdapter;
-import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.ioc.services.*;
import org.apache.tapestry5.ioc.util.AvailableValues;
import org.apache.tapestry5.ioc.util.UnknownValueException;
-import org.apache.tapestry5.plastic.Condition;
-import org.apache.tapestry5.plastic.InstructionBuilder;
-import org.apache.tapestry5.plastic.InstructionBuilderCallback;
-import org.apache.tapestry5.plastic.MethodDescription;
-import org.apache.tapestry5.plastic.PlasticClass;
-import org.apache.tapestry5.plastic.PlasticClassTransformer;
-import org.apache.tapestry5.plastic.PlasticField;
-import org.apache.tapestry5.plastic.PlasticMethod;
-import org.apache.tapestry5.plastic.PlasticUtils;
+import org.apache.tapestry5.plastic.*;
import org.apache.tapestry5.services.ComponentLayer;
import org.apache.tapestry5.services.InvalidationListener;
import org.apache.tapestry5.services.PropertyConduitSource;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.*;
+
public class PropertyConduitSourceImpl implements PropertyConduitSource, InvalidationListener
{
static class ConduitMethods
@@ -124,7 +98,7 @@ public class PropertyConduitSourceImpl i
};
private static final String[] SINGLE_OBJECT_ARGUMENT = new String[]
- { Object.class.getName() };
+ {Object.class.getName()};
@SuppressWarnings("unchecked")
private static Method getMethod(Class containingClass, String name, Class... parameterTypes)
@@ -132,8 +106,7 @@ public class PropertyConduitSourceImpl i
try
{
return containingClass.getMethod(name, parameterTypes);
- }
- catch (NoSuchMethodException ex)
+ } catch (NoSuchMethodException ex)
{
throw new IllegalArgumentException(ex);
}
@@ -176,16 +149,20 @@ public class PropertyConduitSourceImpl i
final Class genericType;
- /** Describes the term, for use in error messages. */
+ /**
+ * Describes the term, for use in error messages.
+ */
final String description;
final AnnotationProvider annotationProvider;
- /** Callback that will implement the term. */
+ /**
+ * Callback that will implement the term.
+ */
final InstructionBuilderCallback callback;
Term(Type type, Class genericType, String description, AnnotationProvider annotationProvider,
- InstructionBuilderCallback callback)
+ InstructionBuilderCallback callback)
{
this.type = type;
this.genericType = genericType;
@@ -204,7 +181,9 @@ public class PropertyConduitSourceImpl i
this(type, description, null, callback);
}
- /** Returns a clone of this Term with a new callback. */
+ /**
+ * Returns a clone of this Term with a new callback.
+ */
Term withCallback(InstructionBuilderCallback newCallback)
{
return new Term(type, genericType, description, annotationProvider, newCallback);
@@ -388,8 +367,7 @@ public class PropertyConduitSourceImpl i
if (callbacks.isEmpty())
{
navMethod = getRootMethod;
- }
- else
+ } else
{
navMethod = plasticClass.introducePrivateMethod(PlasticUtils.toTypeName(activeClass), "navigate",
SINGLE_OBJECT_ARGUMENT, null);
@@ -649,8 +627,7 @@ public class PropertyConduitSourceImpl i
}
/**
- * @param node
- * subexpression to invert
+ * @param node subexpression to invert
*/
private void implementNotOpGetter(final Tree node)
{
@@ -685,13 +662,10 @@ public class PropertyConduitSourceImpl i
/**
* Uses the builder to add instructions for a subexpression.
- *
- * @param builder
- * used to add instructions
- * @param activeType
- * type of value on top of the stack when this code will execute, or null if no value on stack
- * @param node
- * defines the expression
+ *
+ * @param builder used to add instructions
+ * @param activeType type of value on top of the stack when this code will execute, or null if no value on stack
+ * @param node defines the expression
* @return the expression type
*/
private Type implementSubexpression(InstructionBuilder builder, Type activeType, Tree node)
@@ -774,9 +748,21 @@ public class PropertyConduitSourceImpl i
return implementNotExpression(builder, node);
+ case THIS:
+
+ invokeGetRootMethod(builder);
+
+ return rootType;
+
+ case NULL:
+
+ builder.loadNull();
+
+ return Void.class;
+
default:
throw unexpectedNodeType(node, TRUE, FALSE, INTEGER, DECIMAL, STRING, DEREF, SAFEDEREF,
- IDENTIFIER, INVOKE, LIST, NOT);
+ IDENTIFIER, INVOKE, LIST, NOT, THIS, NULL);
}
}
}
@@ -842,7 +828,7 @@ public class PropertyConduitSourceImpl i
builder.newInstance(HashMap.class);
builder.dupe().loadConstant(count).invokeConstructor(HashMap.class, int.class);
- for (int i = 0; i < count; i+=2)
+ for (int i = 0; i < count; i += 2)
{
builder.dupe();
@@ -851,7 +837,7 @@ public class PropertyConduitSourceImpl i
boxIfPrimitive(builder, GenericsUtils.asClass(keyType));
//and the value:
- Type valueType = implementSubexpression(builder, null, mapNode.getChild(i+1));
+ Type valueType = implementSubexpression(builder, null, mapNode.getChild(i + 1));
boxIfPrimitive(builder, GenericsUtils.asClass(valueType));
//put the value into the array, then pop off the returned object.
@@ -885,16 +871,12 @@ public class PropertyConduitSourceImpl i
/**
* Invokes a method that may take parameters. The children of the invokeNode are subexpressions
* to be evaluated, and potentially coerced, so that they may be passed to the method.
- *
- * @param builder
- * constructs code
- * @param method
- * method to invoke
- * @param node
- * INVOKE or RANGEOP node
- * @param childOffset
- * offset within the node to the first child expression (1 in an INVOKE node because the
- * first child is the method name, 0 in a RANGEOP node)
+ *
+ * @param builder constructs code
+ * @param method method to invoke
+ * @param node INVOKE or RANGEOP node
+ * @param childOffset offset within the node to the first child expression (1 in an INVOKE node because the
+ * first child is the method name, 0 in a RANGEOP node)
*/
private void invokeMethod(InstructionBuilder builder, Method method, Tree node, int childOffset)
{
@@ -927,8 +909,7 @@ public class PropertyConduitSourceImpl i
if (parameterType.isPrimitive())
{
builder.castOrUnbox(parameterType.getName());
- }
- else
+ } else
{
builder.checkcast(parameterType);
}
@@ -947,7 +928,7 @@ public class PropertyConduitSourceImpl i
/**
* Analyzes a DEREF or SAFEDEREF node, proving back a term that identifies its type and provides a callback to
* peform the dereference.
- *
+ *
* @return a term indicating the type of the expression to this point, and a {@link InstructionBuilderCallback}
* to advance the evaluation of the expression form the previous value to the current
*/
@@ -1062,11 +1043,17 @@ public class PropertyConduitSourceImpl i
// Prefer the accessor over the field
- if (adapter.getReadMethod() != null) { return buildGetterMethodAccessTerm(activeType, propertyName,
- adapter.getReadMethod()); }
+ if (adapter.getReadMethod() != null)
+ {
+ return buildGetterMethodAccessTerm(activeType, propertyName,
+ adapter.getReadMethod());
+ }
- if (adapter.getField() != null) { return buildPublicFieldAccessTerm(activeType, propertyName,
- adapter.getField()); }
+ if (adapter.getField() != null)
+ {
+ return buildPublicFieldAccessTerm(activeType, propertyName,
+ adapter.getField());
+ }
throw new RuntimeException(String.format(
"Property '%s' of class %s is not readable (it has no read accessor method).", adapter.getName(),
@@ -1129,13 +1116,10 @@ public class PropertyConduitSourceImpl i
/**
* Casts the results of a field read or method invocation based on generic information.
- *
- * @param builder
- * used to add instructions
- * @param rawType
- * the simple type (often Object) of the field (or method return type)
- * @param genericType
- * the generic Type, from which parameterizations can be determined
+ *
+ * @param builder used to add instructions
+ * @param rawType the simple type (often Object) of the field (or method return type)
+ * @param genericType the generic Type, from which parameterizations can be determined
*/
private void castToGenericType(InstructionBuilder builder, Class rawType, final Type genericType)
{
@@ -1178,7 +1162,8 @@ public class PropertyConduitSourceImpl i
castToGenericType(builder, method.getReturnType(), genericType);
}
- });
+ }
+ );
}
private Method findMethod(Class activeType, String methodName, int parameterCount)
@@ -1199,8 +1184,7 @@ public class PropertyConduitSourceImpl i
if (searchType != Object.class)
{
searchType = Object.class;
- }
- else
+ } else
{
throw new RuntimeException(String.format("Class %s does not contain a public method named '%s()'.",
activeType.getName(), methodName));
@@ -1234,7 +1218,9 @@ public class PropertyConduitSourceImpl i
return boolean.class;
}
- /** Defer creation of the delegate field unless actually needed. */
+ /**
+ * Defer creation of the delegate field unless actually needed.
+ */
private PlasticField getDelegateField()
{
if (delegateField == null)
@@ -1297,11 +1283,9 @@ public class PropertyConduitSourceImpl i
* conduits for the same
* rootClass/expression, and it will get sorted out when the conduit is
* stored into the cache.
- *
- * @param rootClass
- * class of root object for expression evaluation
- * @param expression
- * expression to be evaluated
+ *
+ * @param rootClass class of root object for expression evaluation
+ * @param expression expression to be evaluated
* @return the conduit
*/
private PropertyConduit build(final Class rootClass, String expression)
@@ -1371,8 +1355,7 @@ public class PropertyConduitSourceImpl i
return proxyFactory.createProxy(InternalPropertyConduit.class,
new PropertyConduitBuilder(rootClass, expression, tree)).newInstance();
- }
- catch (Exception ex)
+ } catch (Exception ex)
{
throw new PropertyExpressionException(String.format("Exception generating conduit for expression '%s': %s",
expression, InternalUtils.toMessage(ex)), expression, ex);
@@ -1420,8 +1403,7 @@ public class PropertyConduitSourceImpl i
try
{
ais = new ANTLRInputStream(is);
- }
- catch (IOException ex)
+ } catch (IOException ex)
{
throw new RuntimeException(ex);
}
@@ -1435,8 +1417,7 @@ public class PropertyConduitSourceImpl i
try
{
return (Tree) parser.start().getTree();
- }
- catch (Exception ex)
+ } catch (Exception ex)
{
throw new RuntimeException(String.format("Error parsing property expression '%s': %s.", expression,
ex.getMessage()), ex);
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java?rev=1174893&r1=1174892&r2=1174893&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java Fri Sep 23 17:20:38 2011
@@ -25,7 +25,6 @@ import org.apache.tapestry5.internal.tes
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.internal.util.IntegerRange;
import org.apache.tapestry5.ioc.internal.services.ClassFactoryImpl;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.services.ClassFab;
import org.apache.tapestry5.ioc.services.ClassFactory;
import org.apache.tapestry5.services.PropertyConduitSource;
@@ -105,8 +104,7 @@ public class PropertyConduitSourceImplTe
{
pc.set(bean, 42);
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertEquals(ex.getMessage(), "Literal values are not updateable.");
}
@@ -122,8 +120,7 @@ public class PropertyConduitSourceImplTe
{
normal.set(bean, 42);
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertEquals(ex.getMessage(), "Literal values are not updateable.");
}
@@ -147,8 +144,7 @@ public class PropertyConduitSourceImplTe
{
normal.get(bean);
unreachable();
- }
- catch (NullPointerException ex)
+ } catch (NullPointerException ex)
{
// Expected.
}
@@ -159,8 +155,7 @@ public class PropertyConduitSourceImplTe
{
normal.set(bean, "Howard");
unreachable();
- }
- catch (NullPointerException ex)
+ } catch (NullPointerException ex)
{
// Expected.
}
@@ -408,7 +403,7 @@ public class PropertyConduitSourceImplTe
bean.type1Field = holder;
bean.type2Field = 5678L;
bean.type2ArrayField = new Long[]
- { 123L, 456L };
+ {123L, 456L};
PropertyConduit conduit = source.create(RealizedParameters.class, "type1property.get().firstName");
assertSame(conduit.get(bean), first);
@@ -465,8 +460,7 @@ public class PropertyConduitSourceImplTe
{
conduit.get(null);
unreachable();
- }
- catch (NullPointerException ex)
+ } catch (NullPointerException ex)
{
assertEquals(ex.getMessage(), "Root object of property expression 'value.get()' is null.");
}
@@ -484,8 +478,7 @@ public class PropertyConduitSourceImplTe
{
conduit.get(bean);
unreachable();
- }
- catch (NullPointerException ex)
+ } catch (NullPointerException ex)
{
assertMessageContains(ex, "Property 'simple' (within property expression 'simple.lastName', of",
") is null.");
@@ -613,9 +606,9 @@ public class PropertyConduitSourceImplTe
EchoBean bean = new EchoBean();
bean.setStoredArray(new Number[][]
- { new Integer[]
- { 1, 2 }, new Double[]
- { 3.0, 4.0 } });
+ {new Integer[]
+ {1, 2}, new Double[]
+ {3.0, 4.0}});
Number[][] array = (Number[][]) conduit.get(bean);
@@ -656,7 +649,7 @@ public class PropertyConduitSourceImplTe
PropertyConduit conduit = source.create(EchoBean.class, "echoMap({ 1: 'one', 2.0: 'two', storedString: stringSource.value })");
EchoBean bean = new EchoBean();
- bean.setStoredString( "3" );
+ bean.setStoredString("3");
bean.setStringSource(new StringSource("three"));
Map m = (Map) conduit.get(bean);
@@ -720,8 +713,7 @@ public class PropertyConduitSourceImplTe
{
source.create(IntegerHolder.class, "getValue(");
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
//note that addition of map support changed how this expression was parsed such that the error is now
//reported at character 8, (, rather than 0: getValue(.
@@ -737,8 +729,7 @@ public class PropertyConduitSourceImplTe
{
source.create(IntegerHolder.class, "fred #");
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertEquals(ex.getMessage(),
"Error parsing property expression 'fred #': Unable to parse input at character position 6.");
@@ -831,4 +822,21 @@ public class PropertyConduitSourceImplTe
assertNotNull(pc.getAnnotation(NonVisual.class));
}
+
+ /**
+ * TAP5-1555
+ */
+ @Test
+ public void this_and_null_inside_array()
+ {
+ PropertyConduit pc = source.create(NonVisualBean.class, "[this, null]");
+
+ Object bean = new NonVisualBean();
+
+ List list = (List) pc.get(bean);
+
+ assertEquals(list.size(), 2);
+ assertSame(list.get(0), bean);
+ assertNull(list.get(1));
+ }
}