ProxyMetaClass.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.codehaus.groovy.grails.commons.metaclass |
![]() |
![]() |
Grails |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/* Copyright 2004-2005 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 c;pWARRANTIES 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.codehaus.groovy.grails.commons.metaclass;
import 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.
*
* This is based on original code by Dierk Koenig, but uses a callback object for thread
* safety and supports not only method interception, but property and constructor
* interception too.
*
* @author Dierk Koenig
* @author Graeme Rocher
*
*/
public class ProxyMetaClass extends MetaClassImpl implements AdaptingMetaClass {
protected MetaClass adaptee = null;
protected Interceptor interceptor = null;
public MetaClass getAdaptee()
{
return adaptee;
}
/**
* @param adaptee the adaptee to set
*/
public void setAdaptee(MetaClass adaptee) {
this.adaptee = adaptee;
}
/**
* convenience factory method for the most usual case.
* @return A new ProxyMetaClass instance
* @param theClass The class to create a ProxyMetaClass for
* @throws java.beans.IntrospectionException When the class canot be introspected
*/
public static ProxyMetaClass getInstance(Class theClass) throws IntrospectionException {
MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry();
MetaClass meta = metaRegistry.getMetaClass(theClass);
ProxyMetaClass pmc = new ProxyMetaClass(metaRegistry, theClass, meta);
pmc.initialize();
return pmc;
}
/**
* @param adaptee the MetaClass to decorate with interceptability
* @param registry The MetaClassRegistry instance
*
* @param theClass The class to apply this ProxyMetaClass to
* @throws java.beans.IntrospectionException Thrown when the class cannot be introspected
*/
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");
}
}
/**
* Use the ProxyMetaClass for the given Closure.
* Cares for balanced register/unregister.
* @param closure piece of code to be executed with registered ProxyMetaClass
*/
public void use(Closure closure){
registry.setMetaClass(theClass, this);
try {
closure.call();
} finally {
registry.setMetaClass(theClass, adaptee);
}
}
/**
* Use the ProxyMetaClass for the given Closure.
* Cares for balanced setting/unsetting ProxyMetaClass.
* @param closure piece of code to be executed with ProxyMetaClass
* @param object The GroovyObject to use this ProxyMetaClass with
*/
public void use(GroovyObject object, Closure closure){
object.setMetaClass(this);
try {
closure.call();
} finally {
object.setMetaClass(adaptee);
}
}
/**
* @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(Class aClass, final Object object, final String methodName, final Object[] arguments, boolean b, boolean b1) {
return doCall(object, methodName, arguments, 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, 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) {
if (null == interceptor) {
return super.invokeConstructor(arguments);
}
if(interceptor instanceof ConstructorInterceptor) {
ConstructorInterceptor ci = (ConstructorInterceptor)interceptor;
InvocationCallback callback = new InvocationCallback();
Object result = ci.beforeConstructor(arguments,callback);
if (!callback.isInvoked()) {
result = super.invokeConstructor(arguments);
}
result = ci.afterConstructor(arguments,result);
return result;
}
return super.invokeConstructor(arguments);
}
// since Java has no Closures...
private interface Callable{
Object call();
}
private Object doCall(Object object, String methodName, Object[] arguments, Callable howToInvoke) {
if (null == interceptor) {
return howToInvoke.call();
}
InvocationCallback callback = new InvocationCallback();
Object result = interceptor.beforeInvoke(object, methodName, arguments,callback);
if (!callback.isInvoked()) {
result = howToInvoke.call();
}
result = interceptor.afterInvoke(object, methodName, arguments, result);
return result;
}
/**
* 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;
InvocationCallback callback = new InvocationCallback();
Object result = pae.beforeGet(object,property,callback);
if (!callback.isInvoked()) {
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;
InvocationCallback callback = new InvocationCallback();
pae.beforeSet(object,property,newValue,callback);
if (!callback.isInvoked()) {
super.setProperty(aClass,object, property,newValue,b,b1);
}
}
else {
super.setProperty(aClass,object, property, newValue,b,b1);
}
}
}
The table below shows all metrics for ProxyMetaClass.java.




