Package org.apache.tapestry.enhance

Source Code of org.apache.tapestry.enhance.ComponentClassFactory

/* $$ Clover has instrumented this file $$ */// Copyright 2004 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.tapestry.enhance;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.Location;
import org.apache.hivemind.service.ClassFactory;
import org.apache.tapestry.IBinding;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.spec.Direction;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.spec.IParameterSpecification;
import org.apache.tapestry.spec.IPropertySpecification;

/**
* Contains the logic for analyzing and enhancing a single component class. Internally, this class
* makes use of {@link IEnhancedClassFactory}.
*
* @author Howard Lewis Ship
* @since 3.0
*/

public class ComponentClassFactory
{public static com.cortexeb.tools.clover.d __CLOVER_106_0 = com.cortexeb.tools.clover.aq.getRecorder(new char[] {67,58,92,119,111,114,107,115,112,97,99,101,92,106,97,107,97,114,116,97,45,116,97,112,101,115,116,114,121,92,102,114,97,109,101,119,111,114,107,92,116,97,114,103,101,116,92,99,108,111,118,101,114,45,100,98},1096998272901L);
    private static final Log LOG = LogFactory.getLog(ComponentClassFactory.class);

    /**
     * Package prefix used for classes that come out of the java. or javax. packages.
     */
    private static final String ENHANCED_PACKAGE = "org.apache.tapestry.enhanced.";

    /**
     * UID used to generate new class names.
     */
    private static int _uid = 0;

    private EnhancementWorklist _worklist;

    private Map _beanProperties = new HashMap();

    private ClassResolver _resolver;

    private IComponentSpecification _specification;

    private Class _componentClass;

    private ClassFactory _classFactory;

    private JavaClassMapping _classMapping = new JavaClassMapping();

    public ComponentClassFactory(ClassResolver resolver, IComponentSpecification specification,
            Class componentClass, ClassFactory classFactory)
    {try { __CLOVER_106_0.M[588]++;
        __CLOVER_106_0.S[2527]++;_resolver = resolver;
        __CLOVER_106_0.S[2528]++;_specification = specification;
        __CLOVER_106_0.S[2529]++;_componentClass = componentClass;
        __CLOVER_106_0.S[2530]++;_classFactory = classFactory;

        __CLOVER_106_0.S[2531]++;buildBeanProperties();
    } finally { }}

    /**
     * We synchronize this method to, hopefully, prevent multiple threads from introspecting any
     * singe class at one time. The Introspector is not thread safe. Unforunately, PropertyUtils,
     * OGNL, here (and elsewhere?) may attempt to introspect at the same time ... we're safe as long
     * as its not the same class being introspected.
     */
    private synchronized void buildBeanProperties()
    {try { __CLOVER_106_0.M[589]++;
        __CLOVER_106_0.S[2532]++;BeanInfo info = null;

        __CLOVER_106_0.S[2533]++;try
        {
            __CLOVER_106_0.S[2534]++;info = Introspector.getBeanInfo(_componentClass);

        }
        catch (IntrospectionException ex)
        {
            __CLOVER_106_0.S[2535]++;throw new ApplicationRuntimeException(EnhanceMessages.unabelToIntrospectClass(
                    _componentClass,
                    ex), ex);
        }

        __CLOVER_106_0.S[2536]++;PropertyDescriptor[] descriptors = info.getPropertyDescriptors();

        __CLOVER_106_0.S[2537]++;for (int i = 0; (((i < descriptors.length) && (++__CLOVER_106_0.CT[468] != 0)) || (++__CLOVER_106_0.CF[468] == 0)); i++){
        {
            __CLOVER_106_0.S[2538]++;_beanProperties.put(descriptors[i].getName(), descriptors[i]);
        }}
    } finally { }}

    protected PropertyDescriptor getPropertyDescriptor(String name)
    {try { __CLOVER_106_0.M[590]++;
        __CLOVER_106_0.S[2539]++;return (PropertyDescriptor) _beanProperties.get(name);
    } finally { }}

    /**
     * Invokes {@link #scanForEnhancements()}to identify any enhancements needed on the class,
     * returning true if there are any enhancements to be performed.
     */

    public boolean needsEnhancement()
    {try { __CLOVER_106_0.M[591]++;
        __CLOVER_106_0.S[2540]++;scanForEnhancements();

        __CLOVER_106_0.S[2541]++;return _worklist != null && _worklist.hasModifications();
    } finally { }}

