📄 invoker.java
字号:
/* $Id: Invoker.java,v 1.89 2006/06/15 23:08:14 blackdrag Exp $ Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain copyright statements and notices. Redistributions must also contain a copy of this document. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name "groovy" must not be used to endorse or promote products derived from this Software without prior written permission of The Codehaus. For written permission, please contact info@codehaus.org. 4. Products derived from this Software may not be called "groovy" nor may "groovy" appear in their names without prior written permission of The Codehaus. "groovy" is a registered trademark of The Codehaus. 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/ THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package org.codehaus.groovy.runtime;import groovy.lang.Closure;import groovy.lang.GString;import groovy.lang.GroovyObject;import groovy.lang.GroovyRuntimeException;import groovy.lang.MetaClass;import groovy.lang.MetaClassRegistry;import groovy.lang.MissingMethodException;import groovy.lang.Range;import groovy.lang.SpreadList;import groovy.lang.Tuple;import groovy.lang.GroovyInterceptable;import org.apache.xml.serialize.OutputFormat;import org.apache.xml.serialize.XMLSerializer;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import java.io.File;import java.io.IOException;import java.io.StringWriter;import java.lang.reflect.Array;import java.lang.reflect.Method;import java.math.BigDecimal;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Collections;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.NoSuchElementException;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * A helper class to invoke methods or extract properties on arbitrary Java objects dynamically * * @author <a href="mailto:james@coredevelopers.net">James Strachan</a> * @version $Revision: 1.89 $ */public class Invoker { protected static final Object[] EMPTY_ARGUMENTS = { }; protected static final Class[] EMPTY_TYPES = { }; public MetaClassRegistry getMetaRegistry() { return metaRegistry; } private MetaClassRegistry metaRegistry = new MetaClassRegistry(); public MetaClass getMetaClass(Object object) { return metaRegistry.getMetaClass(object.getClass()); } /** * Invokes the given method on the object. * * @param object * @param methodName * @param arguments * @return */ public Object invokeMethod(Object object, String methodName, Object arguments) { /* System .out .println( "Invoker - Invoking method on object: " + object + " method: " + methodName + " arguments: " + InvokerHelper.toString(arguments)); */ if (object == null) { object = NullObject.getNullObject(); //throw new NullPointerException("Cannot invoke method " + methodName + "() on null object"); } // if the object is a Class, call a static method from that class if (object instanceof Class) { Class theClass = (Class) object; MetaClass metaClass = metaRegistry.getMetaClass(theClass); return metaClass.invokeStaticMethod(object, methodName, asArray(arguments)); } else // it's an instance { // if it's not an object implementing GroovyObject (thus not builder, nor a closure) if (!(object instanceof GroovyObject)) { Class theClass = object.getClass(); MetaClass metaClass = metaRegistry.getMetaClass(theClass); return metaClass.invokeMethod(object, methodName, asArray(arguments)); } // it's an object implementing GroovyObject else { GroovyObject groovy = (GroovyObject) object; try { // if it's a pure interceptable object (even intercepting toString(), clone(), ...) if (groovy instanceof GroovyInterceptable) { return groovy.invokeMethod(methodName, asArray(arguments)); } //else if there's a statically typed method or a GDK method else { return groovy.getMetaClass().invokeMethod(object, methodName, asArray(arguments)); } } catch (MissingMethodException e) { if (e.getMethod().equals(methodName) && object.getClass() == e.getType()) { // in case there's nothing else, invoke the object's own invokeMethod() return groovy.invokeMethod(methodName, asArray(arguments)); } else { throw e; } } } } } public Object invokeSuperMethod(Object object, String methodName, Object arguments) { if (object == null) { throw new NullPointerException("Cannot invoke method " + methodName + "() on null object"); } Class theClass = object.getClass(); MetaClass metaClass = metaRegistry.getMetaClass(theClass.getSuperclass()); return metaClass.invokeMethod(object, methodName, asArray(arguments)); } public Object invokeStaticMethod(String type, String method, Object arguments) { MetaClass metaClass = metaRegistry.getMetaClass(loadClass(type)); List argumentList = asList(arguments); return metaClass.invokeStaticMethod(null, method, asArray(arguments)); } public Object invokeConstructorAt(Class at, Class type, Object arguments) { MetaClass metaClass = metaRegistry.getMetaClass(type); return metaClass.invokeConstructorAt(at, asArray(arguments)); } public Object invokeConstructorAt(Class at, String type, Object arguments) { return invokeConstructorAt(at, loadClass(type), arguments); } public Object invokeConstructorOf(Class type, Object arguments) { MetaClass metaClass = metaRegistry.getMetaClass(type); return metaClass.invokeConstructor(asArray(arguments)); } public Object invokeConstructorOf(String type, Object arguments) { return invokeConstructorOf(loadClass(type), arguments); } /** * Converts the given object into an array; if its an array then just * cast otherwise wrap it in an array */ public Object[] asArray(Object arguments) { if (arguments == null) { return EMPTY_ARGUMENTS; } else if ((arguments instanceof Object[]) && ((Object[]) arguments).length == 0) { return (Object[]) arguments; } else if (arguments instanceof Tuple) { Tuple tuple = (Tuple) arguments; Object[] objects = tuple.toArray(); ArrayList array = new ArrayList(); for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof SpreadList) { SpreadList slist = (SpreadList) objects[i]; for (int j = 0; j < slist.size(); j++) { array.add(slist.get(j)); } } else { array.add(objects[i]); } } return array.toArray(); } else if (arguments instanceof Object[]) { Object[] objects = (Object[]) arguments; ArrayList array = new ArrayList(); for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof SpreadList) { SpreadList slist = (SpreadList) objects[i]; for (int j = 0; j < slist.size(); j++) { array.add(slist.get(j)); } } else { array.add(objects[i]); } } return array.toArray(); } else if (arguments instanceof SpreadList) { ArrayList array = new ArrayList(); SpreadList slist = (SpreadList) arguments; for (int j = 0; j < slist.size(); j++) { array.add(slist.get(j)); } return array.toArray(); } else { return new Object[]{arguments}; } } public List asList(Object value) { if (value == null) { return Collections.EMPTY_LIST; } else if (value instanceof List) { return (List) value; } else if (value.getClass().isArray()) { return Arrays.asList((Object[]) value); } else if (value instanceof Enumeration) { List answer = new ArrayList(); for (Enumeration e = (Enumeration) value; e.hasMoreElements();) { answer.add(e.nextElement()); } return answer; } else { // lets assume its a collection of 1 return Collections.singletonList(value); } } /** * Converts the value parameter into a <code>Collection</code>. * * @param value value to convert * @return a Collection */ public Collection asCollection(Object value) { if (value == null) { return Collections.EMPTY_LIST; } else if (value instanceof Collection) { return (Collection) value; } else if (value instanceof Map) { Map map = (Map) value; return map.entrySet(); } else if (value.getClass().isArray()) { if (value.getClass().getComponentType().isPrimitive()) { return InvokerHelper.primitiveArrayToList(value); } return Arrays.asList((Object[]) value); } else if (value instanceof MethodClosure) { MethodClosure method = (MethodClosure) value; IteratorClosureAdapter adapter = new IteratorClosureAdapter(method.getDelegate()); method.call(adapter); return adapter.asList(); } else if (value instanceof String) { return DefaultGroovyMethods.toList((String) value); } else if (value instanceof File) { try { return DefaultGroovyMethods.readLines((File) value); } catch (IOException e) { throw new GroovyRuntimeException("Error reading file: " + value, e); } } else { // lets assume its a collection of 1 return Collections.singletonList(value); } } public Iterator asIterator(Object value) { if (value == null) { return Collections.EMPTY_LIST.iterator(); } if (value instanceof Iterator) { return (Iterator) value; } if (value instanceof NodeList) { final NodeList nodeList = (NodeList) value; return new Iterator() { private int current = 0; public boolean hasNext() { return current < nodeList.getLength(); } public Object next() { Node node = nodeList.item(current++); return node; } public void remove() { throw new UnsupportedOperationException("Cannot remove() from an Enumeration"); } }; } else if (value instanceof Enumeration) { final Enumeration enumeration = (Enumeration) value; return new Iterator() { private Object last; public boolean hasNext() { return enumeration.hasMoreElements(); } public Object next() { last = enumeration.nextElement(); return last; } public void remove() { throw new UnsupportedOperationException("Cannot remove() from an Enumeration"); } }; } else if (value instanceof Matcher) { final Matcher matcher = (Matcher) value; return new Iterator() { private boolean found = false; private boolean done = false; public boolean hasNext() { if (done) { return false; } if (!found) { found = matcher.find(); if (!found) { done = true; } } return found; } public Object next() { if (!found) { if (!hasNext()) { throw new NoSuchElementException(); } } found = false; return matcher.group(); } public void remove() { throw new UnsupportedOperationException(); } }; } else { try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -