defaultgroovymethods.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,794 行 · 第 1/5 页
JAVA
1,794 行
/*
* $Id: DefaultGroovyMethods.java 4598 2006-12-22 20:21:21Z blackdrag $
*
* 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.*;
import groovy.util.CharsetToolkit;
import groovy.util.ClosureComparator;
import groovy.util.OrderBy;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.NumberMath;
import org.codehaus.groovy.tools.RootLoader;
import org.w3c.dom.NodeList;
/**
* This class defines all the new groovy methods which appear on normal JDK
* classes inside the Groovy environment. Static methods are used with the
* first parameter the destination class.
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
* @author Jeremy Rayner
* @author Sam Pullara
* @author Rod Cope
* @author Guillaume Laforge
* @author John Wilson
* @author Hein Meling
* @author Dierk Koenig
* @author Pilho Kim
* @author Marc Guillemot
* @author Russel Winder
* @author bing ran
* @author Jochen Theodorou
* @version $Revision: 4598 $
*/
public class DefaultGroovyMethods {
private static final Logger LOG = Logger.getLogger(DefaultGroovyMethods.class.getName());
private static final Integer ONE = new Integer(1);
/**
* Identity check. Since == is overridden in Groovy with the meaning of equality
* we need some fallback to check for object identity.
*
* @param self
* @param other
* @return true if self and other are identical, false otherwise
*/
public static boolean is(Object self, Object other) {
return self == other;
}
/**
* Allows the closure to be called for the object reference self
*
* @param self the object to have a closure act upon
* @param closure the closure to call on the object
* @return result of calling the closure
*/
public static Object identity(Object self, Closure closure) {
final Closure clonedClosure = (Closure) closure.clone();
clonedClosure.setDelegate(self);
return clonedClosure.call(self);
}
/**
* Allows the subscript operator to be used to lookup dynamic property values.
* <code>bean[somePropertyNameExpression]</code>. The normal property notation
* of groovy is neater and more concise but only works with compile-time known
* property names.
*
* @param self the object to act upon
*/
public static Object getAt(Object self, String property) {
return InvokerHelper.getProperty(self, property);
}
/**
* Allows the subscript operator to be used to set dynamically named property values.
* <code>bean[somePropertyNameExpression] = foo</code>. The normal property notation
* of groovy is neater and more concise but only works with property names which
* are known at compile time.
*
* @param self the object to act upon
* @param property the name of the property to set
* @param newValue the value to set
*/
public static void putAt(Object self, String property, Object newValue) {
InvokerHelper.setProperty(self, property, newValue);
}
/**
* Generates a detailed dump string of an object showing its class,
* hashCode and fields
*/
public static String dump(Object self) {
if (self == null) {
return "null";
}
StringBuffer buffer = new StringBuffer("<");
Class klass = self.getClass();
buffer.append(klass.getName());
buffer.append("@");
buffer.append(Integer.toHexString(self.hashCode()));
boolean groovyObject = self instanceof GroovyObject;
/*jes this may be rewritten to use the new getProperties() stuff
* but the original pulls out private variables, whereas getProperties()
* does not. What's the real use of dump() here?
*/
while (klass != null) {
Field[] fields = klass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
final Field field = fields[i];
if ((field.getModifiers() & Modifier.STATIC) == 0) {
if (groovyObject && field.getName().equals("metaClass")) {
continue;
}
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
field.setAccessible(true);
return null;
}
});
buffer.append(" ");
buffer.append(field.getName());
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(field.get(self)));
} catch (Exception e) {
buffer.append(e);
}
}
}
klass = klass.getSuperclass();
}
/* here is a different implementation that uses getProperties(). I have left
* it commented out because it returns a slightly different list of properties;
* ie it does not return privates. I don't know what dump() really should be doing,
* although IMO showing private fields is a no-no
*/
/*
List props = getProperties(self);
for(Iterator itr = props.keySet().iterator(); itr.hasNext(); ) {
String propName = itr.next().toString();
// the original skipped this, so I will too
if(pv.getName().equals("metaClass")) continue;
if(pv.getName().equals("class")) continue;
buffer.append(" ");
buffer.append(propName);
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(props.get(propName)));
}
catch (Exception e) {
buffer.append(e);
}
}
*/
buffer.append(">");
return buffer.toString();
}
/**
* Retrieves the list of {@link MetaProperty} objects for 'self' and wraps it
* in a list of {@link PropertyValue} objects that additionally provide
* the value for each property of 'self'.
*
* @param self the receiver object
* @return list of {@link PropertyValue} objects
* @see groovy.util.Expando#getMetaPropertyValues()
*/
public static List getMetaPropertyValues(Object self) {
MetaClass metaClass = InvokerHelper.getMetaClass(self);
List mps = metaClass.getProperties();
List props = new ArrayList(mps.size());
for (Iterator itr = mps.iterator(); itr.hasNext();) {
MetaProperty mp = (MetaProperty) itr.next();
PropertyValue pv = new PropertyValue(self, mp);
props.add(pv);
}
return props;
}
/**
* Convenience method that calls {@link #getMetaPropertyValues(Object)}(self)
* and provides the data in form of simple key/value pairs, i.e. without
* type() information.
*
* @param self the receiver object
* @return meta properties as Map of key/value pairs
*/
public static Map getProperties(Object self) {
List metaProps = getMetaPropertyValues(self);
Map props = new HashMap(metaProps.size());
for (Iterator itr = metaProps.iterator(); itr.hasNext();) {
PropertyValue pv = (PropertyValue) itr.next();
try {
props.put(pv.getName(), pv.getValue());
} catch (Exception e) {
LOG.throwing(self.getClass().getName(), "getProperty(" + pv.getName() + ")", e);
}
}
return props;
}
/**
* Scoped use method
*/
public static void use(Object self, Class categoryClass, Closure closure) {
GroovyCategorySupport.use(categoryClass, closure);
}
/**
* Scoped use method with list of categories
*/
public static void use(Object self, List categoryClassList, Closure closure) {
GroovyCategorySupport.use(categoryClassList, closure);
}
/**
* use() a list of categories, specifying the list as varargs:<br>
* use(CategoryClass1, CategoryClass2) { ... }<br>
* This method prevents the error of forgetting to wrap the the category
* classes in a list.
*
* @param self
* @param array
*/
public static void use(Object self, Object[] array) {
if (array.length < 2)
throw new IllegalArgumentException(
"Expecting at least 2 arguments, a category class and a Closure");
Closure closure;
try {
closure = (Closure) array[array.length - 1];
} catch (ClassCastException e) {
throw new IllegalArgumentException("Expecting a Closure to be the last argument");
}
List list = new ArrayList(array.length - 1);
for (int i = 0; i < array.length - 1; ++i)
list.add(array[i]);
GroovyCategorySupport.use(list, closure);
}
/**
* Print to a console in interactive format
*/
public static void print(Object self, Object value) {
System.out.print(InvokerHelper.toString(value));
}
/**
* Print a linebreak to the standard out.
*/
public static void println(Object self) {
System.out.println();
}
/**
* Print to a console in interactive format along with a newline
*/
public static void println(Object self, Object value) {
System.out.println(InvokerHelper.toString(value));
}
/**
* Printf to a console. Only works with JDK1.5 or later.
*/
public static void printf(Object self, String format, Object[] values) {
if (System.getProperty("java.version").charAt(2) == '5') {
//
// Cannot just do:
//
// System.out.printf(format, values) ;
//
// because this fails to compile on JDK1.4.x and earlier. So until the entire world is using
// JDK1.5 or later then we have to do things by reflection so as to hide the use of printf
// from the compiler. In JDK1.5 you might try:
//
// System.out.getClass().getMethod("printf", String.class, Object[].class).invoke(System.out, format, values) ;
//
// but of course this doesn't work on JDK1.4 as it relies on varargs. argh. So we are
// forced into:
//
try {
System.out.getClass().getMethod("printf", new Class[]{String.class, Object[].class}).invoke(System.out, new Object[]{format, values});
} catch (NoSuchMethodException nsme) {
throw new RuntimeException("getMethod threw a NoSuchMethodException. This is impossible.");
} catch (IllegalAccessException iae) {
throw new RuntimeException("invoke threw a IllegalAccessException. This is impossible.");
} catch (java.lang.reflect.InvocationTargetException ite) {
throw new RuntimeException("invoke threw a InvocationTargetException. This is impossible.");
}
} else {
throw new RuntimeException("printf requires JDK1.5 or later.");
}
}
/**
* Returns a formatted string using the specified format string and
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?