    /**
     * @return true if pd is not null and both read/write methods are implemented
     */
    public boolean isImplemented(PropertyDescriptor pd)
    {try { __CLOVER_106_0.M[592]++;
        __CLOVER_106_0.S[2542]++;if ((((pd == null) && (++__CLOVER_106_0.CT[469] != 0)) || (++__CLOVER_106_0.CF[469] == 0))){
            __CLOVER_106_0.S[2543]++;return false;}

        __CLOVER_106_0.S[2544]++;return isImplemented(pd.getReadMethod()) && isImplemented(pd.getWriteMethod());
    } finally { }}

    /**
     * @return true if m is not null and is abstract.
     */
    public boolean isAbstract(Method m)
    {try { __CLOVER_106_0.M[593]++;
        __CLOVER_106_0.S[2545]++;if ((((m == null) && (++__CLOVER_106_0.CT[470] != 0)) || (++__CLOVER_106_0.CF[470] == 0))){
            __CLOVER_106_0.S[2546]++;return false;}

        __CLOVER_106_0.S[2547]++;return Modifier.isAbstract(m.getModifiers());
    } finally { }}

    /**
     * @return true if m is not null and not abstract
     */
    public boolean isImplemented(Method m)
    {try { __CLOVER_106_0.M[594]++;
        __CLOVER_106_0.S[2548]++;if ((((m == null) && (++__CLOVER_106_0.CT[471] != 0)) || (++__CLOVER_106_0.CF[471] == 0))){
            __CLOVER_106_0.S[2549]++;return false;}

        __CLOVER_106_0.S[2550]++;return !Modifier.isAbstract(m.getModifiers());
    } finally { }}

    /**
     * Given a class name, returns the corresponding class. In addition, scalar types, arrays of
     * scalar types, java.lang.Object[] and java.lang.String[] are supported.
     *
     * @param type
     *            to convert to a Class
     * @param location
     *            of the involved specification element (for exception reporting)
     */

    public Class convertPropertyType(String type, Location location)
    {try { __CLOVER_106_0.M[595]++;
        __CLOVER_106_0.S[2551]++;Class result = _classMapping.getType(type);

        __CLOVER_106_0.S[2552]++;if ((((result == null) && (++__CLOVER_106_0.CT[472] != 0)) || (++__CLOVER_106_0.CF[472] == 0))){
        {
            __CLOVER_106_0.S[2553]++;try
            {
                __CLOVER_106_0.S[2554]++;String typeName = JavaTypeUtils.getJVMClassName(type);
                __CLOVER_106_0.S[2555]++;result = _resolver.findClass(typeName);
            }
            catch (Exception ex)
            {
                __CLOVER_106_0.S[2556]++;throw new ApplicationRuntimeException(EnhanceMessages.badPropertyType(type, ex),
                        location, ex);
            }

            __CLOVER_106_0.S[2557]++;_classMapping.recordType(type, result);
        }}

        __CLOVER_106_0.S[2558]++;return result;
    } finally { }}

    private void checkPropertyType(PropertyDescriptor pd, Class propertyType, Location location)
    {try { __CLOVER_106_0.M[596]++;
        __CLOVER_106_0.S[2559]++;if ((((!pd.getPropertyType().equals(propertyType)) && (++__CLOVER_106_0.CT[473] != 0)) || (++__CLOVER_106_0.CF[473] == 0))){
            __CLOVER_106_0.S[2560]++;throw new ApplicationRuntimeException(EnhanceMessages.propertyTypeMismatch(
                    _componentClass,
                    pd.getName(),
                    pd.getPropertyType(),
                    propertyType), location, null);}
    } finally { }}

    /**
     * Checks to see that that class either doesn't provide the property, or does but the
     * accessor(s) are abstract. Returns the name of the read accessor if found, or fabricates an
     * appropriate name (if not). Returns null only if the property does not exist.
     */

