alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (ProxyMetaClass.java)

This example Groovy source code file (ProxyMetaClass.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

bean, callable, callable, closure, interceptor, introspectionexception, javabean, metaclass, metaclass, metaclassimpl, object, object, propertyaccessinterceptor, propertyaccessinterceptor, proxymetaclass, string

The Groovy ProxyMetaClass.java source code

/*
 * Copyright 2003-2007 the original author or authors.
 *
 * 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 groovy.lang;

import java.beans.IntrospectionException;

/**
 * As subclass of MetaClass, ProxyMetaClass manages calls from Groovy Objects to POJOs.
 * It enriches MetaClass with the feature of making method invokations interceptable by
 * an Interceptor. To this end, it acts as a decorator (decorator pattern) allowing
 * to add or withdraw this feature at runtime.
 * See groovy/lang/InterceptorTest.groovy for details.
 * <p/>
 * <p>WARNING: This implementation of ProxyMetaClass is NOT threadsafe and hence should only be used for
 * as a per-instance MetaClass running in a single thread. Do not place this MetaClass in the MetaClassRegistry
 * as it will result in unpredictable behaviour
 *
 * @author Dierk Koenig
 * @author Graeme Rocher
 * @see groovy.lang.MetaClassRegistry
 */
public class ProxyMetaClass extends MetaClassImpl implements AdaptingMetaClass {

    protected MetaClass adaptee = null;
    protected Interceptor interceptor = null;


    /**
     * convenience factory method for the most usual case.
     */
    public static ProxyMetaClass getInstance(Class theClass) throws IntrospectionException {
        MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry();
        MetaClass meta = metaRegistry.getMetaClass(theClass);
        return new ProxyMetaClass(metaRegistry, theClass, meta);
    }

    /**
     * @param adaptee the MetaClass to decorate with interceptability
     */
    public ProxyMetaClass(MetaClassRegistry registry, Class theClass, MetaClass adaptee) throws IntrospectionException {
        super(registry, theClass);
        this.adaptee = adaptee;
        if (null == adaptee) throw new IllegalArgumentException("adaptee must not be null");
        super.initialize();
    }

    public synchronized void initialize() {
        this.adaptee.initialize();
    }

    /**
     * Use the ProxyMetaClass for the given Closure.
     * Cares for balanced register/unregister.
     *
     * @param closure piece of code to be executed with registered ProxyMetaClass
     */
    public Object use(Closure closure) {
        // grab existing meta (usually adaptee but we may have nested use calls)
        MetaClass origMetaClass = registry.getMetaClass(theClass);
        registry.setMetaClass(theClass, this);
        try {
            return closure.call();
        } finally {
            registry.setMetaClass(theClass, origMetaClass);
        }
    }

    /**
     * Use the ProxyMetaClass for the given Closure.
     * Cares for balanced setting/unsetting ProxyMetaClass.
     *
     * @param closure piece of code to be executed with ProxyMetaClass
     */
    public Object use(GroovyObject object, Closure closure) {
        // grab existing meta (usually adaptee but we may have nested use calls)
        MetaClass origMetaClass = object.getMetaClass();
        object.setMetaClass(this);
        try {
            return closure.call();
        } finally {
            object.setMetaClass(origMetaClass);
        }
    }

    /**
     * @return the interceptor in use or null if no interceptor is used
     */
    public Interceptor getInterceptor() {
        return interceptor;
    }

    /**
     * @param interceptor may be null to reset any interception
     */
    public void setInterceptor(Interceptor interceptor) {
        this.interceptor = interceptor;
    }

    /**
     * Call invokeMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
     * The method call is suppressed if Interceptor.doInvoke() returns false.
     * See Interceptor for details.
     */
    public Object invokeMethod(final Object object, final String methodName, final Object[] arguments) {
        return doCall(object, methodName, arguments, interceptor, new Callable() {
            public Object call() {
                return adaptee.invokeMethod(object, methodName, arguments);
            }
        });
    }

    /**
     * Call invokeStaticMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
     * The method call is suppressed if Interceptor.doInvoke() returns false.
     * See Interceptor for details.
     */
    public Object invokeStaticMethod(final Object object, final String methodName, final Object[] arguments) {
        return doCall(object, methodName, arguments, interceptor, new Callable() {
            public Object call() {
                return adaptee.invokeStaticMethod(object, methodName, arguments);
            }
        });
    }

    /**
     * Call invokeConstructor on adaptee with logic like in MetaClass unless we have an Interceptor.
     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
     * The method call is suppressed if Interceptor.doInvoke() returns false.
     * See Interceptor for details.
     */
    public Object invokeConstructor(final Object[] arguments) {
        return doCall(theClass, "ctor", arguments, interceptor, new Callable() {
            public Object call() {
                return adaptee.invokeConstructor(arguments);
            }
        });
    }

    /**
     * Interceptors the call to getProperty if a PropertyAccessInterceptor is
     * available
     *
     * @param object   the object to invoke the getter on
     * @param property the property name
     * @return the value of the property
     */
    public Object getProperty(Class aClass, Object object, String property, boolean b, boolean b1) {
        if (null == interceptor) {
            return super.getProperty(aClass, object, property, b, b1);
        }
        if (interceptor instanceof PropertyAccessInterceptor) {
            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;

            Object result = pae.beforeGet(object, property);
            if (interceptor.doInvoke()) {
                result = super.getProperty(aClass, object, property, b, b1);
            }
            return result;
        }
        return super.getProperty(aClass, object, property, b, b1);
    }

    /**
     * Interceptors the call to a property setter if a PropertyAccessInterceptor
     * is available
     *
     * @param object   The object to invoke the setter on
     * @param property The property name to set
     * @param newValue The new value of the property
     */
    public void setProperty(Class aClass, Object object, String property, Object newValue, boolean b, boolean b1) {
        if (null == interceptor) {
            super.setProperty(aClass, object, property, newValue, b, b1);
        }
        if (interceptor instanceof PropertyAccessInterceptor) {
            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;

            pae.beforeSet(object, property, newValue);
            if (interceptor.doInvoke()) {
                super.setProperty(aClass, object, property, newValue, b, b1);
            }
        } else {
            super.setProperty(aClass, object, property, newValue, b, b1);
        }
    }

    public MetaClass getAdaptee() {
        return this.adaptee;
    }

    public void setAdaptee(MetaClass metaClass) {
        this.adaptee = metaClass;
    }

    // since Java has no Closures...
    private interface Callable {
        Object call();
    }

    private Object doCall(Object object, String methodName, Object[] arguments, Interceptor interceptor, Callable howToInvoke) {
        if (null == interceptor) {
            return howToInvoke.call();
        }
        Object result = interceptor.beforeInvoke(object, methodName, arguments);
        if (interceptor.doInvoke()) {
            result = howToInvoke.call();
        }
        result = interceptor.afterInvoke(object, methodName, arguments, result);
        return result;
    }
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy ProxyMetaClass.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.