You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by cc...@apache.org on 2017/12/17 14:01:19 UTC
[08/62] [abbrv] [partial] groovy git commit: Move Java source set
into `src/main/java`
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
new file mode 100644
index 0000000..e621729
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class contains utility methods to determine which class called the
+ * current class to multiple levels of depth. Calls used to handle the
+ * groovy MOP are excluded from the level counting.
+ */
+public class ReflectionUtils {
+
+ // these are packages in the call stack that are only part of the groovy MOP
+ private static final Set<String> IGNORED_PACKAGES = new HashSet<String>();
+
+ static {
+ //IGNORED_PACKAGES.add("java.lang.reflect");
+ IGNORED_PACKAGES.add("groovy.lang");
+ IGNORED_PACKAGES.add("org.codehaus.groovy.reflection");
+ IGNORED_PACKAGES.add("org.codehaus.groovy.runtime.callsite");
+ IGNORED_PACKAGES.add("org.codehaus.groovy.runtime.metaclass");
+ IGNORED_PACKAGES.add("org.codehaus.groovy.runtime");
+ IGNORED_PACKAGES.add("sun.reflect");
+ IGNORED_PACKAGES.add("java.lang.invoke");
+ IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v7");
+ }
+
+ private static final ClassContextHelper HELPER = new ClassContextHelper();
+
+ /**
+ * Determine whether or not the getCallingClass methods will return
+ * any sensible results. On JVMs that are not Sun derived i.e.
+ * (gcj, Harmony) this will likely return false. When not available
+ * all getCallingClass methods will return null.
+ *
+ * @return true if getCallingClass can return anything but null, false if
+ * it will only return null.
+ */
+ public static boolean isCallingClassReflectionAvailable() {
+ return true;
+ }
+
+ /**
+ * Get the immediate calling class, ignoring MOP frames.
+ *
+ * @return The Class of the caller
+ */
+ public static Class getCallingClass() {
+ return getCallingClass(1);
+ }
+
+ /**
+ * Get the called that is matchLevel stack frames before the call,
+ * ignoring MOP frames.
+ *
+ * @param matchLevel how may call stacks down to look.
+ * If it is less than 1 it is treated as though it was 1.
+ * @return The Class of the matched caller, or null if there aren't
+ * enough stackframes to satisfy matchLevel
+ */
+ public static Class getCallingClass(int matchLevel) {
+ return getCallingClass(matchLevel, Collections.EMPTY_SET);
+ }
+
+ /**
+ * Get the called that is matchLevel stack frames before the call,
+ * ignoring MOP frames and desired exclude packages.
+ *
+ * @param matchLevel how may call stacks down to look.
+ * If it is less than 1 it is treated as though it was 1.
+ * @param extraIgnoredPackages A collection of string names of packages to exclude
+ * in addition to the MOP packages when counting stack frames.
+ * @return The Class of the matched caller, or null if there aren't
+ * enough stackframes to satisfy matchLevel
+ */
+ public static Class getCallingClass(int matchLevel, Collection<String> extraIgnoredPackages) {
+ Class[] classContext = HELPER.getClassContext();
+
+ int depth = 0;
+ try {
+ Class c;
+ // this super class stuff is for Java 1.4 support only
+ // it isn't needed on a 5.0 VM
+ Class sc;
+ do {
+ do {
+ c = classContext[depth++];
+ if (c != null) {
+ sc = c.getSuperclass();
+ } else {
+ sc = null;
+ }
+ } while (classShouldBeIgnored(c, extraIgnoredPackages)
+ || superClassShouldBeIgnored(sc));
+ } while (c != null && matchLevel-- > 0 && depth<classContext.length);
+ return c;
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ private static boolean superClassShouldBeIgnored(Class sc) {
+ return ((sc != null) && (sc.getPackage() != null) && "org.codehaus.groovy.runtime.callsite".equals(sc.getPackage().getName()));
+ }
+
+ private static boolean classShouldBeIgnored(Class c, Collection<String> extraIgnoredPackages) {
+ return ((c != null)
+ && (c.isSynthetic()
+ || (c.getPackage() != null
+ && (IGNORED_PACKAGES.contains(c.getPackage().getName())
+ || extraIgnoredPackages.contains(c.getPackage().getName())))));
+ }
+
+ private static class ClassContextHelper extends SecurityManager {
+ @Override
+ public Class[] getClassContext() {
+ return super.getClassContext();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/SunClassLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/SunClassLoader.java b/src/main/java/org/codehaus/groovy/reflection/SunClassLoader.java
new file mode 100644
index 0000000..0a6a082
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/SunClassLoader.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Special class loader, which when running on Sun VM allows to generate accessor classes for any method
+ */
+public class SunClassLoader extends ClassLoader implements Opcodes {
+ protected final Map<String,Class> knownClasses = new HashMap<String,Class>();
+
+ protected static final SunClassLoader sunVM;
+
+ static {
+ SunClassLoader res;
+ try {
+ res = AccessController.doPrivileged(new PrivilegedAction<SunClassLoader>() {
+ public SunClassLoader run() {
+ try {
+ return new SunClassLoader();
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+ });
+ }
+ catch (Throwable e) {
+ res = null;
+ }
+ sunVM = res;
+ }
+
+ protected SunClassLoader() throws Throwable {
+ super (SunClassLoader.class.getClassLoader());
+
+ final Class magic = ClassLoader.getSystemClassLoader().loadClass("sun.reflect.MagicAccessorImpl");
+ knownClasses.put("sun.reflect.MagicAccessorImpl", magic);
+ loadMagic ();
+ }
+
+ private void loadMagic() {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ cw.visit(Opcodes.V1_4, Opcodes.ACC_PUBLIC, "sun/reflect/GroovyMagic", null, "sun/reflect/MagicAccessorImpl", null);
+ MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "sun/reflect/MagicAccessorImpl", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0,0);
+ mv.visitEnd();
+ cw.visitEnd();
+
+ define(cw.toByteArray(), "sun.reflect.GroovyMagic");
+ }
+
+ protected void loadFromRes(String name) throws IOException {
+ final InputStream asStream = SunClassLoader.class.getClassLoader().getResourceAsStream(resName(name));
+ ClassReader reader = new ClassReader(asStream);
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ reader.accept(cw, ClassWriter.COMPUTE_MAXS);
+ asStream.close();
+ define(cw.toByteArray(), name);
+ }
+
+ protected static String resName(String s) {
+ return s.replace('.','/') + ".class";
+ }
+
+ protected void define(byte[] bytes, final String name) {
+ knownClasses.put(name, defineClass(name, bytes, 0, bytes.length));
+ }
+
+ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ final Class aClass = knownClasses.get(name);
+ if (aClass != null)
+ return aClass;
+ else {
+ try {
+ return super.loadClass(name, resolve);
+ }
+ catch (ClassNotFoundException e) {
+ return getClass().getClassLoader().loadClass(name);
+ }
+ }
+ }
+
+ public Class doesKnow(String name) {
+ return knownClasses.get(name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/android/AndroidSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/android/AndroidSupport.java b/src/main/java/org/codehaus/groovy/reflection/android/AndroidSupport.java
new file mode 100644
index 0000000..67416e9
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/android/AndroidSupport.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.android;
+
+public abstract class AndroidSupport {
+ private static final boolean IS_ANDROID;
+
+ static {
+ boolean isAndroid = true;
+ try {
+ Class.forName("android.app.Activity", false, AndroidSupport.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ isAndroid = false;
+ }
+ IS_ANDROID = isAndroid;
+ }
+
+ public static boolean isRunningAndroid() {
+ return IS_ANDROID;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/package.html b/src/main/java/org/codehaus/groovy/reflection/package.html
new file mode 100644
index 0000000..a01a2dd
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/package.html
@@ -0,0 +1,28 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+-->
+<html>
+ <head>
+ <title>package org.codehaus.groovy.reflection.*</title>
+ </head>
+ <body>
+ <p>Internal classes for assisting with reflection.</p>
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/ArrayCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/ArrayCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ArrayCachedClass.java
new file mode 100644
index 0000000..fcf2908
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ArrayCachedClass.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import groovy.lang.GString;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class ArrayCachedClass extends CachedClass {
+ public ArrayCachedClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo);
+ }
+
+ public Object coerceArgument(Object argument) {
+ Class argumentClass = argument.getClass();
+ if (argumentClass.getName().charAt(0) != '[') return argument;
+ Class argumentComponent = argumentClass.getComponentType();
+
+ Class paramComponent = getTheClass().getComponentType();
+ if (paramComponent.isPrimitive()) {
+ argument = DefaultTypeTransformation.convertToPrimitiveArray(argument, paramComponent);
+ } else if (paramComponent == String.class && argument instanceof GString[]) {
+ GString[] strings = (GString[]) argument;
+ String[] ret = new String[strings.length];
+ for (int i = 0; i < strings.length; i++) {
+ ret[i] = strings[i].toString();
+ }
+ argument = ret;
+ } else if (paramComponent==Object.class && argumentComponent.isPrimitive()){
+ argument = DefaultTypeTransformation.primitiveArrayBox(argument);
+ }
+ return argument;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java
new file mode 100644
index 0000000..45a1c85
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class BigDecimalCachedClass extends DoubleCachedClass {
+ public BigDecimalCachedClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo, true);
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return argument instanceof BigDecimal;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof BigDecimal) {
+ return argument;
+ } else if (argument instanceof Long) {
+ return new BigDecimal((Long) argument);
+ } else if (argument instanceof BigInteger) {
+ return new BigDecimal((BigInteger) argument);
+ }
+
+ if (argument instanceof Number) {
+ return new BigDecimal(((Number) argument).doubleValue());
+ }
+ return argument;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigIntegerCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigIntegerCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigIntegerCachedClass.java
new file mode 100644
index 0000000..573fc42
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BigIntegerCachedClass.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class BigIntegerCachedClass extends NumberCachedClass {
+ public BigIntegerCachedClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo);
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return argument instanceof BigInteger;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return classToTransformFrom == null
+ || classToTransformFrom == Integer.class
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == BigInteger.class
+ || classToTransformFrom == Long.class
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE
+ || classToTransformFrom == Long.TYPE
+ || BigInteger.class.isAssignableFrom(classToTransformFrom);
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/BooleanCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/BooleanCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BooleanCachedClass.java
new file mode 100644
index 0000000..9dacdf4
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/BooleanCachedClass.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class BooleanCachedClass extends CachedClass {
+ private final boolean allowNull;
+ public BooleanCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Boolean;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Boolean.class
+ || classToTransformFrom == Boolean.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/ByteCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/ByteCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ByteCachedClass.java
new file mode 100644
index 0000000..21abd59
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ByteCachedClass.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class ByteCachedClass extends NumberCachedClass {
+ private final boolean allowNull;
+ public ByteCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Byte) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ return ((Number) argument).byteValue();
+ }
+ return argument;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Byte;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == Byte.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedClosureClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedClosureClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedClosureClass.java
new file mode 100644
index 0000000..7dcaed0
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedClosureClass.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.CachedMethod;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+public class CachedClosureClass extends CachedClass {
+ private final Class[] parameterTypes;
+ private final int maximumNumberOfParameters;
+
+ public CachedClosureClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo);
+
+ CachedMethod methods [] = getMethods();
+
+ // set it to -1 for starters so parameterTypes will always get a type
+ int maximumNumberOfParameters = -1;
+ Class[] parameterTypes = null;
+
+ for (CachedMethod method : methods) {
+ if ("doCall".equals(method.getName())) {
+ final Class[] pt = method.getNativeParameterTypes();
+ if (pt.length > maximumNumberOfParameters) {
+ parameterTypes = pt;
+ maximumNumberOfParameters = parameterTypes.length;
+ }
+ }
+ }
+ // this line should be useless, but well, just in case
+ maximumNumberOfParameters = Math.max(maximumNumberOfParameters,0);
+
+ this.maximumNumberOfParameters = maximumNumberOfParameters;
+ this.parameterTypes = parameterTypes;
+ }
+
+ public Class[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ public int getMaximumNumberOfParameters() {
+ return maximumNumberOfParameters;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
new file mode 100644
index 0000000..6364f40
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import groovy.lang.Closure;
+import groovy.util.ProxyGenerator;
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+import org.codehaus.groovy.reflection.ReflectionCache;
+import org.codehaus.groovy.runtime.ConvertedClosure;
+import org.codehaus.groovy.transform.trait.Traits;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+public class CachedSAMClass extends CachedClass {
+
+ private static final int ABSTRACT_STATIC_PRIVATE =
+ Modifier.ABSTRACT|Modifier.PRIVATE|Modifier.STATIC;
+ private static final int VISIBILITY = 5; // public|protected
+ private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
+ private final Method method;
+
+ public CachedSAMClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo);
+ method = getSAMMethod(klazz);
+ if (method==null) throw new GroovyBugError("assigned method should not have been null!");
+ }
+
+ @Override
+ public boolean isAssignableFrom(Class argument) {
+ return argument == null ||
+ Closure.class.isAssignableFrom(argument) ||
+ ReflectionCache.isAssignableFrom(getTheClass(), argument);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Object coerceToSAM(Closure argument, Method method, Class clazz, boolean isInterface) {
+ if (argument!=null && clazz.isAssignableFrom(argument.getClass())) {
+ return argument;
+ }
+ if (isInterface) {
+ if (Traits.isTrait(clazz)) {
+ Map<String,Closure> impl = Collections.singletonMap(
+ method.getName(),
+ argument
+ );
+ return ProxyGenerator.INSTANCE.instantiateAggregate(impl,Collections.singletonList(clazz));
+ }
+ return Proxy.newProxyInstance(
+ clazz.getClassLoader(),
+ new Class[]{clazz},
+ new ConvertedClosure(argument));
+ } else {
+ Map<String, Object> m = new HashMap<String,Object>();
+ m.put(method.getName(), argument);
+ return ProxyGenerator.INSTANCE.
+ instantiateAggregateFromBaseClass(m, clazz);
+ }
+ }
+
+ @Override
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Closure) {
+ Class clazz = getTheClass();
+ return coerceToSAM((Closure) argument, method, clazz, clazz.isInterface());
+ } else {
+ return argument;
+ }
+ }
+
+ private static Method[] getDeclaredMethods(final Class c) {
+ try {
+ Method[] methods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ public Method[] run() {
+ return c.getDeclaredMethods();
+ }
+ });
+ if (methods!=null) return methods;
+ } catch (java.security.AccessControlException ace) {
+ // swallow and do as if no method is available
+ }
+ return EMPTY_METHOD_ARRAY;
+ }
+
+ private static void getAbstractMethods(Class c, List<Method> current) {
+ if (c==null || !Modifier.isAbstract(c.getModifiers())) return;
+ getAbstractMethods(c.getSuperclass(), current);
+ for (Class ci : c.getInterfaces()) {
+ getAbstractMethods(ci, current);
+ }
+ for (Method m : getDeclaredMethods(c)) {
+ if (Modifier.isPrivate(m.getModifiers())) continue;
+ if (Modifier.isAbstract(m.getModifiers())) current.add(m);
+ }
+ }
+
+ private static boolean hasUsableImplementation(Class c, Method m) {
+ if (c==m.getDeclaringClass()) return false;
+ Method found;
+ try {
+ found = c.getMethod(m.getName(), m.getParameterTypes());
+ int asp = found.getModifiers() & ABSTRACT_STATIC_PRIVATE;
+ int visible = found.getModifiers() & VISIBILITY;
+ if (visible !=0 && asp == 0) return true;
+ } catch (NoSuchMethodException e) {/*ignore*/}
+ if (c==Object.class) return false;
+ return hasUsableImplementation(c.getSuperclass(), m);
+ }
+
+ private static Method getSingleNonDuplicateMethod(List<Method> current) {
+ if (current.isEmpty()) return null;
+ if (current.size()==1) return current.get(0);
+ Method m = current.remove(0);
+ for (Method m2 : current) {
+ if (m.getName().equals(m2.getName()) &&
+ Arrays.equals(m.getParameterTypes(), m2.getParameterTypes()))
+ {
+ continue;
+ }
+ return null;
+ }
+ return m;
+ }
+
+ /**
+ * returns the abstract method from a SAM type, if it is a SAM type.
+ * @param c the SAM class
+ * @return null if nothing was found, the method otherwise
+ */
+ public static Method getSAMMethod(Class<?> c) {
+ try {
+ return getSAMMethodImpl(c);
+ } catch (NoClassDefFoundError ignore) {
+ return null;
+ }
+ }
+
+ private static Method getSAMMethodImpl(Class<?> c) {
+ // SAM = single public abstract method
+ // if the class is not abstract there is no abstract method
+ if (!Modifier.isAbstract(c.getModifiers())) return null;
+ if (c.isInterface()) {
+ Method[] methods = c.getMethods();
+ // res stores the first found abstract method
+ Method res = null;
+ for (Method mi : methods) {
+ // ignore methods, that are not abstract and from Object
+ if (!Modifier.isAbstract(mi.getModifiers())) continue;
+ // ignore trait methods which have a default implementation
+ if (mi.getAnnotation(Traits.Implemented.class)!=null) continue;
+ try {
+ Object.class.getMethod(mi.getName(), mi.getParameterTypes());
+ continue;
+ } catch (NoSuchMethodException e) {/*ignore*/}
+
+ // we have two methods, so no SAM
+ if (res!=null) return null;
+ res = mi;
+ }
+ return res;
+
+ } else {
+
+ LinkedList<Method> methods = new LinkedList();
+ getAbstractMethods(c, methods);
+ if (methods.isEmpty()) return null;
+ ListIterator<Method> it = methods.listIterator();
+ while (it.hasNext()) {
+ Method m = it.next();
+ if (hasUsableImplementation(c, m)) it.remove();
+ }
+ return getSingleNonDuplicateMethod(methods);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/CharacterCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/CharacterCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CharacterCachedClass.java
new file mode 100644
index 0000000..619332e
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CharacterCachedClass.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class CharacterCachedClass extends CachedClass {
+ private final boolean allowNull;
+
+ public CharacterCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Character;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Character.class
+ || classToTransformFrom == Character.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/DoubleCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/DoubleCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/DoubleCachedClass.java
new file mode 100644
index 0000000..4a0f5c6
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/DoubleCachedClass.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class DoubleCachedClass extends NumberCachedClass { // Double, double
+ private final boolean allowNull;
+
+ public DoubleCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Double;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Double) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ Double res = ((Number) argument).doubleValue();
+ if (argument instanceof BigDecimal && res.isInfinite()) {
+ throw new IllegalArgumentException(Double.class + " out of range while converting from BigDecimal");
+ }
+ return res;
+ }
+ return argument;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Double.class
+ || classToTransformFrom == Integer.class
+ || classToTransformFrom == Long.class
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == Float.class
+ || classToTransformFrom == Double.TYPE
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Long.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE
+ || classToTransformFrom == Float.TYPE
+ || classToTransformFrom == BigDecimal.class
+ || classToTransformFrom == BigInteger.class
+ || (classToTransformFrom!=null && BigDecimal.class.isAssignableFrom(classToTransformFrom))
+ || (classToTransformFrom!=null && BigInteger.class.isAssignableFrom(classToTransformFrom))
+ ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/FloatCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/FloatCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/FloatCachedClass.java
new file mode 100644
index 0000000..a579028
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/FloatCachedClass.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class FloatCachedClass extends NumberCachedClass {
+ private final boolean allowNull;
+
+ public FloatCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Float) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ Float res = ((Number) argument).floatValue();
+ if (argument instanceof BigDecimal && res.isInfinite()) {
+ throw new IllegalArgumentException(Float.class + " out of range while converting from BigDecimal");
+ }
+ return res;
+ }
+ return argument;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Float;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Float.class
+ || classToTransformFrom == Integer.class
+ || classToTransformFrom == Long.class
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == Float.TYPE
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Long.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE
+ || classToTransformFrom == BigDecimal.class
+ || classToTransformFrom == BigInteger.class;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/IntegerCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/IntegerCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/IntegerCachedClass.java
new file mode 100644
index 0000000..334a3ab
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/IntegerCachedClass.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class IntegerCachedClass extends NumberCachedClass { // int, Integer
+ private final boolean allowNull;
+
+ public IntegerCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Integer) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ return ((Number) argument).intValue();
+ }
+ return argument;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Integer;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Integer.class
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == BigInteger.class
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/LongCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/LongCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/LongCachedClass.java
new file mode 100644
index 0000000..5d42b0c
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/LongCachedClass.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class LongCachedClass extends NumberCachedClass {
+ private final boolean allowNull;
+
+ public LongCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Long) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ return ((Number) argument).longValue();
+ }
+ return argument;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Long;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Integer.class
+ || classToTransformFrom == Long.class
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Long.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/NumberCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/NumberCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/NumberCachedClass.java
new file mode 100644
index 0000000..311cbc2
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/NumberCachedClass.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+import java.math.BigInteger;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class NumberCachedClass extends CachedClass {
+
+ public NumberCachedClass(Class klazz, ClassInfo classInfo) {
+ super(klazz, classInfo);
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Number) {
+ return coerceNumber(argument);
+ }
+ return argument;
+
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return classToTransformFrom == null
+ || Number.class.isAssignableFrom(classToTransformFrom)
+ || classToTransformFrom == Byte.TYPE
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Integer.TYPE
+ || classToTransformFrom == Long.TYPE
+ || classToTransformFrom == Float.TYPE
+ || classToTransformFrom == Double.TYPE
+ ;
+ }
+
+ private Object coerceNumber(Object argument) {
+ Class param = getTheClass();
+ if (param == Byte.class /*|| param == Byte.TYPE*/) {
+ argument = Byte.valueOf(((Number) argument).byteValue());
+ } else if (param == BigInteger.class) {
+ argument = new BigInteger(String.valueOf((Number) argument));
+ }
+
+ return argument;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/ObjectCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/ObjectCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ObjectCachedClass.java
new file mode 100644
index 0000000..f29acf7
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ObjectCachedClass.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class ObjectCachedClass extends CachedClass {
+ public ObjectCachedClass(ClassInfo classInfo) {
+ super(Object.class,classInfo);
+ }
+
+ public synchronized CachedClass getCachedSuperClass() {
+ return null;
+ }
+
+ public boolean isAssignableFrom(Class argument) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/ShortCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/ShortCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ShortCachedClass.java
new file mode 100644
index 0000000..f6cccf1
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/ShortCachedClass.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class ShortCachedClass extends NumberCachedClass {
+ private final boolean allowNull;
+
+ public ShortCachedClass(Class klazz, ClassInfo classInfo, boolean allowNull) {
+ super(klazz, classInfo);
+ this.allowNull = allowNull;
+ }
+
+ public Object coerceArgument(Object argument) {
+ if (argument instanceof Short) {
+ return argument;
+ }
+
+ if (argument instanceof Number) {
+ return ((Number) argument).shortValue();
+ }
+ return argument;
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return (allowNull && argument == null) || argument instanceof Short;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return (allowNull && classToTransformFrom == null)
+ || classToTransformFrom == Short.class
+ || classToTransformFrom == Byte.class
+ || classToTransformFrom == Short.TYPE
+ || classToTransformFrom == Byte.TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/stdclasses/StringCachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/StringCachedClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/StringCachedClass.java
new file mode 100644
index 0000000..a3039ad
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/StringCachedClass.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.stdclasses;
+
+import groovy.lang.GString;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ClassInfo;
+import org.codehaus.groovy.reflection.ReflectionCache;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class StringCachedClass extends CachedClass {
+ private static final Class STRING_CLASS = String.class;
+ private static final Class GSTRING_CLASS = GString.class;
+
+ public StringCachedClass(ClassInfo classInfo) {
+ super(STRING_CLASS, classInfo);
+ }
+
+ public boolean isDirectlyAssignable(Object argument) {
+ return argument instanceof String;
+ }
+
+ public boolean isAssignableFrom(Class classToTransformFrom) {
+ return classToTransformFrom == null
+ || classToTransformFrom == STRING_CLASS
+ || ReflectionCache.isAssignableFrom(GSTRING_CLASS,classToTransformFrom);
+ }
+
+ public Object coerceArgument(Object argument) {
+ return argument instanceof GString ? argument.toString() : argument;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/reflection/v7/GroovyClassValueJava7.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/v7/GroovyClassValueJava7.java b/src/main/java/org/codehaus/groovy/reflection/v7/GroovyClassValueJava7.java
new file mode 100644
index 0000000..a964a3e
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/v7/GroovyClassValueJava7.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.reflection.v7;
+
+import org.codehaus.groovy.reflection.GroovyClassValue;
+
+/** GroovyClassValue implementaion that simply delegates to Java 7's java.lang.ClassValue
+ * @see java.lang.ClassValue
+ *
+ * @param <T>
+*/
+public class GroovyClassValueJava7<T> extends ClassValue<T> implements GroovyClassValue<T> {
+ private final ComputeValue<T> computeValue;
+ public GroovyClassValueJava7(ComputeValue<T> computeValue){
+ this.computeValue = computeValue;
+ }
+ @Override
+ protected T computeValue(Class<?> type) {
+ return computeValue.computeValue(type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/runtime/AbstractComparator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/runtime/AbstractComparator.java b/src/main/java/org/codehaus/groovy/runtime/AbstractComparator.java
new file mode 100644
index 0000000..7c977cd
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/runtime/AbstractComparator.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.runtime;
+
+import java.util.Comparator;
+
+/**
+ * @author Andres Almiray
+ */
+public abstract class AbstractComparator<T> implements Comparator<T> {
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0edfcde9/src/main/java/org/codehaus/groovy/runtime/ArrayTypeUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/runtime/ArrayTypeUtils.java b/src/main/java/org/codehaus/groovy/runtime/ArrayTypeUtils.java
new file mode 100644
index 0000000..2a6e409
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/runtime/ArrayTypeUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.codehaus.groovy.runtime;
+
+/**
+ * Utilities for handling array types
+ *
+ * @author <a href="mailto:realbluesun@hotmail.com">Daniel.Sun</a>
+ * Created on 2016/10/28
+ */
+public class ArrayTypeUtils {
+
+ /**
+ * Calculate the dimension of array
+ *
+ * @param clazz the type of array
+ * @return the dimension of array
+ */
+ public static int dimension(Class clazz) {
+ checkArrayType(clazz);
+
+ int result = 0;
+ while (clazz.isArray()) {
+ result++;
+ clazz = clazz.getComponentType();
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the type of array elements
+ *
+ * @param clazz the type of array
+ * @return the type of elements
+ */
+ public static Class elementType(Class clazz) {
+ checkArrayType(clazz);
+
+ while (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Reduce the dimension of array
+ *
+ * @param clazz the type of array
+ * @param dim the target dimension
+ * @return the result array
+ */
+ public static Class reduceDimension(Class clazz, int dim) {
+ checkArrayType(clazz);
+
+ if (dim < 0) {
+ throw new IllegalArgumentException("The target dimension should not be less than zero: " + dim);
+ }
+
+ while (clazz.isArray() && dimension(clazz) > dim) {
+ clazz = clazz.getComponentType();
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Check whether the type passed in is array type.
+ * If the type is not array type, throw IllegalArgumentException.
+ */
+ private static void checkArrayType(Class clazz) {
+ if (null == clazz) {
+ throw new IllegalArgumentException("clazz can not be null");
+ }
+
+ if (!clazz.isArray()) {
+ throw new IllegalArgumentException(clazz.getCanonicalName() + " is not array type");
+ }
+ }
+}