    private String findReadMethodName(String propertyName, Class propertyType, Location location)
    {try { __CLOVER_106_0.M[597]++;
        __CLOVER_106_0.S[2561]++;PropertyDescriptor d = getPropertyDescriptor(propertyName);

        __CLOVER_106_0.S[2562]++;if ((((d == null) && (++__CLOVER_106_0.CT[474] != 0)) || (++__CLOVER_106_0.CF[474] == 0))){
            __CLOVER_106_0.S[2563]++;return CreateAccessorUtils.buildMethodName("get", propertyName);}

        __CLOVER_106_0.S[2564]++;checkPropertyType(d, propertyType, location);

        __CLOVER_106_0.S[2565]++;Method write = d.getWriteMethod();
        __CLOVER_106_0.S[2566]++;Method read = d.getReadMethod();

        __CLOVER_106_0.S[2567]++;if ((((isImplemented(write)) && (++__CLOVER_106_0.CT[475] != 0)) || (++__CLOVER_106_0.CF[475] == 0))){
            __CLOVER_106_0.S[2568]++;throw new ApplicationRuntimeException(EnhanceMessages.nonAbstractWrite(write
                    .getDeclaringClass(), propertyName), location, null);}

        __CLOVER_106_0.S[2569]++;if ((((isImplemented(read)) && (++__CLOVER_106_0.CT[476] != 0)) || (++__CLOVER_106_0.CF[476] == 0))){
            __CLOVER_106_0.S[2570]++;throw new ApplicationRuntimeException(EnhanceMessages.nonAbstractRead(read
                    .getDeclaringClass(), propertyName), location, null);}

        __CLOVER_106_0.S[2571]++;if ((((read != null) && (++__CLOVER_106_0.CT[477] != 0)) || (++__CLOVER_106_0.CF[477] == 0))){
            __CLOVER_106_0.S[2572]++;return read.getName();}

        __CLOVER_106_0.S[2573]++;return CreateAccessorUtils.buildMethodName("get", propertyName);
    } finally { }}

    private boolean isMissingProperty(String propertyName)
    {try { __CLOVER_106_0.M[598]++;
        __CLOVER_106_0.S[2574]++;PropertyDescriptor pd = getPropertyDescriptor(propertyName);

        __CLOVER_106_0.S[2575]++;return !isImplemented(pd);
    } finally { }}

    /**
     * Invoked by {@link org.apache.tapestry.enhance.DefaultComponentClassEnhancer}to create an
     * enahanced subclass of the component class. This means creating a default constructor, new
     * fields, and new accessor and mutator methods. Properties are created for connected
     * parameters, for all formal parameters (the binding property), and for all specified
     * parameters (which may be transient or persistent).
     */

