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

Groovy example source code file (MetaMethod.java)

This example Groovy source code file (MetaMethod.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

cachedclass, cachedclass, class, clonenotsupportedexception, exception, groovyruntimeexception, metamethod, object, object, parameters, reflection, runtimeexception, runtimeexception, string, string

The Groovy MetaMethod.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 org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.reflection.ParameterTypes;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.MetaClassHelper;

import java.lang.reflect.Modifier;

/**
 * Represents a Method on a Java object a little like {@link java.lang.reflect.Method}
 * except without using reflection to invoke the method
 *
 * @author <a href="mailto:james@coredevelopers.net">James Strachan
 * @author Alex Tkachman
 * @version $Revision: 22637 $
 */
public abstract class MetaMethod extends ParameterTypes implements Cloneable {
    private String signature;
    private String mopName;

    public MetaMethod() {
    }

    public MetaMethod(Class [] pt) {
        super (pt);
    }

    public abstract int getModifiers();

    public abstract String getName();

    public abstract Class getReturnType();

    public abstract CachedClass getDeclaringClass();

    public abstract Object invoke(Object object, Object[] arguments);

    /**
     * Checks that the given parameters are valid to call this method
     *
     * @param arguments the arguments to check
     * @throws IllegalArgumentException if the parameters are not valid
     */
    public void checkParameters(Class[] arguments) {
        // lets check that the argument types are valid
        if (!isValidMethod(arguments)) {
            throw new IllegalArgumentException(
                    "Parameters to method: "
                    + getName()
                    + " do not match types: "
                    + InvokerHelper.toString(getParameterTypes())
                    + " for arguments: "
                    + InvokerHelper.toString(arguments));
        }
    }

    public boolean isMethod(MetaMethod method) {
        return getName().equals(method.getName())
            && getModifiers() == method.getModifiers()
            && getReturnType().equals(method.getReturnType())
            && equal(getParameterTypes(), method.getParameterTypes());
    }

    protected static boolean equal(CachedClass[] a, Class[] b) {
        if (a.length == b.length) {
            for (int i = 0, size = a.length; i < size; i++) {
                if (!a[i].getTheClass().equals(b[i])) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    protected static boolean equal(CachedClass[] a, CachedClass[] b) {
        if (a.length == b.length) {
            for (int i = 0, size = a.length; i < size; i++) {
                if (a[i] != b[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    public String toString() {
        return super.toString()
            + "[name: "
            + getName()
            + " params: "
            + InvokerHelper.toString(getParameterTypes())
            + " returns: "
            + getReturnType()
            + " owner: "
            + getDeclaringClass()
            + "]";
    }

    public Object clone() {
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException e) {
            throw new GroovyRuntimeException("This should never happen", e);
        }
    }

    public boolean isStatic() {
        return (getModifiers() & Modifier.STATIC) != 0;
    }

    public boolean isAbstract() {
        return (getModifiers() & Modifier.ABSTRACT) != 0;
    }

    public final boolean isPrivate() {
        return (getModifiers() & Modifier.PRIVATE) != 0;
    }

    public final boolean isProtected() {
        return (getModifiers() & Modifier.PROTECTED) != 0;
    }

    public final boolean isPublic() {
        return (getModifiers() & Modifier.PUBLIC) != 0;
    }

    /**
     * @param method the method to compare against
     * @return true if the given method has the same name, parameters, return type
     * and modifiers but may be defined on another type
     */
    public final boolean isSame(MetaMethod method) {
        return getName().equals(method.getName())
            && compatibleModifiers(getModifiers(), method.getModifiers())
            && getReturnType().equals(method.getReturnType())
            && equal(getParameterTypes(), method.getParameterTypes());
    }

    private static boolean compatibleModifiers(int modifiersA, int modifiersB) {
        int mask = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC | Modifier.STATIC;
        return (modifiersA & mask) == (modifiersB & mask);
    }

    public boolean isCacheable() {
        return true;
    }

    public String getDescriptor() {
        return BytecodeHelper.getMethodDescriptor(getReturnType(), getNativeParameterTypes());
    }

    public synchronized String getSignature() {
        if (signature == null) {
            CachedClass [] parameters = getParameterTypes();
            final String name = getName();
            StringBuffer buf = new StringBuffer(name.length()+parameters.length*10);
            buf.append(getReturnType().getName());
            //
            buf.append(' ');
            buf.append(name);
            buf.append('(');
            for (int i = 0; i < parameters.length; i++) {
                if (i > 0) {
                    buf.append(", ");
                }
                buf.append(parameters[i].getName());
            }
            buf.append(')');
            signature = buf.toString();
        }
        return signature;
    }

    public String getMopName() {
        if (mopName == null) {
          String name = getName();
          CachedClass declaringClass = getDeclaringClass();
          if (Modifier.isPrivate(getModifiers()))
            mopName = new StringBuffer().append("this$").append(declaringClass.getSuperClassDistance()).append("$").append(name).toString();
          else 
            mopName = new StringBuffer().append("super$").append(declaringClass.getSuperClassDistance()).append("$").append(name).toString();
        }
        return mopName;
    }

    public final RuntimeException processDoMethodInvokeException (Exception e, Object object, Object [] argumentArray) {
//        if (e instanceof IllegalArgumentException) {
//            //TODO: test if this is OK with new MOP, should be changed!
//            // we don't want the exception being unwrapped if it is a IllegalArgumentException
//            // but in the case it is for example a IllegalThreadStateException, we want the unwrapping
//            // from the runtime
//            //Note: the reason we want unwrapping sometimes and sometimes not is that the method
//            // invocation tries to invoke the method with and then reacts with type transformation
//            // if the invocation failed here. This is OK for IllegalArgumentException, but it is
//            // possible that a Reflector will be used to execute the call and then an Exception from inside
//            // the method is not wrapped in a InvocationTargetException and we will end here.
//            boolean setReason = e.getClass() != IllegalArgumentException.class || this instanceof org.codehaus.groovy.reflection.GeneratedMetaMethod;
//            return MetaClassHelper.createExceptionText("failed to invoke method: ", this, object, argumentArray, e, setReason);
//        }

        if (e instanceof RuntimeException)
          return (RuntimeException) e;

        return MetaClassHelper.createExceptionText("failed to invoke method: ", this, object, argumentArray, e, true);
    }

    // This method is not final but it should be overloaded very carefully and only by generated methods
    // there is no guarantee that it will be called
    public Object doMethodInvoke(Object object, Object[] argumentArray) {
        argumentArray = coerceArgumentsToClasses(argumentArray);
        try {
            return invoke(object, argumentArray);
        } catch (Exception e) {
            throw processDoMethodInvokeException(e, object, argumentArray);
        }
    }
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy MetaMethod.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.