Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2007, 2008, 2009, 2010 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.internal.services;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.Tree;
import org.apache.tapestry5.PropertyConduit;
import org.apache.tapestry5.internal.antlr.PropertyExpressionLexer;
import org.apache.tapestry5.internal.antlr.PropertyExpressionParser;
import org.apache.tapestry5.internal.util.IntegerRange;
import org.apache.tapestry5.internal.util.MultiKey;
import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.internal.NullAnnotationProvider;
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.*;
import org.apache.tapestry5.ioc.util.AvailableValues;
import org.apache.tapestry5.ioc.util.BodyBuilder;
import org.apache.tapestry5.ioc.util.UnknownValueException;
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.Modifier;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static org.apache.tapestry5.internal.antlr.PropertyExpressionParser.*;
public class PropertyConduitSourceImpl implements PropertyConduitSource, InvalidationListener
{
private static final MethodSignature GET_SIGNATURE = new MethodSignature(Object.class, "get", new Class[]
{ Object.class }, null);
private static final MethodSignature SET_SIGNATURE = new MethodSignature(void.class, "set", new Class[]
{ Object.class, Object.class }, null);
private static final Method RANGE;
private static final Method INVERT;
static
{
try
{
RANGE = BasePropertyConduit.class.getMethod("range", int.class, int.class);
INVERT = BasePropertyConduit.class.getMethod("invert", Object.class);
}
catch (NoSuchMethodException ex)
{
throw new RuntimeException(ex);
}
}
private final AnnotationProvider nullAnnotationProvider = new NullAnnotationProvider();
private static class ConstructorParameter
{
private final String fieldName;
private final Class type;
private final Object value;
ConstructorParameter(String fieldName, Class type, Object value)
{
this.fieldName = fieldName;
this.type = type;
this.value = value;
}
public String getFieldName()
{
return fieldName;
}
public Class getType()
{
return type;
}
public Object getValue()
{
return value;
}
}
/**
* Describes all the gory details of one term (one property or method
* invocation) from within the expression.
*/
private interface ExpressionTermInfo extends AnnotationProvider
{
/**
* The method to invoke to read the property value, or null.
*/
Method getReadMethod();
/**
* The method to invoke to write the property value, or null. Always
* null for method terms (which are inherently
* read-only).
*/
Method getWriteMethod();
/**
* The return type of the method, or the type of the property.
*/
Class getType();
/**
* True if an explicit cast to the return type is needed (typically
* because of generics).
*/
boolean isCastRequired();
/**
* Returns a user-presentable name identifying the property or method
* name.
*/
String getDescription();
/**
* Returns the name of the property, if exists. This is also the name of the public field.
*/
String getPropertyName();
/**
* Returns true if the term is actually a public field.
*/
boolean isField();
/**
* Returns the Field if the term is a public field.
*/
Field getField();
}
/**
* How are null values in intermdiate terms to be handled?
*/
private enum NullHandling
{
/**
* Add code to check for null and throw exception if null.
*/
FORBID,
/**
* Add code to check for null and short-circuit (i.e., the "?."
* safe-dereference operator)
*/
ALLOW,
/**
* Add no null check at all.
*/
IGNORE
}
private class GeneratedTerm
{
final Type type;
final String termReference;
/**
* @param type
* type of variable
* @param termReference
* name of variable, or a constant value
*/
private GeneratedTerm(Type type, String termReference)
{
this.type = type;
this.termReference = termReference;
}
}
private final PropertyAccess access;
private final ClassFactory classFactory;
private final TypeCoercer typeCoercer;
private final StringInterner interner;
/**
* Because of stuff like Hibernate, we sometimes start with a subclass in
* some inaccessible class loader and need to
* work up to a base class from a common class loader.
*/
private final Map classToEffectiveClass = CollectionFactory.newConcurrentMap();
/**
* Keyed on combination of root class and expression.
*/
private final Map cache = CollectionFactory.newConcurrentMap();
private final Invariant invariantAnnotation = new Invariant()
{
public Class annotationType()
{
return Invariant.class;
}
};
private final AnnotationProvider invariantAnnotationProvider = new AnnotationProvider()
{
public T getAnnotation(Class annotationClass)
{
if (annotationClass == Invariant.class)
return annotationClass.cast(invariantAnnotation);
return null;
}
};
private final PropertyConduit literalTrue;
private final PropertyConduit literalFalse;
private final PropertyConduit literalNull;
/**
* Encapsulates the process of building a PropertyConduit instance from an
* expression.
*/
class PropertyConduitBuilder
{
private final Class rootType;
private final ClassFab classFab;
private final String expression;
private final Tree tree;
private Class conduitPropertyType;
private String conduitPropertyName;
private AnnotationProvider annotationProvider = nullAnnotationProvider;
// Used to create unique variable names.
private int variableIndex = 0;
private final List parameters = CollectionFactory.newList();
private final BodyBuilder navBuilder = new BodyBuilder();
PropertyConduitBuilder(Class rootType, String expression, Tree tree)
{
this.rootType = rootType;
this.expression = expression;
this.tree = tree;
String name = ClassFabUtils.generateClassName("PropertyConduit");
this.classFab = classFactory.newClass(name, BasePropertyConduit.class);
}
PropertyConduit createInstance()
{
createAccessors();
Object[] parameters = createConstructor();
Class conduitClass = classFab.createClass();
try
{
return (PropertyConduit) conduitClass.getConstructors()[0].newInstance(parameters);
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
private Object[] createConstructor()
{
List types = CollectionFactory.newList();
// $1, $2, $3, $4, $5 ...
types.add(Class.class);
types.add(String.class);
types.add(AnnotationProvider.class);
types.add(String.class);
types.add(TypeCoercer.class);
List