    public Class createEnhancedSubclass()
    {try { __CLOVER_106_0.M[599]++;
        __CLOVER_106_0.S[2576]++;EnhancementWorklist worklist = getWorklist();

        __CLOVER_106_0.S[2577]++;String startClassName = _componentClass.getName();
        __CLOVER_106_0.S[2578]++;String subclassName = worklist.getClassName();

        __CLOVER_106_0.S[2579]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_106_0.CT[478] != 0)) || (++__CLOVER_106_0.CF[478] == 0))){
            __CLOVER_106_0.S[2580]++;LOG.debug("Enhancing subclass of " + startClassName + " for "
                    + _specification.getSpecificationLocation());}

        __CLOVER_106_0.S[2581]++;Class result = worklist.createEnhancedSubclass();

        __CLOVER_106_0.S[2582]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_106_0.CT[479] != 0)) || (++__CLOVER_106_0.CF[479] == 0))){
            __CLOVER_106_0.S[2583]++;LOG.debug("Finished creating enhanced class " + subclassName);}

        __CLOVER_106_0.S[2584]++;return result;
    } finally { }}

    /**
     * Invoked by {@link #needsEnhancement()}to find any enhancements that may be needed. Should
     * create an {@link org.apache.tapestry.enhance.IEnhancer}for each one, and add it to the
     * queue.
     */

    private void scanForEnhancements()
    {try { __CLOVER_106_0.M[600]++;
        __CLOVER_106_0.S[2585]++;scanForParameterEnhancements();
        __CLOVER_106_0.S[2586]++;scanForSpecifiedPropertyEnhancements();
    } finally { }}

    /**
     * Invoked by {@link #scanForEnhancements()}to locate any enhancements needed for component
     * parameters (this includes binding properties and connected parameter property).
     */

    private void scanForParameterEnhancements()
    {try { __CLOVER_106_0.M[601]++;
        __CLOVER_106_0.S[2587]++;List names = _specification.getParameterNames();
        __CLOVER_106_0.S[2588]++;int count = names.size();

        __CLOVER_106_0.S[2589]++;for (int i = 0; (((i < count) && (++__CLOVER_106_0.CT[480] != 0)) || (++__CLOVER_106_0.CF[480] == 0)); i++){
        {
            __CLOVER_106_0.S[2590]++;String name = (String) names.get(i);

            __CLOVER_106_0.S[2591]++;IParameterSpecification ps = _specification.getParameter(name);

            __CLOVER_106_0.S[2592]++;scanForBindingProperty(name, ps);

            __CLOVER_106_0.S[2593]++;scanForParameterProperty(name, ps);
        }}

    } finally { }}

    private void scanForSpecifiedPropertyEnhancements()
    {try { __CLOVER_106_0.M[602]++;
        __CLOVER_106_0.S[2594]++;List names = _specification.getPropertySpecificationNames();
        __CLOVER_106_0.S[2595]++;int count = names.size();

        __CLOVER_106_0.S[2596]++;for (int i = 0; (((i < count) && (++__CLOVER_106_0.CT[481] != 0)) || (++__CLOVER_106_0.CF[481] == 0)); i++){
        {
            __CLOVER_106_0.S[2597]++;String name = (String) names.get(i);

            __CLOVER_106_0.S[2598]++;IPropertySpecification ps = _specification.getPropertySpecification(name);

            __CLOVER_106_0.S[2599]++;scanForSpecifiedProperty(ps);
        }}
    } finally { }}

    private void scanForBindingProperty(String parameterName, IParameterSpecification ps)
    {try { __CLOVER_106_0.M[603]++;
        __CLOVER_106_0.S[2600]++;String propertyName = parameterName + Tapestry.PARAMETER_PROPERTY_NAME_SUFFIX;
        __CLOVER_106_0.S[2601]++;PropertyDescriptor pd = getPropertyDescriptor(propertyName);

        // only enhance custom parameter binding properties if they are declared abstract
        __CLOVER_106_0.S[2602]++;if ((((ps.getDirection() == Direction.CUSTOM) && (++__CLOVER_106_0.CT[482] != 0)) || (++__CLOVER_106_0.CF[482] == 0))){
        {
            __CLOVER_106_0.S[2603]++;if ((((pd == null) && (++__CLOVER_106_0.CT[483] != 0)) || (++__CLOVER_106_0.CF[483] == 0))){
                __CLOVER_106_0.S[2604]++;return;}

            __CLOVER_106_0.S[2605]++;if ((((!(isAbstract(pd.getReadMethod()) || isAbstract(pd.getWriteMethod()))) && (++__CLOVER_106_0.CT[484] != 0)) || (++__CLOVER_106_0.CF[484] == 0))){
                __CLOVER_106_0.S[2606]++;return;}
        }}

        __CLOVER_106_0.S[2607]++;if ((((isImplemented(pd)) && (++__CLOVER_106_0.CT[485] != 0)) || (++__CLOVER_106_0.CF[485] == 0))){
            __CLOVER_106_0.S[2608]++;return;}

        __CLOVER_106_0.S[2609]++;IEnhancer enhancer = new CreatePropertyEnhancer(propertyName, IBinding.class);

        __CLOVER_106_0.S[2610]++;addEnhancer(enhancer);
    } finally { }}

    private void scanForParameterProperty(String parameterName, IParameterSpecification ps)
    {try { __CLOVER_106_0.M[604]++;
        __CLOVER_106_0.S[2611]++;Direction direction = ps.getDirection();

        __CLOVER_106_0.S[2612]++;if ((((direction == Direction.CUSTOM) && (++__CLOVER_106_0.CT[486] != 0)) || (++__CLOVER_106_0.CF[486] == 0))){
            __CLOVER_106_0.S[2613]++;return;}

        __CLOVER_106_0.S[2614]++;if ((((direction == Direction.AUTO) && (++__CLOVER_106_0.CT[487] != 0)) || (++__CLOVER_106_0.CF[487] == 0))){
        {
            __CLOVER_106_0.S[2615]++;addAutoParameterEnhancer(parameterName, ps);
            __CLOVER_106_0.S[2616]++;return;
        }}

        __CLOVER_106_0.S[2617]++;String propertyName = ps.getPropertyName();

        // Yes, but does it *need* a property created?

        __CLOVER_106_0.S[2618]++;if ((((!isMissingProperty(propertyName)) && (++__CLOVER_106_0.CT[488] != 0)) || (++__CLOVER_106_0.CF[488] == 0))){
            __CLOVER_106_0.S[2619]++;return;}

        __CLOVER_106_0.S[2620]++;Location location = ps.getLocation();

        __CLOVER_106_0.S[2621]++;Class propertyType = convertPropertyType(ps.getType(), location);

        __CLOVER_106_0.S[2622]++;String readMethodName = findReadMethodName(propertyName, propertyType, location);

        __CLOVER_106_0.S[2623]++;IEnhancer enhancer = new CreatePropertyEnhancer(propertyName, propertyType, readMethodName,
                false);

        __CLOVER_106_0.S[2624]++;addEnhancer(enhancer);
    } finally { }}

    private void addAutoParameterEnhancer(String parameterName, IParameterSpecification ps)
    {try { __CLOVER_106_0.M[605]++;
        __CLOVER_106_0.S[2625]++;Location location = ps.getLocation();
        __CLOVER_106_0.S[2626]++;String propertyName = ps.getPropertyName();

        __CLOVER_106_0.S[2627]++;if ((((!ps.isRequired() && ps.getDefaultValue() == null) && (++__CLOVER_106_0.CT[489] != 0)) || (++__CLOVER_106_0.CF[489] == 0))){
            __CLOVER_106_0.S[2628]++;throw new ApplicationRuntimeException(EnhanceMessages.autoMustBeRequired(propertyName),
                    location, null);}

        __CLOVER_106_0.S[2629]++;Class propertyType = convertPropertyType(ps.getType(), location);

        __CLOVER_106_0.S[2630]++;String readMethodName = findReadMethodName(propertyName, propertyType, location);

        __CLOVER_106_0.S[2631]++;IEnhancer enhancer = new CreateAutoParameterEnhancer(propertyName, parameterName,
                propertyType, readMethodName);

        __CLOVER_106_0.S[2632]++;addEnhancer(enhancer);
    } finally { }}

    private void addEnhancer(IEnhancer eh)
    {try { __CLOVER_106_0.M[606]++;
        __CLOVER_106_0.S[2633]++;if ((((_worklist == null) && (++__CLOVER_106_0.CT[490] != 0)) || (++__CLOVER_106_0.CF[490] == 0))){
        {
            __CLOVER_106_0.S[2634]++;String subclassName = constructEnhancedClassName();

            __CLOVER_106_0.S[2635]++;_worklist = new EnhancementWorklistImpl(subclassName, _componentClass, _resolver,
                    _classFactory);
        }}

        __CLOVER_106_0.S[2636]++;_worklist.addEnhancer(eh);
    } finally { }}

    private String constructEnhancedClassName()
    {try { __CLOVER_106_0.M[607]++;
        __CLOVER_106_0.S[2637]++;String startClassName = _componentClass.getName();

        __CLOVER_106_0.S[2638]++;int lastdot = startClassName.lastIndexOf('.');

        // Get package name, INCLUDING, seperator dot

        __CLOVER_106_0.S[2639]++;String packageName = (((lastdot < 1 ) && (++__CLOVER_106_0.CT[491] != 0)) || (++__CLOVER_106_0.CF[491] == 0))? "" : startClassName.substring(0, lastdot + 1);
        __CLOVER_106_0.S[2640]++;String rawName = startClassName.substring(lastdot + 1);

        // If the new class is located in a 'restricted' package,
        // use a neutral package name

        __CLOVER_106_0.S[2641]++;if ((((packageName.startsWith("java.") || packageName.startsWith("javax.")) && (++__CLOVER_106_0.CT[492] != 0)) || (++__CLOVER_106_0.CF[492] == 0))){
            __CLOVER_106_0.S[2642]++;packageName = ENHANCED_PACKAGE;}

        __CLOVER_106_0.S[2643]++;return packageName + "$" + rawName + "_" + generateUID();
    } finally { }}

    private void scanForSpecifiedProperty(IPropertySpecification ps)
    {try { __CLOVER_106_0.M[608]++;
        __CLOVER_106_0.S[2644]++;String propertyName = ps.getName();
        __CLOVER_106_0.S[2645]++;Location location = ps.getLocation();
        __CLOVER_106_0.S[2646]++;Class propertyType = convertPropertyType(ps.getType(), location);

        __CLOVER_106_0.S[2647]++;PropertyDescriptor pd = getPropertyDescriptor(propertyName);

        __CLOVER_106_0.S[2648]++;if ((((isImplemented(pd)) && (++__CLOVER_106_0.CT[493] != 0)) || (++__CLOVER_106_0.CF[493] == 0))){
        {
            // Make sure the property is at least the right type.

            __CLOVER_106_0.S[2649]++;checkPropertyType(pd, propertyType, location);
            __CLOVER_106_0.S[2650]++;return;
        }}

        __CLOVER_106_0.S[2651]++;String readMethodName = findReadMethodName(propertyName, propertyType, location);

        __CLOVER_106_0.S[2652]++;IEnhancer enhancer = new CreatePropertyEnhancer(propertyName, propertyType, readMethodName,
                ps.isPersistent());

        __CLOVER_106_0.S[2653]++;addEnhancer(enhancer);
    } finally { }}

    public EnhancementWorklist getWorklist()
    {try { __CLOVER_106_0.M[609]++;
        __CLOVER_106_0.S[2654]++;return _worklist;
    } finally { }}

    private static synchronized int generateUID()
    {try { __CLOVER_106_0.M[610]++;
        __CLOVER_106_0.S[2655]++;return _uid++;
    } finally { }}

}
TOP

Related Classes of org.apache.tapestry.enhance.ComponentClassFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.