You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/20 04:29:09 UTC

[01/47] groovy git commit: Move source files to proper packages

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_5_X b464b23bd -> 0ad8c07c2


http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/OrderBy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/OrderBy.java b/src/main/groovy/util/OrderBy.java
deleted file mode 100644
index 703c9bc..0000000
--- a/src/main/groovy/util/OrderBy.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import org.codehaus.groovy.runtime.NumberAwareComparator;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * A helper class for sorting objects via a closure to return the field
- * or operation on which to sort.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class OrderBy<T> implements Comparator<T>, Serializable {
-
-    private static final long serialVersionUID = 8385130064804116654L;
-    private final List<Closure> closures;
-    private boolean equalityCheck;
-    private final NumberAwareComparator<Object> numberAwareComparator = new NumberAwareComparator<Object>();
-
-    public OrderBy() {
-        this(new ArrayList<Closure>(), false);
-    }
-
-    public OrderBy(boolean equalityCheck) {
-        this(new ArrayList<Closure>(), equalityCheck);
-    }
-
-    public OrderBy(Closure closure) {
-        this(closure, false);
-    }
-
-    public OrderBy(Closure closure, boolean equalityCheck) {
-        this(new ArrayList<Closure>(), equalityCheck);
-        closures.add(closure);
-    }
-
-    public OrderBy(List<Closure> closures) {
-        this(closures, false);
-    }
-
-    public OrderBy(List<Closure> closures, boolean equalityCheck) {
-        this.equalityCheck = equalityCheck;
-        this.closures = closures;
-    }
-
-    public void add(Closure closure) {
-        closures.add(closure);
-    }
-
-    public int compare(T object1, T object2) {
-        for (Closure closure : closures) {
-            Object value1 = closure.call(object1);
-            Object value2 = closure.call(object2);
-            int result;
-            if (!equalityCheck || (value1 instanceof Comparable && value2 instanceof Comparable)) {
-                result = numberAwareComparator.compare(value1, value2);
-            } else {
-                result = DefaultTypeTransformation.compareEqual(value1, value2) ? 0 : -1;
-            }
-            if (result == 0) continue;
-            return result;
-        }
-        return 0;
-    }
-
-    public boolean isEqualityCheck() {
-        return equalityCheck;
-    }
-
-    public void setEqualityCheck(boolean equalityCheck) {
-        this.equalityCheck = equalityCheck;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/PermutationGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/PermutationGenerator.java b/src/main/groovy/util/PermutationGenerator.java
deleted file mode 100644
index 5a82abc..0000000
--- a/src/main/groovy/util/PermutationGenerator.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *  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 groovy.util;
-
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Systematically generate permutations.
- *
- * Adapted from Java Code by Michael Gilleland (released with no restrictions) using an algorithm described here:
- * Kenneth H. Rosen, Discrete Mathematics and Its Applications, 2nd edition (NY: McGraw-Hill, 1991), pp. 282-284
- */
-public class PermutationGenerator<E> implements Iterator<List<E>> {
-    private final int[] a;
-    private BigInteger numLeft;
-    private final BigInteger total;
-    private final List<E> items;
-
-    /**
-     * WARNING: Don't make n too large.
-     * Recall that the number of permutations is n!
-     * which can be very large, even when n is as small as 20 --
-     * 20! = 2,432,902,008,176,640,000 and
-     * 21! is too big to fit into a Java long, which is
-     * why we use BigInteger instead.
-     *
-     * @param items the items to permute
-     */
-    public PermutationGenerator(Collection<E> items) {
-        this.items = new ArrayList<E>(items);
-        int n = items.size();
-        if (n < 1) {
-            throw new IllegalArgumentException("At least one item required");
-        }
-        a = new int[n];
-        total = getFactorial(n);
-        reset();
-    }
-
-    public PermutationGenerator(Iterable<E> items) {
-        this(DefaultGroovyMethods.asCollection(items));
-    }
-
-    public void reset() {
-        for (int i = 0; i < a.length; i++) {
-            a[i] = i;
-        }
-        numLeft = new BigInteger(total.toString());
-    }
-
-    public BigInteger getTotal() {
-        return total;
-    }
-
-    public boolean hasNext() {
-        return numLeft.compareTo(BigInteger.ZERO) == 1;
-    }
-
-    /**
-     * Compute factorial (TODO: expose this)
-     *
-     * @param n the input integer
-     * @return the factorial for n
-     */
-    private static BigInteger getFactorial(int n) {
-        BigInteger fact = BigInteger.ONE;
-        for (int i = n; i > 1; i--) {
-            fact = fact.multiply(new BigInteger(Integer.toString(i)));
-        }
-        return fact;
-    }
-
-    /**
-     * Generate next permutation (algorithm from Rosen p. 284)
-     *
-     * @return the items permuted
-     */
-    public List<E> next() {
-        if (numLeft.equals(total)) {
-            numLeft = numLeft.subtract(BigInteger.ONE);
-            return items;
-        }
-
-        int temp;
-
-        // Find largest index j with a[j] < a[j+1]
-        int j = a.length - 2;
-        while (a[j] > a[j + 1]) {
-            j--;
-        }
-
-        // Find index k such that a[k] is smallest integer
-        // greater than a[j] to the right of a[j]
-        int k = a.length - 1;
-        while (a[j] > a[k]) {
-            k--;
-        }
-
-        // Interchange a[j] and a[k]
-        temp = a[k];
-        a[k] = a[j];
-        a[j] = temp;
-
-        // Put tail end of permutation after jth position in increasing order
-        int r = a.length - 1;
-        int s = j + 1;
-
-        while (r > s) {
-            temp = a[s];
-            a[s] = a[r];
-            a[r] = temp;
-            r--;
-            s++;
-        }
-
-        numLeft = numLeft.subtract(BigInteger.ONE);
-        List<E> ans = new ArrayList<E>(a.length);
-        for (int index : a) {
-            ans.add(items.get(index));
-        }
-        return ans;
-    }
-
-    public void remove() {
-        throw new UnsupportedOperationException("remove() not allowed for PermutationGenerator");
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Proxy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Proxy.java b/src/main/groovy/util/Proxy.java
deleted file mode 100644
index ac080b3..0000000
--- a/src/main/groovy/util/Proxy.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.MissingMethodException;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.util.Iterator;
-
-/**
- * Dynamic groovy proxy for another object.  All method
- * invocations get forwarded to actual object, unless the proxy overrides it.
- * See groovy/util/ProxyTest.groovy for usage details.
- *
- * @author Troy Heninger
- * @author Dierk Koenig
- */
-public class Proxy extends GroovyObjectSupport {
-
-    private Object adaptee = null;
-
-    /**
-     * This method is for convenience.
-     * It allows to get around the need for defining dump ctors in subclasses.
-     * See unit tests for details.
-     */
-    public Proxy wrap(Object adaptee){
-        setAdaptee(adaptee);
-        return this;
-    }
-
-    public Object getAdaptee() {
-        return adaptee;
-    }
-
-    public void setAdaptee(Object adaptee) {
-        this.adaptee = adaptee;
-    }
-
-    public Object invokeMethod(String name, Object args) {
-        try {
-            return super.invokeMethod(name, args);
-        }
-        catch (MissingMethodException e) {
-            return InvokerHelper.invokeMethod(adaptee, name, args);
-        }
-    }
-    
-    public Iterator iterator() {
-        return InvokerHelper.asIterator(adaptee);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ProxyGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ProxyGenerator.java b/src/main/groovy/util/ProxyGenerator.java
deleted file mode 100644
index da12b97..0000000
--- a/src/main/groovy/util/ProxyGenerator.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.DelegatingMetaClass;
-import groovy.lang.GroovyObject;
-import groovy.lang.GroovySystem;
-import groovy.lang.MetaClass;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.ProxyGeneratorAdapter;
-import org.codehaus.groovy.runtime.memoize.LRUCache;
-import org.codehaus.groovy.runtime.typehandling.GroovyCastException;
-import org.codehaus.groovy.transform.trait.Traits;
-
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Classes to generate 'Proxy' objects which implement interfaces,
- * maps of closures and/or extend classes/delegates.
- *
- * @author Paul King
- * @author Guillaume Laforge
- * @author Cedric Champeau
- */
-public class ProxyGenerator {
-    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-    private static final Class[] EMPTY_INTERFACE_ARRAY = EMPTY_CLASS_ARRAY;
-    private static final Map<Object,Object> EMPTY_CLOSURE_MAP = Collections.emptyMap();
-    private static final Set<String> EMPTY_KEYSET = Collections.emptySet();
-
-    public static final ProxyGenerator INSTANCE = new ProxyGenerator();
-
-    static {
-        // wrap the standard MetaClass with the delegate
-        setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(ProxyGenerator.class));
-    }
-
-    private ClassLoader override = null;
-    private boolean debug = false;
-    private boolean emptyMethods = false;
-
-    /**
-     * The adapter cache is used to cache proxy classes. When, for example, a call like:
-     * map as MyClass is found, then a lookup is made into the cache to find if a suitable
-     * adapter already exists. If so, then the class is reused, instead of generating a
-     * new class.
-     */
-    private final LRUCache adapterCache = new LRUCache(16);
-
-    public boolean getDebug() {
-        return debug;
-    }
-
-    /**
-     * Instructs <code>ProxyGenerator</code> to dump generated Groovy
-     * source code to standard output during construction. This is useful
-     * for debugging purposes but should be turned off in production.
-     *
-     * @param debug true if you want generated source to be printed
-     */
-    public void setDebug(boolean debug) {
-        this.debug = debug;
-    }
-
-    public boolean getEmptyMethods() {
-        return emptyMethods;
-    }
-
-    /**
-     * Changes generated methods to have empty implementations.
-     * <p>
-     * Methods in generated aggregates not supplied in a closures map or
-     * base class are given 'default' implementations. The implementation
-     * will normally throw an <code>UnsupportedOperationException</code>
-     * but setting this boolean will leave it empty.
-     *
-     * @param emptyMethods true if you want generated methods to be empty
-     */
-    public void setEmptyMethods(boolean emptyMethods) {
-        this.emptyMethods = emptyMethods;
-    }
-
-    public ClassLoader getOverride() {
-        return override;
-    }
-
-    public void setOverride(ClassLoader override) {
-        this.override = override;
-    }
-
-    public GroovyObject instantiateAggregateFromBaseClass(Class clazz) {
-        return instantiateAggregateFromBaseClass((Map) null, clazz);
-    }
-
-    public GroovyObject instantiateAggregateFromBaseClass(Map map, Class clazz) {
-        return instantiateAggregateFromBaseClass(map, clazz, null);
-    }
-
-    public GroovyObject instantiateAggregateFromBaseClass(Closure cl, Class clazz) {
-        Map<String, Closure> m = new HashMap<String, Closure>();
-        m.put("*", cl);
-        return instantiateAggregateFromBaseClass(m, clazz, null);
-    }
-
-    public GroovyObject instantiateAggregateFromBaseClass(Class clazz, Object[] constructorArgs) {
-        return instantiateAggregate(null, null, clazz, constructorArgs);
-    }
-
-    public GroovyObject instantiateAggregateFromBaseClass(Map map, Class clazz, Object[] constructorArgs) {
-        return instantiateAggregate(map, null, clazz, constructorArgs);
-    }
-
-    public GroovyObject instantiateAggregateFromInterface(Class clazz) {
-        return instantiateAggregateFromInterface(null, clazz);
-    }
-
-    public GroovyObject instantiateAggregateFromInterface(Map map, Class clazz) {
-        List<Class> interfaces = new ArrayList<Class>();
-        interfaces.add(clazz);
-        return instantiateAggregate(map, interfaces);
-    }
-
-    public GroovyObject instantiateAggregate(List<Class> interfaces) {
-        return instantiateAggregate(null, interfaces);
-    }
-
-    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces) {
-        return instantiateAggregate(closureMap, interfaces, null);
-    }
-
-    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces, Class clazz) {
-        return instantiateAggregate(closureMap, interfaces, clazz, null);
-    }
-
-    @SuppressWarnings("unchecked")
-    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces, Class clazz, Object[] constructorArgs) {
-        if (clazz != null && Modifier.isFinal(clazz.getModifiers())) {
-            throw new GroovyCastException("Cannot coerce a map to class " + clazz.getName() + " because it is a final class");
-        }
-        Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
-        ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, null, clazz);
-
-        return adapter.proxy(map, constructorArgs);
-    }
-
-    public GroovyObject instantiateDelegate(Object delegate) {
-        return instantiateDelegate(null, delegate);
-    }
-
-    public GroovyObject instantiateDelegate(List<Class> interfaces, Object delegate) {
-        return instantiateDelegate(null, interfaces, delegate);
-    }
-
-    public GroovyObject instantiateDelegate(Map closureMap, List<Class> interfaces, Object delegate) {
-        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, null);
-    }
-
-    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate) {
-        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, delegate.getClass());
-    }
-
-    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate, Class baseClass) {
-        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, baseClass, null);
-    }
-
-    /**
-     * Creates a proxy with a delegate object.
-     *
-     * @param closureMap the closure for methods not handled by the delegate
-     * @param interfaces interfaces to be implemented
-     * @param delegate the delegate object
-     * @param baseClass the base class
-     * @param name the name of the proxy, unused, but kept for compatibility with previous versions of Groovy.
-     * @return a proxy object implementing the specified interfaces, and delegating to the provided object
-     */
-    @SuppressWarnings("unchecked")
-    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate, Class baseClass, String name) {
-        Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
-        ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, delegate.getClass(), baseClass);
-
-        return adapter.delegatingProxy(delegate, map, (Object[])null);
-    }
-
-    private ProxyGeneratorAdapter createAdapter(Map closureMap, List<Class> interfaces, Class delegateClass, Class baseClass) {
-        // According to https://shipilev.net/blog/2016/arrays-wisdom-ancients/#_conclusion
-        // toArray(new T[0]) seems faster, safer, and contractually cleaner, and therefore should be the default choice now.
-        Class[] intfs = interfaces != null ? interfaces.toArray(EMPTY_CLASS_ARRAY) : EMPTY_INTERFACE_ARRAY;
-        Class base = baseClass;
-        if (base == null) {
-            if (intfs.length > 0) {
-                base = intfs[0];
-            } else {
-                base = Object.class;
-            }
-        }
-        Set<String> keys = closureMap == EMPTY_CLOSURE_MAP ? EMPTY_KEYSET : new HashSet<String>();
-        for (Object o : closureMap.keySet()) {
-            keys.add(o.toString());
-        }
-        boolean useDelegate = null != delegateClass;
-        CacheKey key = new CacheKey(base, useDelegate ? delegateClass : Object.class, keys, intfs, emptyMethods, useDelegate);
-        ProxyGeneratorAdapter adapter = (ProxyGeneratorAdapter) adapterCache.get(key);
-        if (adapter == null) {
-            adapter = new ProxyGeneratorAdapter(closureMap, base, intfs, useDelegate ? delegateClass.getClassLoader() : base.getClassLoader(), emptyMethods, useDelegate ? delegateClass : null);
-            adapterCache.put(key, adapter);
-        }
-
-        return adapter;
-    }
-
-    private static void setMetaClass(final MetaClass metaClass) {
-        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
-            @Override
-            public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
-                return InvokerHelper.invokeMethod(INSTANCE, methodName, arguments);
-            }
-        };
-        GroovySystem.getMetaClassRegistry().setMetaClass(ProxyGenerator.class, newMetaClass);
-    }
-    
-    private static final class CacheKey {
-        private static final Comparator<Class> INTERFACE_COMPARATOR = new Comparator<Class>() {
-            public int compare(final Class o1, final Class o2) {
-                // Traits order *must* be preserved
-                // See GROOVY-7285
-                if (Traits.isTrait(o1)) return -1;
-                if (Traits.isTrait(o2)) return 1;
-                return o1.getName().compareTo(o2.getName());
-            }
-        };
-        private final boolean emptyMethods;
-        private final boolean useDelegate;
-        private final Set<String> methods;
-        private final ClassReference delegateClass;
-        private final ClassReference baseClass;
-        private final ClassReference[] interfaces;
-
-        private CacheKey(final Class baseClass, final Class delegateClass, final Set<String> methods, final Class[] interfaces, final boolean emptyMethods, final boolean useDelegate) {
-            this.useDelegate = useDelegate;
-            this.baseClass = new ClassReference(baseClass);
-            this.delegateClass = new ClassReference(delegateClass);
-            this.emptyMethods = emptyMethods;
-            this.interfaces = interfaces == null ? null : new ClassReference[interfaces.length];
-            if (interfaces != null) {
-                Class[] interfacesCopy = new Class[interfaces.length];
-                System.arraycopy(interfaces, 0, interfacesCopy, 0, interfaces.length);
-                Arrays.sort(interfacesCopy, INTERFACE_COMPARATOR);
-                for (int i = 0; i < interfacesCopy.length; i++) {
-                    Class anInterface = interfacesCopy[i];
-                    this.interfaces[i] = new ClassReference(anInterface);
-                }
-            }
-            this.methods = methods;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            final CacheKey cacheKey = (CacheKey) o;
-
-            if (emptyMethods != cacheKey.emptyMethods) return false;
-            if (useDelegate != cacheKey.useDelegate) return false;
-            if (baseClass != null ? !baseClass.equals(cacheKey.baseClass) : cacheKey.baseClass != null) return false;
-            if (delegateClass != null ? !delegateClass.equals(cacheKey.delegateClass) : cacheKey.delegateClass != null) return false;
-            if (!Arrays.equals(interfaces, cacheKey.interfaces)) return false;
-            if (methods != null ? !methods.equals(cacheKey.methods) : cacheKey.methods != null) return false;
-
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = (emptyMethods ? 1 : 0);
-            result = 31 * result + (useDelegate ? 1 : 0);
-            result = 31 * result + (methods != null ? methods.hashCode() : 0);
-            result = 31 * result + (baseClass != null ? baseClass.hashCode() : 0);
-            result = 31 * result + (delegateClass != null ? delegateClass.hashCode() : 0);
-            result = 31 * result + (interfaces != null ? Arrays.hashCode(interfaces) : 0);
-            return result;
-        }
-
-        /**
-         * A weak reference which delegates equals and hashcode to the referent.
-         */
-        private static class ClassReference extends WeakReference<Class> {
-
-            public ClassReference(Class referent) {
-                super(referent);
-            }
-
-            @Override
-            public boolean equals(final Object o) {
-                if (this == o) return true;
-                if (o == null || getClass() != o.getClass()) return false;
-                Class thisClass = this.get();
-                ClassReference that = (ClassReference) o;
-                if (thisClass == null) return false;
-                return thisClass.equals(that.get());
-            }
-
-            @Override
-            public int hashCode() {
-                Class thisClass = this.get();
-                if (thisClass == null) return 0;
-                return thisClass.hashCode();
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ResourceConnector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ResourceConnector.java b/src/main/groovy/util/ResourceConnector.java
deleted file mode 100644
index 81e329a..0000000
--- a/src/main/groovy/util/ResourceConnector.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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 groovy.util;
-
-import java.net.URLConnection;
-
-/**
- * Base interface for customizing where resources can be found for the <code>GroovyScriptEngine</code>.
- *
- * @author sam
- */
-public interface ResourceConnector {
-
-    /**
-     * Retrieve a URLConnection to a script referenced by name.
-     *
-     * @param name
-     * @throws ResourceException
-     */
-    URLConnection getResourceConnection(String name) throws ResourceException;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ResourceException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ResourceException.java b/src/main/groovy/util/ResourceException.java
deleted file mode 100644
index 8b31d7e..0000000
--- a/src/main/groovy/util/ResourceException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  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 groovy.util;
-
-/**
- * @author sam
- */
-public class ResourceException extends Exception {
-
-    /**
-     *
-     */
-    public ResourceException() {
-        super();
-        // TODO Auto-generated constructor stub
-    }
-
-    /**
-     * @param message
-     */
-    public ResourceException(String message) {
-        super(message);
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public ResourceException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    /**
-     * @param cause
-     */
-    public ResourceException(Throwable cause) {
-        super(cause);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ScriptException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ScriptException.java b/src/main/groovy/util/ScriptException.java
deleted file mode 100644
index 85ce60f..0000000
--- a/src/main/groovy/util/ScriptException.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  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 groovy.util;
-
-/**
- * @author sam
- */
-public class ScriptException extends Exception {
-
-    /**
-     *
-     */
-    public ScriptException() {
-        super();
-    }
-
-    /**
-     * @param message
-     */
-    public ScriptException(String message) {
-        super(message);
-    }
-
-    /**
-     * @param message
-     * @param cause
-     */
-    public ScriptException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    /**
-     * @param cause
-     */
-    public ScriptException(Throwable cause) {
-        super(cause);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/logging/Commons.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/logging/Commons.java b/src/main/groovy/util/logging/Commons.java
deleted file mode 100644
index aa456d2..0000000
--- a/src/main/groovy/util/logging/Commons.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  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 groovy.util.logging;
-
-import groovy.lang.GroovyClassLoader;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.codehaus.groovy.transform.LogASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Locale;
-
-/**
- * This local transform adds a logging ability to your program using
- * Apache Commons logging. Every method call on a unbound variable named <i>log</i>
- * will be mapped to a call to the logger. For this a <i>log</i> field will be
- * inserted in the class. If the field already exists the usage of this transform
- * will cause a compilation error. The method name will be used to determine
- * what to call on the logger.
- * <pre>
- * log.name(exp)
- * </pre>is mapped to
- * <pre>
- * if (log.isNameEnabled() {
- *    log.name(exp)
- * }</pre>
- * Here name is a place holder for info, debug, warning, error, etc.
- * If the expression exp is a constant or only a variable access the method call will
- * not be transformed. But this will still cause a call on the injected logger.
- *
- * @author Hamlet D'Arcy
- * @author Matthias Cullmann
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
-public @interface Commons {
-    String value() default "log";
-    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
-    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default CommonsLoggingStrategy.class;
-
-    public  static class CommonsLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
-
-        private static final String LOGGER_NAME = "org.apache.commons.logging.Log";
-        private static final String LOGGERFACTORY_NAME = "org.apache.commons.logging.LogFactory";
-
-        protected CommonsLoggingStrategy(final GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
-            return classNode.addField(logFieldName,
-                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
-                    classNode(LOGGER_NAME),
-                    new MethodCallExpression(
-                            new ClassExpression(classNode(LOGGERFACTORY_NAME)),
-                            "getLog",
-                            new ConstantExpression(getCategoryName(classNode, categoryName))));
-        }
-
-        public boolean isLoggingMethod(String methodName) {
-            return methodName.matches("fatal|error|warn|info|debug|trace");
-        }
-
-        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
-            MethodCallExpression condition = new MethodCallExpression(
-                    logVariable,
-                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
-                    ArgumentListExpression.EMPTY_ARGUMENTS);
-            condition.setImplicitThis(false);
-
-            return new TernaryExpression(
-                    new BooleanExpression(condition),
-                    originalExpression,
-                    ConstantExpression.NULL);
-        }
-   }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/logging/Log.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/logging/Log.java b/src/main/groovy/util/logging/Log.java
deleted file mode 100644
index e52d39b..0000000
--- a/src/main/groovy/util/logging/Log.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  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 groovy.util.logging;
-
-import groovy.lang.GroovyClassLoader;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.AttributeExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.codehaus.groovy.transform.LogASTTransformation;
-import org.codehaus.groovy.transform.LogASTTransformation.LoggingStrategy;
-import org.objectweb.asm.Opcodes;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Locale;
-
-/**
- * This local transform adds a logging ability to your program using
- * java.util.logging. Every method call on a unbound variable named <i>log</i>
- * will be mapped to a call to the logger. For this a <i>log</i> field will be
- * inserted in the class. If the field already exists the usage of this transform
- * will cause a compilation error. The method name will be used to determine
- * what to call on the logger.
- * <pre>
- * log.name(exp)
- * </pre>is mapped to
- * <pre>
- * if (log.isLoggable(Level.NAME) {
- *    log.name(exp)
- * }</pre>
- * Here name is a place holder for info, fine, finer, finest, config, warning, severe.
- * NAME is name transformed to upper case. if anything else is used it will result in
- * an exception at runtime. If the expression exp is a constant or only a variable access
- * the method call will not be transformed. But this will still cause a call on the injected
- * logger.
- *
- * @author Guillaume Laforge
- * @author Jochen Theodorou
- * @author Dinko Srkoc
- * @author Hamlet D'Arcy
- * @author Raffaele Cigni
- * @author Alberto Vilches Raton
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
-public @interface Log {
-    String value() default "log";
-    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
-    Class<? extends LoggingStrategy> loggingStrategy() default JavaUtilLoggingStrategy.class;
-
-    /**
-     * This class contains the logic of how to weave a Java Util Logging logger into the host class.
-     */
-    public static class JavaUtilLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
-
-        private static final ClassNode LOGGER_CLASSNODE = ClassHelper.make(java.util.logging.Logger.class);
-        private static final ClassNode LEVEL_CLASSNODE = ClassHelper.make(java.util.logging.Level.class);
-
-        protected JavaUtilLoggingStrategy(final GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
-            return classNode.addField(logFieldName,
-                        Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
-                        LOGGER_CLASSNODE,
-                        new MethodCallExpression(
-                                new ClassExpression(LOGGER_CLASSNODE),
-                                "getLogger",
-                                new ConstantExpression(getCategoryName(classNode, categoryName))));
-        }
-
-        public boolean isLoggingMethod(String methodName) {
-            return methodName.matches("severe|warning|info|fine|finer|finest");
-        }
-
-        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
-            AttributeExpression logLevelExpression = new AttributeExpression(
-                    new ClassExpression(LEVEL_CLASSNODE),
-                    new ConstantExpression(methodName.toUpperCase(Locale.ENGLISH)));
-
-            ArgumentListExpression args = new ArgumentListExpression();
-            args.addExpression(logLevelExpression);
-            MethodCallExpression condition = new MethodCallExpression(logVariable, "isLoggable", args);
-            condition.setImplicitThis(false);
-
-            return new TernaryExpression(
-                    new BooleanExpression(condition),
-                    originalExpression,
-                    ConstantExpression.NULL);
-
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/logging/Log4j.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/logging/Log4j.java b/src/main/groovy/util/logging/Log4j.java
deleted file mode 100644
index 2dfdf7f..0000000
--- a/src/main/groovy/util/logging/Log4j.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  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 groovy.util.logging;
-
-import groovy.lang.GroovyClassLoader;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.AttributeExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.codehaus.groovy.transform.LogASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Locale;
-
-/**
- * This local transform adds a logging ability to your program using
- * Log4j logging. Every method call on a unbound variable named <i>log</i>
- * will be mapped to a call to the logger. For this a <i>log</i> field will be
- * inserted in the class. If the field already exists the usage of this transform
- * will cause a compilation error. The method name will be used to determine
- * what to call on the logger.
- * <pre>
- * log.name(exp)
- * </pre>is mapped to
- * <pre>
- * if (log.isNameEnabled() {
- *    log.name(exp)
- * }</pre>
- * Here name is a place holder for info, debug, warning, error, etc.
- * If the expression exp is a constant or only a variable access the method call will
- * not be transformed. But this will still cause a call on the injected logger.
- *
- * @author Hamlet D'Arcy
- * @author Tomek Bujok
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
-public @interface Log4j {
-    String value() default "log";
-    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
-    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Log4jLoggingStrategy.class;
-
-    public static class Log4jLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
-        private static final String LOGGER_NAME = "org.apache.log4j.Logger";
-        private static final String PRIORITY_NAME = "org.apache.log4j.Priority";
-
-        protected Log4jLoggingStrategy(final GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
-            return classNode.addField(logFieldName,
-                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
-                    classNode(LOGGER_NAME),
-                    new MethodCallExpression(
-                            new ClassExpression(classNode(LOGGER_NAME)),
-                            "getLogger",
-                            new ConstantExpression(getCategoryName(classNode, categoryName))));
-        }
-
-        public boolean isLoggingMethod(String methodName) {
-            return methodName.matches("fatal|error|warn|info|debug|trace");
-        }
-
-        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
-            final MethodCallExpression condition;
-            if (!"trace".equals(methodName)) {
-                AttributeExpression logLevelExpression = new AttributeExpression(
-                        new ClassExpression(classNode(PRIORITY_NAME)),
-                        new ConstantExpression(methodName.toUpperCase(Locale.ENGLISH)));
-                ArgumentListExpression args = new ArgumentListExpression();
-                args.addExpression(logLevelExpression);
-                condition = new MethodCallExpression(logVariable, "isEnabledFor", args);
-            } else {
-                // log4j api is inconsistent, so trace requires special handling
-                condition = new MethodCallExpression(
-                        logVariable,
-                        "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
-                        ArgumentListExpression.EMPTY_ARGUMENTS);
-            }
-            condition.setImplicitThis(false);
-
-            return new TernaryExpression(
-                    new BooleanExpression(condition),
-                    originalExpression,
-                    ConstantExpression.NULL);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/logging/Log4j2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/logging/Log4j2.java b/src/main/groovy/util/logging/Log4j2.java
deleted file mode 100644
index 7aca5a5..0000000
--- a/src/main/groovy/util/logging/Log4j2.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  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 groovy.util.logging;
-
-import groovy.lang.GroovyClassLoader;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.codehaus.groovy.transform.LogASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Locale;
-
-/**
- * This local transform adds a logging ability to your program using
- * Log4j2 logging. Every method call on a unbound variable named <i>log</i>
- * will be mapped to a call to the logger. For this a <i>log</i> field will be
- * inserted in the class. If the field already exists the usage of this transform
- * will cause a compilation error. The method name will be used to determine
- * what to call on the logger.
- * <pre>
- * log.name(exp)
- * </pre>is mapped to
- * <pre>
- * if (log.isNameEnabled() {
- *    log.name(exp)
- * }</pre>
- * Here name is a place holder for info, debug, warning, error, etc.
- * If the expression exp is a constant or only a variable access the method call will
- * not be transformed. But this will still cause a call on the injected logger.
- *
- * @since 2.2.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
-public @interface Log4j2 {
-    String value() default "log";
-    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
-    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Log4j2LoggingStrategy.class;
-
-    public static class Log4j2LoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
-        private static final String LOGGER_NAME = "org.apache.logging.log4j.core.Logger";
-        private static final String LOG_MANAGER_NAME = "org.apache.logging.log4j.LogManager";
-
-        protected Log4j2LoggingStrategy(final GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
-            return classNode.addField(logFieldName,
-                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
-                    classNode(LOGGER_NAME),
-                    new MethodCallExpression(
-                            new ClassExpression(classNode(LOG_MANAGER_NAME)),
-                            "getLogger",
-                            new ConstantExpression(getCategoryName(classNode, categoryName))));
-        }
-
-        public boolean isLoggingMethod(String methodName) {
-            return methodName.matches("fatal|error|warn|info|debug|trace");
-        }
-
-        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
-            MethodCallExpression condition = new MethodCallExpression(
-                    logVariable,
-                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
-                    ArgumentListExpression.EMPTY_ARGUMENTS);
-            condition.setImplicitThis(false);
-
-            return new TernaryExpression(
-                    new BooleanExpression(condition),
-                    originalExpression,
-                    ConstantExpression.NULL);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/logging/Slf4j.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/logging/Slf4j.java b/src/main/groovy/util/logging/Slf4j.java
deleted file mode 100644
index 0e866e4..0000000
--- a/src/main/groovy/util/logging/Slf4j.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  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 groovy.util.logging;
-
-import groovy.lang.GroovyClassLoader;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-import org.codehaus.groovy.transform.LogASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Locale;
-
-/**
- * This local transform adds a logging ability to your program using
- * LogBack logging. Every method call on a unbound variable named <i>log</i>
- * will be mapped to a call to the logger. For this a <i>log</i> field will be
- * inserted in the class. If the field already exists the usage of this transform
- * will cause a compilation error. The method name will be used to determine
- * what to call on the logger.
- * <pre>
- * log.name(exp)
- * </pre>is mapped to
- * <pre>
- * if (log.isNameLoggable() {
- *    log.name(exp)
- * }</pre>
- * Here name is a place holder for info, debug, warning, error, etc.
- * If the expression exp is a constant or only a variable access the method call will
- * not be transformed. But this will still cause a call on the injected logger.
- *
- * @author Hamlet D'Arcy
- * @author Alberto Mijares
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
-public @interface Slf4j {
-    String value() default "log";
-    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
-    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Slf4jLoggingStrategy.class;
-
-    public static class Slf4jLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
-        private static final String LOGGER_NAME = "org.slf4j.Logger";
-        private static final String FACTORY_NAME = "org.slf4j.LoggerFactory";
-
-        protected Slf4jLoggingStrategy(final GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
-            return classNode.addField(logFieldName,
-                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
-                    classNode(LOGGER_NAME),
-                    new MethodCallExpression(
-                            new ClassExpression(classNode(FACTORY_NAME)),
-                            "getLogger",
-                            new ConstantExpression(getCategoryName(classNode, categoryName))));
-        }
-
-        public boolean isLoggingMethod(String methodName) {
-            return methodName.matches("error|warn|info|debug|trace");
-        }
-
-        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
-            MethodCallExpression condition = new MethodCallExpression(
-                    logVariable,
-                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
-                    ArgumentListExpression.EMPTY_ARGUMENTS);
-            condition.setImplicitThis(false);
-
-            return new TernaryExpression(
-                    new BooleanExpression(condition),
-                    originalExpression,
-                    ConstantExpression.NULL);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/package.html b/src/main/groovy/util/package.html
deleted file mode 100644
index e7a2c5a..0000000
--- a/src/main/groovy/util/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-
-     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 groovy.util.*</title>
-  </head>
-  <body>
-    <p>Various Groovy utilities for working with nodes, builders, logging, JUnit test cases, text expressions, Ant tasks or JMX MBeans.</p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/xml/QName.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/xml/QName.java b/src/main/groovy/xml/QName.java
deleted file mode 100644
index 06a733d..0000000
--- a/src/main/groovy/xml/QName.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- *  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 groovy.xml;
-
-import java.io.Serializable;
-
-/**
- * <code>QName</code> class represents the value of a qualified name
- * as specified in <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML
- * Schema Part2: Datatypes specification</a>.
- * <p>
- * The value of a QName contains a <b>namespaceURI</b>, a <b>localPart</b> and a <b>prefix</b>.
- * The localPart provides the local part of the qualified name. The
- * namespaceURI is a URI reference identifying the namespace.
- */
-public class QName implements Serializable {
-    private static final long serialVersionUID = -9029109610006696081L;
-
-    /** comment/shared empty string */
-    private static final String EMPTY_STRING = "";
-
-    /** Field namespaceURI */
-    private String namespaceURI;
-
-    /** Field localPart */
-    private String localPart;
-
-    /** Field prefix */
-    private String prefix;
-
-    /**
-     * Constructor for the QName.
-     *
-     * @param localPart Local part of the QName
-     */
-    public QName(String localPart) {
-        this(EMPTY_STRING, localPart, EMPTY_STRING);
-    }
-
-    /**
-     * Constructor for the QName.
-     *
-     * @param namespaceURI Namespace URI for the QName
-     * @param localPart Local part of the QName.
-     */
-    public QName(String namespaceURI, String localPart) {
-        this(namespaceURI, localPart, EMPTY_STRING);
-    }
-
-    /**
-     * Constructor for the QName.
-     *
-     * @param namespaceURI Namespace URI for the QName
-     * @param localPart Local part of the QName.
-     * @param prefix Prefix of the QName.
-     */
-    public QName(String namespaceURI, String localPart, String prefix) {
-        this.namespaceURI = (namespaceURI == null)
-                ? EMPTY_STRING
-                : namespaceURI;
-        if (localPart == null) {
-            throw new IllegalArgumentException("invalid QName local part");
-        } else {
-            this.localPart = localPart;
-        }
-
-        if (prefix == null) {
-            throw new IllegalArgumentException("invalid QName prefix");
-        } else {
-            this.prefix = prefix;
-        }
-    }
-
-    /**
-     * Gets the Namespace URI for this QName
-     *
-     * @return Namespace URI
-     */
-    public String getNamespaceURI() {
-        return namespaceURI;
-    }
-
-    /**
-     * Gets the Local part for this QName
-     *
-     * @return Local part
-     */
-    public String getLocalPart() {
-        return localPart;
-    }
-
-    /**
-     * Gets the Prefix for this QName
-     *
-     * @return Prefix
-     */
-    public String getPrefix() {
-        return prefix;
-    }
-
-    /**
-     * Returns the fully qualified name of this QName
-     *
-     * @return  a string representation of the QName
-     */
-    public String getQualifiedName() {
-        return ((prefix.equals(EMPTY_STRING))
-                ? localPart
-                : prefix + ':' + localPart);
-    }
-
-    /**
-     * Returns a string representation of this QName
-     *
-     * @return  a string representation of the QName
-     */
-    public String toString() {
-        return ((namespaceURI.equals(EMPTY_STRING))
-                ? localPart
-                : '{' + namespaceURI + '}' + localPart);
-    }
-
-    /**
-     * Tests this QName for equality with another object.
-     * <p>
-     * If the given object is not a QName or String equivalent or is null then this method
-     * returns <tt>false</tt>.
-     * <p>
-     * For two QNames to be considered equal requires that both
-     * localPart and namespaceURI must be equal. This method uses
-     * <code>String.equals</code> to check equality of localPart
-     * and namespaceURI. Any class that extends QName is required
-     * to satisfy this equality contract.
-     *
-     * If the supplied object is a String, then it is split in two on the last colon
-     * and the first half is compared against the prefix || namespaceURI
-     * and the second half is compared against the localPart
-     *
-     * i.e.&#160;assert new QName("namespace","localPart").equals("namespace:localPart")
-     *
-     * Intended Usage: for gpath accessors, e.g.&#160;root.'urn:mynamespace:node'
-     *
-     * Warning: this equivalence is not commutative,
-     * i.e.&#160;qname.equals(string) may be true/false  but string.equals(qname) is always false
-     *
-     * <p>
-     * This method satisfies the general contract of the <code>Object.equals</code> method.
-     *
-     * @param o the reference object with which to compare
-     *
-     * @return <code>true</code> if the given object is identical to this
-     *      QName: <code>false</code> otherwise.
-     */
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null) return false;
-        if (o instanceof QName) {
-            final QName qName = (QName) o;
-            if (!namespaceURI.equals(qName.namespaceURI)) return false;
-            return localPart.equals(qName.localPart);
-
-        } else if (o instanceof String) {
-            final String string = (String)o;
-            if (string.length() == 0) return false;
-            int lastColonIndex = string.lastIndexOf(":");
-            if (lastColonIndex < 0 || lastColonIndex == string.length() - 1) return false;
-            final String stringPrefix = string.substring(0,lastColonIndex);
-            final String stringLocalPart = string.substring(lastColonIndex + 1);
-            if (stringPrefix.equals(prefix) || stringPrefix.equals(namespaceURI)) {
-                return localPart.equals(stringLocalPart);
-            }
-            return false;
-        }
-        return false;
-    }
-
-    /**
-     * Tests if this QName matches another object.
-     * <p>
-     * If the given object is not a QName or String equivalent or is null then this method
-     * returns <tt>false</tt>.
-     * <p>
-     * For two QNames to be considered matching requires that both
-     * localPart and namespaceURI must be equal or one of them is a wildcard.
-     *
-     * If the supplied object is a String, then it is split in two on the last colon
-     * and the first half is matched against the prefix || namespaceURI
-     * and the second half is matched against the localPart
-     *
-     * @param o the reference object with which to compare
-     *
-     * @return <code>true</code> if the given object matches
-     * this QName: <code>false</code> otherwise.
-     */
-    public boolean matches(Object o) {
-        if (this == o) return true;
-        if (o == null) return false;
-        if (o instanceof QName) {
-            final QName qName = (QName) o;
-            if (!namespaceURI.equals(qName.namespaceURI) && !namespaceURI.equals("*") && !qName.namespaceURI.equals("*")) return false;
-            return localPart.equals(qName.localPart) || localPart.equals("*") || qName.localPart.equals("*");
-        } else if (o instanceof String) {
-            final String string = (String)o;
-            if (string.length() == 0) return false;
-            // try matching against 'prefix:localname'
-            int lastColonIndex = string.lastIndexOf(":");
-            if (lastColonIndex < 0 && prefix.length() == 0) return string.equals(localPart);
-            if (lastColonIndex < 0 || lastColonIndex == string.length() - 1) return false;
-            final String stringPrefix = string.substring(0,lastColonIndex);
-            final String stringLocalPart = string.substring(lastColonIndex + 1);
-            if (stringPrefix.equals(prefix) || stringPrefix.equals(namespaceURI) || stringPrefix.equals("*")) {
-                return localPart.equals(stringLocalPart) || stringLocalPart.equals("*");
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a QName holding the value of the specified String.
-     * <p>
-     * The string must be in the form returned by the QName.toString()
-     * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}"
-     * part being optional.
-     * <p>
-     * This method doesn't do a full validation of the resulting QName.
-     * In particular, it doesn't check that the resulting namespace URI
-     * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting
-     * local part is a legal NCName per the XML Namespaces specification.
-     *
-     * @param s the string to be parsed
-     * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName
-     * @return QName corresponding to the given String
-     */
-    public static QName valueOf(String s) {
-
-        if ((s == null) || s.equals("")) {
-            throw new IllegalArgumentException("invalid QName literal");
-        }
-
-        if (s.charAt(0) == '{') {
-            int i = s.indexOf('}');
-
-            if (i == -1) {
-                throw new IllegalArgumentException("invalid QName literal");
-            }
-
-            if (i == s.length() - 1) {
-                throw new IllegalArgumentException("invalid QName literal");
-            } else {
-                return new QName(s.substring(1, i), s.substring(i + 1));
-            }
-        } else {
-            return new QName(s);
-        }
-    }
-
-    /**
-     * Returns a hash code value for this QName object. The hash code
-     * is based on both the localPart and namespaceURI parts of the
-     * QName. This method satisfies the  general contract of the
-     * <code>Object.hashCode</code> method.
-     *
-     * @return a hash code value for this Qname object
-     */
-    public int hashCode() {
-        int result;
-        result = namespaceURI.hashCode();
-        result = 29 * result + localPart.hashCode();
-        return result;
-    }
-} 
\ No newline at end of file


[15/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaClassRegistry.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassRegistry.java b/src/main/groovy/lang/MetaClassRegistry.java
deleted file mode 100644
index f13c1c1..0000000
--- a/src/main/groovy/lang/MetaClassRegistry.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.GeneratedClosure;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
-
-import java.lang.reflect.Constructor;
-import java.util.Iterator;
-
-/**
- * A MetaClassRegistry is an object that is responsible for managing the a cache of MetaClass instances. Each
- * java.lang.Class instance has an associated MetaClass and client code can query this interface for the MetaClass for
- * a given associated java.lang.Class
- *
- * @see groovy.lang.MetaClass
- *
- * @author John Wilson
- * @author Graeme Rocher
- * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
- *
- */
-public interface MetaClassRegistry {
-    
-    /**
-     * The main function of the registry
-     * If a meta class exists then return it
-     * otherwise create one, put it in the registry and return it
-     */
-    MetaClass getMetaClass(Class theClass);
-    
-    /**
-     * Adds a metaclass to the registry for the given class
-     *
-     * @param theClass The class
-     * @param theMetaClass The MetaClass for theClass
-     */
-    void setMetaClass(Class theClass, MetaClass theMetaClass);
-
-    /**
-     * Removes a cached MetaClass from the registry
-     *
-     * @param theClass The Java class of the MetaClass to remove
-     */
-    void removeMetaClass(Class theClass);
-
-    /**
-     * Retrieves the MetaClassCreationHandle that is responsible for constructing MetaClass instances
-     *
-     * @return The MetaClassCreationHandle instance
-     */
-    MetaClassCreationHandle getMetaClassCreationHandler();
-
-    /**
-     * Sets the MetaClassCreationHandle instance that is responsible for constructing instances
-     *
-     * @param handle The handle instance
-     */
-    void setMetaClassCreationHandle(MetaClassCreationHandle handle);
-
-    /**
-     * Adds a meta class change listener for constant meta classes
-     *
-     * @param listener - the update listener
-     */
-    void addMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
-    
-    /**
-     * Adds a meta class change listener for constant meta classes. 
-     * This listener cannot be removed!
-     *
-     * @param listener - the update listener
-     */
-    void addNonRemovableMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
-
-    /**
-     * Removes a meta class change listener for constant meta classes
-     *
-     * @param listener - the update listener
-     */
-    void removeMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
-
-    /**
-     * Returns all registered class change listener for constant meta classes.
-     *
-     * @return an array containing all change listener
-     */
-    MetaClassRegistryChangeEventListener[] getMetaClassRegistryChangeEventListeners();
-
-    /**
-     * Gets a snapshot of the current constant meta classes and returns it as Iterator.
-     * Modifications done using this Iterator will not cause a ConcurrentModificationException.
-     * If a MetaClass is removed using this Iterator, then the MetaClass will only
-     * be removed if the MetaClass was not replaced by another MetaClass in the meantime.
-     * If a MetaClass is added while using this Iterator, then it will be part of the Iteration.
-     * If a MetaClass replaces another constant meta class, then the Iteration might show two
-     * meta classes for the same class.
-     * <p>
-     * Note: This Iterator may not used with multiple threads.
-     *
-     * @return Iterator for the constant meta classes
-     */
-    Iterator iterator();    
-    
-    /**
-     * Class used as base for the creation of MetaClass implementations.
-     * The Class defaults to MetaClassImpl, if the class loading fails to
-     * find a special meta class. The name for such a meta class would be
-     * the class name it is created for with the prefix
-     * "groovy.runtime.metaclass." By replacing the handle in the registry
-     * you can have any control over the creation of what MetaClass is used
-     * for a class that you want to have. 
-     * WARNING: experimental code, likely to change soon
-     * @author Jochen Theodorou
-     */
-    class MetaClassCreationHandle {
-        private boolean disableCustomMetaClassLookup;
-         
-        /**
-         * Creates a metaclass implementation for theClass.
-         * @param theClass The class to create a metaclass for
-         * @param registry The metaclass registry the metaclass we be registered in.
-         */
-        public final MetaClass create(Class theClass, MetaClassRegistry registry) {
-           if (disableCustomMetaClassLookup)
-               return createNormalMetaClass(theClass, registry);
-
-            return createWithCustomLookup(theClass, registry);
-        }
-
-        private MetaClass createWithCustomLookup(Class theClass, MetaClassRegistry registry) {
-            try {
-                final Class customMetaClass = Class.forName("groovy.runtime.metaclass." + theClass.getName() + "MetaClass");
-                if (DelegatingMetaClass.class.isAssignableFrom(customMetaClass)) {
-                    final Constructor customMetaClassConstructor = customMetaClass.getConstructor(MetaClass.class);
-                    MetaClass normalMetaClass = createNormalMetaClass(theClass, registry);
-                    return (MetaClass)customMetaClassConstructor.newInstance(normalMetaClass);
-                }
-                else {
-                    final Constructor customMetaClassConstructor = customMetaClass.getConstructor(MetaClassRegistry.class, Class.class);
-                    return (MetaClass)customMetaClassConstructor.newInstance(registry, theClass);
-                }
-            }
-            catch (final ClassNotFoundException e) {
-                return createNormalMetaClass(theClass, registry);
-            } catch (final Exception e) {
-                throw new GroovyRuntimeException("Could not instantiate custom Metaclass for class: " + theClass.getName() + ". Reason: " + e, e);
-            }
-        }
-
-        protected MetaClass createNormalMetaClass(Class theClass,MetaClassRegistry registry) {
-            if (GeneratedClosure.class.isAssignableFrom(theClass)) {
-                return new ClosureMetaClass(registry,theClass);
-            } else {
-                return new MetaClassImpl(registry, theClass);
-            }
-        }
-
-        /**
-         * Returns whether custom meta classes are disabled.
-         */
-        public boolean isDisableCustomMetaClassLookup() {
-            return disableCustomMetaClassLookup;
-        }
-
-        /**
-         * Set flag saying to disable lookup of custom meta classes
-         * It's enough to call this method only once in your application for handle which was set in to registry
-         * as every new handle will inherit this property
-         * @param disableCustomMetaClassLookup flag saying to disable lookup of custom meta classes
-         */
-        public void setDisableCustomMetaClassLookup(boolean disableCustomMetaClassLookup) {
-            this.disableCustomMetaClassLookup = disableCustomMetaClassLookup;
-        }
-    }
- }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaClassRegistryChangeEvent.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassRegistryChangeEvent.java b/src/main/groovy/lang/MetaClassRegistryChangeEvent.java
deleted file mode 100644
index c882fda..0000000
--- a/src/main/groovy/lang/MetaClassRegistryChangeEvent.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.EventObject;
-
-/**
- * An event used to propagate meta class updates
- *
- * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
- */
-public class MetaClassRegistryChangeEvent extends EventObject {
-    private final Class clazz;
-    private final Object instance;
-    private final MetaClass metaClass;
-    private final MetaClass oldMetaClass;
-
-    /**
-     *Constructs a new MetaClassRegistryChangeEvent Object
-     *
-     * @param source The object the the event originates at.
-     * @param instance Object instance  the MetaClass change is on.
-     * @param clazz  The class that is affected by the registry change
-     * @param oldMetaClass The old MetaClass
-     * @param newMetaClass The new MetaClass
-     */
-    public MetaClassRegistryChangeEvent(Object source, Object instance, Class clazz, MetaClass oldMetaClass, MetaClass newMetaClass) {
-        super(source);
-        this.clazz = clazz;
-        this.metaClass = newMetaClass;
-        this.oldMetaClass = oldMetaClass;
-        this.instance = instance;
-    }
-
-    /**
-     * Get the class that is updated.
-     *
-     *@return The updated class
-     */
-    public Class getClassToUpdate() {
-        return clazz;
-    }
-
-    /**
-     * Get the new MetaClass
-     *
-     * @return The new MetaClass
-     */
-    public MetaClass getNewMetaClass() {
-        return metaClass;
-    }
-
-    /**
-     * Get the old MetaClass
-     *
-     * @return The old MetaClass
-     */
-    public MetaClass getOldMetaClass() {
-        return oldMetaClass;
-    }
-
-    /**
-     * Determines if this event is for a change for a single instance or all instances of the Class.
-     *
-     * @return whether this event is for a single instance
-     */
-    public boolean isPerInstanceMetaClassChange() {
-        return instance!=null;
-    }
-
-    /**
-     * Returns the instance this event is for.
-     *
-     * @return the instance or null if this event is for a change for all instances of a class
-     */
-    public Object getInstance() {
-        return instance;
-    }
-
-    /**
-     * Get the MetaClassRegistry that originates this change
-     *
-     * @return the source MetaClassRegistry
-     */
-    public MetaClassRegistry getRegistry() {
-        return (MetaClassRegistry) source;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaClassRegistryChangeEventListener.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassRegistryChangeEventListener.java b/src/main/groovy/lang/MetaClassRegistryChangeEventListener.java
deleted file mode 100644
index e7fd40c..0000000
--- a/src/main/groovy/lang/MetaClassRegistryChangeEventListener.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.EventListener;
-
-/**
- * A listener called whenever a constant MetaClass is set, removed or replaced. 
- *
- * @see groovy.lang.MetaClassRegistry
- * @see groovy.lang.MetaClassRegistryChangeEvent
- *
- * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
-  *
- */
-public interface MetaClassRegistryChangeEventListener extends EventListener{
-
-    /**
-     * Called when the a constant MetaClass is updated. If the new MetaClass is null, then the MetaClass
-     * is removed. Be careful, while this method is executed other updates may happen. If you want this
-     * method thread safe, you have to take care of that by yourself.
-     *
-     * @param cmcu - the change event
-     */
-    void updateConstantMetaClass(MetaClassRegistryChangeEvent cmcu);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaExpandoProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaExpandoProperty.java b/src/main/groovy/lang/MetaExpandoProperty.java
deleted file mode 100644
index 6eb2cf7..0000000
--- a/src/main/groovy/lang/MetaExpandoProperty.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.Map.Entry;
-
-/**
- * Represents a property in an Expando object
- *
- * @author John Stump
- */
-public class MetaExpandoProperty extends MetaProperty {
-
-    Object value = null;
-
-    public MetaExpandoProperty(Entry entry) {
-        super((String) entry.getKey(), Object.class);
-
-        value = entry.getValue();
-    }
-
-    /**
-     * @return the property of the given object
-     * @throws Exception if the property could not be evaluated
-     */
-    public Object getProperty(Object object) {
-        return value;
-    }
-
-    /**
-     * Sets the property on the given object to the new value
-     *
-     * @param object   on which to set the property
-     * @param newValue the new value of the property
-     */
-    public void setProperty(Object object, Object newValue) {
-        value = newValue;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaMethod.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaMethod.java b/src/main/groovy/lang/MetaMethod.java
deleted file mode 100644
index 3051675..0000000
--- a/src/main/groovy/lang/MetaMethod.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- *  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 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</a>
- * @author Alex Tkachman
- */
-public abstract class MetaMethod extends ParameterTypes implements Cloneable {
-    private String signature;
-    private String mopName;
-
-    /**
-     * Constructor for a metamethod with an empty parameter list
-     */
-    public MetaMethod() {
-    }
-
-    /**
-     *Constructor wit a list of parameter classes
-     *
-     * @param pt A list of parameters types
-     */
-    public MetaMethod(Class [] pt) {
-        super (pt);
-    }
-
-    /**
-     *Returns the modifiers for this method
-     *
-     * @return modifiers as an int.
-     */
-    public abstract int getModifiers();
-
-    /**
-     * Returns the name of the method represented by this class
-     * 
-     * @return name of this method
-     */
-    public abstract String getName();
-
-    /**
-     * Access the return type for this method
-     *
-     *@return the return type of this method
-     */
-    public abstract Class getReturnType();
-
-    /**
-     * Gets the class where this method is declared
-     *
-     * @return class of this method
-     */
-    public abstract CachedClass getDeclaringClass();
-
-    /**
-     * Invoke this method
-     *
-     * @param object The object this method should be invoked on
-     * @param arguments The arguments for the method if applicable
-     * @return The return value of the invocation
-     */
-    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));
-        }
-    }
-
-    /**
-     *Returns true if this this metamethod represents the same method as the argument.
-     *
-     * @param method A metaMethod instance
-     * @return true if method is for the same method as this method, false otherwise.
-     */
-    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;
-    }
-
-    /**
-     * Returns a string representation of this method
-     */
-    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);
-        }
-    }
-
-    /**
-     * Returns whether or not this method is static.
-     * @return true if this method is static
-     */
-    public boolean isStatic() {
-        return (getModifiers() & Modifier.STATIC) != 0;
-    }
-
-    /**
-     * Returns whether or not this method is abstract.
-     * @return true if this method is abstract
-     */
-    public boolean isAbstract() {
-        return (getModifiers() & Modifier.ABSTRACT) != 0;
-    }
-
-    /**
-     * Returns whether or not this method is private.
-     * @return true if this method is private
-     */
-    public final boolean isPrivate() {
-        return (getModifiers() & Modifier.PRIVATE) != 0;
-    }
-
-    /**
-     * Returns whether or not this method is protected.
-     * @return true if this method is protected
-     */
-    public final boolean isProtected() {
-        return (getModifiers() & Modifier.PROTECTED) != 0;
-    }
-
-    /**
-     * Returns whether or not this method is public.
-     * @return true if this method is public
-     */
-    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());
-    }
-
-    /**
-     * Checks the compatibility between two modifier masks. Checks that they are equal
-     * with regards to access and static modifier.
-     *
-     * @return true if the modifiers are compatible
-     */
-    private static boolean compatibleModifiers(int modifiersA, int modifiersB) {
-        int mask = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC | Modifier.STATIC;
-        return (modifiersA & mask) == (modifiersB & mask);
-    }
-
-    /**
-     * Returns whether this object is cacheable
-     */
-    public boolean isCacheable() {
-        return true;
-    }
-
-    /**
-     * Return a descriptor of this method based on the return type and parameters of this method.
-     */
-    public String getDescriptor() {
-        return BytecodeHelper.getMethodDescriptor(getReturnType(), getNativeParameterTypes());
-    }
-
-    /**
-     * Returns the signature of this method
-     *
-     * @return The signature of this method
-     */
-    public synchronized String getSignature() {
-        if (signature == null) {
-            CachedClass [] parameters = getParameterTypes();
-            final String name = getName();
-            StringBuilder buf = new StringBuilder(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;
-    }
-
-    /**
-     * This method is called when an exception occurs while invoking this method.
-     */
-    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);
-    }
-
-    /**
-     * Invokes the method this object represents. 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
-     *
-     * @param object The object the method is to be called at.
-     * @param argumentArray Arguments for the method invocation.
-     * @return The return value of the invoked method.
-     */
-    public Object doMethodInvoke(Object object, Object[] argumentArray) {
-        argumentArray = coerceArgumentsToClasses(argumentArray);
-        try {
-            return invoke(object, argumentArray);
-        } catch (Exception e) {
-            throw processDoMethodInvokeException(e, object, argumentArray);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaObjectProtocol.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaObjectProtocol.java b/src/main/groovy/lang/MetaObjectProtocol.java
deleted file mode 100644
index 4218831..0000000
--- a/src/main/groovy/lang/MetaObjectProtocol.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.List;
-
-/**
- * <p>An interface that defines the API usable by clients of Groovy's Meta Object Protocol (MOP). These methods are
- * implemented by the reference implementation of the {@link groovy.lang.MetaClass} interface.
- *
- * @see MetaClassImpl
- * @author John Wilson
- * @author Graeme Rocher
- */
-public interface MetaObjectProtocol {
-
-    /**
-     * Obtain a list of all meta properties available on this meta class
-     *
-     * @see groovy.lang.MetaProperty
-     * @return A list of MetaProperty instances
-     */
-    List<MetaProperty> getProperties();
-    /**
-     * Obtain a list of all the meta methods available on this meta class
-     *
-     * @see groovy.lang.MetaMethod
-     * @return A list of MetaMethod instances
-     */
-    List<MetaMethod> getMethods();
-    
-    /**
-     * <p>Returns an object satisfying Groovy truth if the implementing MetaClass responds to
-     * a method with the given name and arguments types.
-     *
-     * <p>Note that this method's return value is based on realised methods and does not take into account
-     * objects or classes that implement invokeMethod or methodMissing
-     *
-     * <p>This method is "safe" in that it will always return a value and never throw an exception
-     *
-     * @param obj The object to inspect
-     * @param name The name of the method of interest
-     * @param argTypes The argument types to match against
-     * @return A List of MetaMethods matching the argument types which will be empty if no matching methods exist
-     */
-    List<MetaMethod> respondsTo(Object obj, String name, Object[] argTypes);
-
-    /**
-     * <p>Returns an object satisfying Groovy truth if the implementing MetaClass responds to
-     * a method with the given name regardless of arguments. In other words this method will
-     * return for foo() and foo(String).
-     *
-     * <p>Note that this method's return value is based on realised methods and does not take into account
-     * objects or classes that implement invokeMethod or methodMissing
-     *
-     * <p>This method is "safe" in that it will always return a value and never throw an exception
-     *
-     * @param obj The object to inspect
-     * @param name The name of the method of interest
-     * @return A List of MetaMethods which will be empty if no methods with the given name exist
-     */
-    List<MetaMethod> respondsTo(Object obj, String name);
-
-    /**
-     * <p>Returns true of the implementing MetaClass has a property of the given name
-     *
-     * <p>Note that this method will only return true for realised properties and does not take into
-     * account implementation of getProperty or propertyMissing
-     *
-     * @param obj The object to inspect
-     * @param name The name of the property
-     * @return The MetaProperty or null if it doesn't exist
-     */
-    MetaProperty hasProperty(Object obj, String name);
-
-    /**
-     * Returns a MetaProperty for the given name or null if it doesn't exist
-     *
-     * @param name The name of the MetaProperty
-     * @return A MetaProperty or null
-     */
-    MetaProperty getMetaProperty(String name);
-
-    /**
-     * Retrieves a static MetaMethod for the given name and argument values, using the types of the arguments
-     * to establish the chosen MetaMethod
-     *
-     * @param name The name of the MetaMethod
-     * @param args The argument types
-     * @return A MetaMethod or null if it doesn't exist
-     */
-    MetaMethod getStaticMetaMethod(String name, Object[] args);
-
-
-    /**
-     * Retrieves an instance MetaMethod for the given name and argument values, using the types of the
-     * argument values to establish the chosen MetaMethod
-     *
-     * @param name The name of the MetaMethod
-     * @param args Array containing - 1) the argument values (using which their types are then inferred), or 2) the corresponding argument types  
-     * @return A MetaMethod or null if it doesn't exist
-     */
-    MetaMethod getMetaMethod(String name, Object[] args);
-
-    /**
-     * Retrieves that Java Class that the attached Meta behaviours apply to
-     *
-     * @return The java.lang.Class instance
-     */
-    Class getTheClass();
-
-    /**
-     * Invokes a constructor for the given arguments. The MetaClass will attempt to pick the best argument which
-     * matches the types of the objects passed within the arguments array
-     *
-     * @param arguments The arguments to the constructor
-     * @return An instance of the java.lang.Class that this MetaObjectProtocol object applies to
-     */
-    Object invokeConstructor(Object[] arguments);
-
-    /**
-     * Invokes a method on the given Object with the given name and arguments. The MetaClass will attempt to pick
-     * the best method for the given name and arguments. If a method cannot be invoked a MissingMethodException will be
-     * thrown.
-     *
-     * @see groovy.lang.MissingMethodException
-     * @param object The instance which the method is invoked on
-     * @param methodName The name of the method
-     * @param arguments The arguments to the method
-     * @return The return value of the method which is null if the return type is void
-     */
-    Object invokeMethod(Object object, String methodName, Object[] arguments);
-
-    /**
-     * Invokes a method on the given object, with the given name and single argument.
-     *
-     * @see #invokeMethod(Object, String, Object[])
-     * @param object The Object to invoke the method on
-     * @param methodName The name of the method
-     * @param arguments The argument to the method
-     * @return The return value of the method which is null if the return type is void
-     */
-     Object invokeMethod(Object object, String methodName, Object arguments);
-
-    /**
-     * Invokes a static method on the given Object with the given name and arguments.
-     * <p>
-     * The Object can either be an instance of the class that this
-     * MetaObjectProtocol instance applies to or the java.lang.Class instance itself. If a method cannot be invoked
-     * a MissingMethodException is will be thrown
-     *
-     * @see groovy.lang.MissingMethodException
-     * @param object An instance of the class returned by the getTheClass() method or the class itself
-     * @param methodName The name of the method
-     * @param arguments The arguments to the method
-     * @return The return value of the method which is null if the return type is void
-     */
-    Object invokeStaticMethod(Object object, String methodName, Object[] arguments);
-
-    /**
-     * Retrieves a property of an instance of the class returned by the getTheClass() method.
-     * <p>
-     * What this means is largely down to the MetaClass implementation, however the default case would result
-     * in an attempt to invoke a JavaBean getter, or if no such getter exists a public field of the instance.
-     *
-     * @see MetaClassImpl
-     * @param object An instance of the class returned by the getTheClass() method
-     * @param property The name of the property to retrieve the value for
-     * @return The properties value
-     */
-    Object getProperty(Object object, String property);
-
-    /**
-     * Sets a property of an instance of the class returned by the getTheClass() method.
-     * <p>
-     * What this means is largely down to the MetaClass implementation, however the default case would result
-     * in an attempt to invoke a JavaBean setter, or if no such setter exists to set a public field of the instance.
-     *
-     * @see MetaClassImpl
-     * @param object An instance of the class returned by the getTheClass() method
-     * @param property The name of the property to set
-     * @param newValue The new value of the property
-     */
-    void setProperty(Object object, String property, Object newValue);
-
-    /**
-     * Retrieves an attribute of an instance of the class returned by the getTheClass() method.
-     * <p>
-     * What this means is largely down to the MetaClass implementation, however the default case would result
-     * in attempt to read a field of the instance.
-     *
-     * @see MetaClassImpl
-     * @param object An instance of the class returned by the getTheClass() method
-     * @param attribute The name of the attribute to retrieve the value for
-     * @return The attribute value
-     */
-    Object getAttribute(Object object, String attribute);
-
-    /**
-     * Sets an attribute of an instance of the class returned by the getTheClass() method.
-     * <p>
-     * What this means is largely down to the MetaClass implementation, however the default case would result
-     * in an attempt to set a field of the instance.
-     *
-     * @see MetaClassImpl
-     * @param object An instance of the class returned by the getTheClass() method
-     * @param attribute The name of the attribute to set
-     * @param newValue The new value of the attribute
-     */
-    void setAttribute(Object object, String attribute, Object newValue);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaProperty.java b/src/main/groovy/lang/MetaProperty.java
deleted file mode 100644
index d3c9633..0000000
--- a/src/main/groovy/lang/MetaProperty.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.MetaClassHelper;
-
-import java.lang.reflect.Modifier;
-
-/**
- * Represents a property on a bean which may have a getter and/or a setter
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public abstract class MetaProperty {
-
-    protected final String name;
-    protected Class type;
-    public static final String PROPERTY_SET_PREFIX = "set";
-
-    /**
-     * Constructor that sets the property name and type (class)
-     */
-    public MetaProperty(String name, Class type) {
-        this.name = name;
-        this.type = type;
-    }
-
-    /**
-     * @return the property of the given object
-     * @throws Exception if the property could not be evaluated
-     */
-    public abstract Object getProperty(Object object);
-
-    /**
-     * Sets the property on the given object to the new value
-     * 
-     * @param object on which to set the property
-     * @param newValue the new value of the property
-     * @throws RuntimeException if the property could not be set
-     */
-    public abstract void setProperty(Object object, Object newValue);
-
-    /**
-     * Return the name of the property
-     *
-     * @return the name of the property
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @return the type of the property
-     */
-    public Class getType() {
-        return type;
-    }
-    
-    /**
-     * Returns the access modifier.
-     * @return Modifier.PUBLIC
-     */
-    public int getModifiers() {
-        return Modifier.PUBLIC;
-    }
-
-    /**
-     * Gets the name for the getter for this property
-     *
-     * @return The name of the property. The name is "get"+ the capitalized propertyName
-     *         or, in the case of boolean values, "is" + the capitalized propertyName
-     */
-    public static String getGetterName(String propertyName, Class type) {
-        String prefix = type == boolean.class || type == Boolean.class ? "is" : "get";
-        return prefix + MetaClassHelper.capitalize(propertyName);
-    }
-
-    /**
-     * Gets the setter for the getter for this property.
-     *
-     * @return The name of the property. The name is "set"+ the capitalized propertyName.
-     */
-    public static String getSetterName(String propertyName) {
-        return PROPERTY_SET_PREFIX + MetaClassHelper.capitalize(propertyName);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MissingClassException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MissingClassException.java b/src/main/groovy/lang/MissingClassException.java
deleted file mode 100644
index ad8e5f5..0000000
--- a/src/main/groovy/lang/MissingClassException.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-
-/**
- * An exception occurred if a dynamic method dispatch fails with an unknown class.
- * 
- * Note that the Missing*Exception classes were named for consistency and
- * to avoid conflicts with JDK exceptions of the same name.
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class MissingClassException extends GroovyRuntimeException {
-
-    private final String type;
-
-    public MissingClassException(String type, ASTNode node, String message) {
-        super("No such class: " + type + " " + message, node);
-        this.type = type;
-    }
-    
-    public MissingClassException(ClassNode type, String message){
-        super("No such class: " + type.getName() + " " + message);
-        this.type = type.getName();
-    }
-
-    /**
-     * 
-     * @return The type that could not be resolved
-     */
-    public String getType() {
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MissingFieldException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MissingFieldException.java b/src/main/groovy/lang/MissingFieldException.java
deleted file mode 100644
index 3c17d39..0000000
--- a/src/main/groovy/lang/MissingFieldException.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  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 groovy.lang;
-
-
-/**
- * An exception occurred if a dynamic field dispatch fails with an unknown field.
- * 
- * Note that the Missing*Exception classes were named for consistency and
- * to avoid conflicts with JDK exceptions of the same name.
- * 
- * @author <a href="mailto:jstrachan@protique.com">James Strachan</a>
- */
-public class MissingFieldException extends GroovyRuntimeException {
-
-    private final String field;
-    private final Class type;
-
-    public MissingFieldException(String field, Class type) {
-        super("No such field: " + field + " for class: " + type.getName());
-        this.field = field;
-        this.type = type;
-    }
-
-    public MissingFieldException(String field, Class type, Throwable e) {
-        super("No such field: " + field + " for class: " + type.getName() + ". Reason: " + e, e);
-        this.field = field;
-        this.type = type;
-    }
-
-    public MissingFieldException(String message, String field, Class type) {
-        super(message);
-        this.field = field;
-        this.type = type;
-    }
-
-    /**
-     * @return the name of the field that could not be found
-     */
-    public String getField() {
-        return field;
-    }
-
-    /**
-     * 
-     * @return The type on which the field was attempted to be called
-     */
-    public Class getType() {
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MissingMethodException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MissingMethodException.java b/src/main/groovy/lang/MissingMethodException.java
deleted file mode 100644
index 0902150..0000000
--- a/src/main/groovy/lang/MissingMethodException.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.MethodRankHelper;
-
-/**
- * An exception occurred if a dynamic method dispatch fails with an unknown method.
- * <p>
- * Note that the Missing*Exception classes were named for consistency and
- * to avoid conflicts with JDK exceptions of the same name.
- */
-public class MissingMethodException extends GroovyRuntimeException {
-
-    private final String method;
-    private final Class type;
-    private final boolean isStatic;
-
-    public Object[] getArguments() {
-        return arguments;
-    }
-
-    private final Object arguments[];
-
-    public MissingMethodException(String method, Class type, Object[] arguments) {
-        this(method, type, arguments, false);
-    }
-
-    public MissingMethodException(String method, Class type, Object[] arguments, boolean isStatic) {
-        super();
-        this.method = method;
-        this.type = type;
-        this.isStatic = isStatic;
-        this.arguments = arguments;
-    }
-
-    public String getMessage() {
-        return "No signature of method: "
-                + (isStatic ? "static " : "")
-                + type.getName()
-                + "."
-                + method
-                + "() is applicable for argument types: ("
-                + InvokerHelper.toTypeString(arguments, 60)
-                + ") values: "
-                + InvokerHelper.toArrayString(arguments, 60, true)
-                + MethodRankHelper.getMethodSuggestionString(method, type, arguments);
-    }
-
-    /**
-     * @return the name of the method that could not be found
-     */
-    public String getMethod() {
-        return method;
-    }
-
-    /**
-     * @return The type on which the method was attempted to be called
-     */
-    public Class getType() {
-        return type;
-    }
-
-    /**
-     * @return Whether the method was called in a static way,
-     *         i.e. on a class rather than an object.
-     */
-    public boolean isStatic() {
-        return isStatic;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MissingPropertyException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MissingPropertyException.java b/src/main/groovy/lang/MissingPropertyException.java
deleted file mode 100644
index 270f039..0000000
--- a/src/main/groovy/lang/MissingPropertyException.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.MethodRankHelper;
-
-
-/**
- * An exception occurred if a dynamic property dispatch fails with an unknown property.
- * 
- * Note that the Missing*Exception classes were named for consistency and
- * to avoid conflicts with JDK exceptions of the same name.
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class MissingPropertyException extends GroovyRuntimeException {
-
-    public static final Object MPE = new Object();
-
-    private final String property;
-    private final Class type;
-
-    public MissingPropertyException(String property, Class type) {
-        this.property = property;
-        this.type = type;
-    }
-
-    public MissingPropertyException(String property, Class type, Throwable t) {
-        super(t);
-        this.property = property;
-        this.type = type;
-    }
-
-    public MissingPropertyException(String message) {
-        super(message);
-        this.property = null;
-        this.type = null;
-    }
-
-    public MissingPropertyException(String message, String property, Class type) {
-        super(message);
-        this.property = property;
-        this.type = type;
-    }
-
-    public String getMessageWithoutLocationText() {
-        final Throwable cause = getCause();
-        if (cause == null) {
-            if (super.getMessageWithoutLocationText() != null) {
-                return super.getMessageWithoutLocationText();
-            }
-            return "No such property: " + property + " for class: " + type.getName() +
-                   MethodRankHelper.getPropertySuggestionString(property, type);
-        }
-        return "No such property: " + property + " for class: " + type.getName() + ". Reason: " + cause;
-    }
-
-    /**
-     * @return the name of the property that could not be found
-     */
-    public String getProperty() {
-        return property;
-    }
-
-    /**
-     * 
-     * @return The type on which the property was attempted to be called
-     */
-    public Class getType() {
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Mixin.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Mixin.java b/src/main/groovy/lang/Mixin.java
deleted file mode 100644
index 22ef4b9..0000000
--- a/src/main/groovy/lang/Mixin.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Provides a mechanism for mixing in methods into a class.
- *
- * @deprecated static mixins have been deprecated in favour of traits (trait keyword).
- *
- * @author Alex Tkachman
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-@GroovyASTTransformationClass("org.codehaus.groovy.ast.MixinASTTransformation")
-@Deprecated
-public @interface Mixin {
-    Class [] value ();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MutableMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MutableMetaClass.java b/src/main/groovy/lang/MutableMetaClass.java
deleted file mode 100644
index 903c895..0000000
--- a/src/main/groovy/lang/MutableMetaClass.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.reflect.Method;
-
-/**
- * An interface that defines methods that implementers of mutable Meta classes should specify. It provides operations to perform mutations
- * on the MetaClass instance.
- * <p>
- * Whether a MetaClass allows mutation is up to the MetaClass itself and considerations of Thread safety
- * need to be taken into account when making a MetaClass mutable
- * <p>
- * The default implementation allows mutation of MetaClass instances before initialisation (before the initialize() method is called)
- * but not after, thus ensuring Thread safety once a MetaClass has been constructed and placed in the registry
- *
- * @see MetaClassImpl
- * @see MetaClass
- * @author Graeme Rocher
- * @since 1.5
- */
-public interface MutableMetaClass extends MetaClass {
-
-    /**
-     * Return whether the MetaClass has been modified or not
-     * @return True if it has
-     */
-    boolean isModified();
-
-    /**
-     * adds a new instance method to this MetaClass. Instance
-     * methods are able to overwrite the original methods of the
-     * class. Calling this method should not be done after
-     * initialise was called.
-     *
-     * @param method the method to be added
-     */
-     void addNewInstanceMethod(Method method);
-
-    /**
-     * adds a new static method to this MetaClass. This is only
-     * possible as long as initialise was not called.
-     *
-     * @param method the method to be added
-     */
-     void addNewStaticMethod(Method method);
-
-    /**
-     * Adds a new MetaMethod to the MetaClass
-     *
-     * @param metaMethod The MetaMethod to add
-     */
-    void addMetaMethod(MetaMethod metaMethod);
-
-    /**
-     * Adds a new MetaBeanProperty to the MetaClass
-     *
-     * @param metaBeanProperty The MetaBeanProperty instance
-     */
-    void addMetaBeanProperty(MetaBeanProperty metaBeanProperty);
-    
-    // TODO: Add methods like addMetaConstructor, addMetaAttribute, addMetaAnnotation etc.
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Newify.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Newify.java b/src/main/groovy/lang/Newify.java
deleted file mode 100644
index 5bf7fdf..0000000
--- a/src/main/groovy/lang/Newify.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation that supports writing constructor call expressions without the 'new'
- * keyword. Instead they can be written "Ruby-style" as a method call to a 'new'
- * method or "Python-style" by just omitting the 'new' keyword.
- * <p>
- * It allows you to write code snippets like this ("Python-style"):
- * <pre>
- * {@code @Newify([Tree,Leaf])} class MyTreeProcessor {
- *     def myTree = Tree(Tree(Leaf("A"), Leaf("B")), Leaf("C"))
- *     def process() { ... }
- * }
- * </pre>
- * or this ("Ruby-style"):
- * <pre>
- * {@code @Newify} class MyTreeProcessor {
- *     def myTree = Tree.new(Tree.new(Leaf.new("A"), Leaf.new("B")), Leaf.new("C"))
- *     def process() { ... }
- * }
- * </pre>
- *
- * After the AST transformation, the following code is passed on for further compilation:
- * <pre>
- * class MyTreeProcessor {
- *     def myTree = new Tree(new Tree(new Leaf("A"), new Leaf("B")), new Leaf("C"))
- *     def process() { ... }
- * }
- * </pre>
- * The annotation can be used on a whole class as shown above or selectively on a particular
- * method, constructor or field.
- * <p>
- * The "Ruby-style" new conversions occur automatically unless the 'auto=false'
- * flag is given when using the annotation. You might do this if you create a new method
- * using meta programming.
- * <p>
- * The "Python-style" conversions require you to specify each class on which you want them
- * to apply. The transformation then works by matching the basename of the provided classes to any
- * similarly named instance method calls not specifically bound to an object, i.e. associated
- * with the 'this' object. In other words <code>Leaf("A")</code> would be transformed to
- * <code>new Leaf("A")</code> but <code>x.Leaf("A")</code> would not be touched.
- * <p>
- * An example showing how to use the annotation at different levels:
- * <pre>
- * {@code @Newify(auto=false, value=Foo)}
- * class Main {
- *     {@code @Newify} // turn auto on for field
- *     def field1 = java.math.BigInteger.new(42)
- *     def field2, field3, field4
- *
- *     {@code @Newify(Bar)}
- *     def process() {
- *         field2 = Bar("my bar")
- *     }
- *
- *     {@code @Newify(Baz)}
- *     Main() {
- *         field3 = Foo("my foo")
- *         field4 = Baz("my baz")
- *     }
- * }
- * </pre>
- *
- * The annotation is intended to be used sparingly; perhaps in DSL scenarios or when
- * using deeply nested structural types. In particular, there is no support for using
- * the facility with two similarly named classes from different packages at the same time.
- * Though it is OK to have different packages in different contexts. Also, there is
- * no support for turning "Ruby-style" conversions off at the method, constructor or
- * field level if already turned on at the class level.
- *
- * @author Paul King
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.NewifyASTTransformation")
-public @interface Newify {
-    Class<?>[] value() default {};
-
-    /**
-     * @return if automatic conversion of "Ruby-style" new method calls should occur
-     */
-    boolean auto() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/NonEmptySequence.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/NonEmptySequence.java b/src/main/groovy/lang/NonEmptySequence.java
deleted file mode 100644
index f069b7a..0000000
--- a/src/main/groovy/lang/NonEmptySequence.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.List;
-
-/**
- * Represents a sequence of objects which represents one or many instances of
- * of objects of a given type. The type can be omitted in which case any type of
- * object can be added.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class NonEmptySequence extends Sequence {
-
-    public NonEmptySequence() {
-        super(null);
-    }
-
-    public NonEmptySequence(Class type) {
-        super(type);
-    }
-
-    public NonEmptySequence(Class type, List content) {
-        super(type, content);
-    }
-
-    public int minimumSize() {
-        return 1;
-    }
-}
\ No newline at end of file


[21/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/FileVisitResult.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/FileVisitResult.java b/src/main/groovy/io/FileVisitResult.java
deleted file mode 100644
index 2c73dd1..0000000
--- a/src/main/groovy/io/FileVisitResult.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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 groovy.io;
-
-/**
- * Represents special return values for the 'preDir', 'postDir' and 'visit'/supplied Closures used with
- * {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#traverse(java.io.File, java.util.Map, groovy.lang.Closure)}
- * and related methods to control subsequent traversal behavior.
- */
-public enum FileVisitResult {
-    /** Continue processing; the default */
-    CONTINUE,
-    /** Skip processing sibling files/directories within the current directory being processed */
-    SKIP_SIBLINGS,
-    /** Do not process the child files/subdirectories within the current directory being processed */
-    SKIP_SUBTREE,
-    /** Do not process any more files */
-    TERMINATE
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/GroovyPrintStream.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/GroovyPrintStream.java b/src/main/groovy/io/GroovyPrintStream.java
deleted file mode 100644
index d77c5aa..0000000
--- a/src/main/groovy/io/GroovyPrintStream.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- *  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 groovy.io;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-
-/**
- * A PrintStream that outputs objects in Groovy style.
- * That means print(Object) uses InvokerHelper.toString(Object)
- * to produce the same results as Writer.print(Object).
- *
- * @author Jim White
- * @since 1.6
- */
-public class GroovyPrintStream extends PrintStream
-{
-    /**
-     * Creates a new print stream.  This stream will not flush automatically.
-     *
-     * @see java.io.PrintStream#PrintStream(java.io.OutputStream)
-     */
-    public GroovyPrintStream(OutputStream out) {
-        super(out, false);
-    }
-
-    /**
-     * Creates a new print stream.
-     *
-     * @see java.io.PrintStream#PrintStream(java.io.OutputStream, boolean)
-     */
-    public GroovyPrintStream(OutputStream out, boolean autoFlush) {
-        super(out, autoFlush);
-    }
-
-    /**
-     * Creates a new print stream.
-     *
-     * @see java.io.PrintStream#PrintStream(java.io.OutputStream, boolean, String)
-     */
-    public GroovyPrintStream(OutputStream out, boolean autoFlush, String encoding)
-        throws UnsupportedEncodingException
-    {
-        super(out, autoFlush, encoding);
-    }
-
-    /**
-     * Creates a new print stream, without automatic line flushing, with the
-     * specified file name.
-     *
-     * @see java.io.PrintStream#PrintStream(String)
-     */
-    public GroovyPrintStream(String fileName) throws FileNotFoundException {
-        super(fileName);
-    }
-
-    /**
-     * Creates a new print stream, without automatic line flushing, with the
-     * specified file name and charset. 
-     *
-     * @see java.io.PrintStream#PrintStream(String, String)
-     */
-    public GroovyPrintStream(String fileName, String csn)
-        throws FileNotFoundException, UnsupportedEncodingException
-    {
-        super(fileName, csn);
-    }
-
-    /**
-     * Creates a new print stream, without automatic line flushing, with the
-     * specified file. 
-     *
-     * @see java.io.PrintStream#PrintStream(File)
-     */
-    public GroovyPrintStream(File file) throws FileNotFoundException {
-        super(file);
-    }
-
-    /**
-     * Creates a new print stream, without automatic line flushing, with the
-     * specified file and charset. 
-     *
-     * @see java.io.PrintStream#PrintStream(File, String)
-     */
-    public GroovyPrintStream(File file, String csn)
-        throws FileNotFoundException, UnsupportedEncodingException
-    {
-        super(file, csn);
-    }
-
-    /**
-     * Prints an object Groovy style.
-     *
-     * @param      obj   The <code>Object</code> to be printed
-     */
-    public void print(Object obj) {
-        print(InvokerHelper.toString(obj));
-    }
-
-    /**
-     * Prints an object Groovy style followed by a newline.  
-     *
-     * @param      obj   The <code>Object</code> to be printed
-     */
-    public void println(Object obj) {
-        println(InvokerHelper.toString(obj));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/GroovyPrintWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/GroovyPrintWriter.java b/src/main/groovy/io/GroovyPrintWriter.java
deleted file mode 100644
index 0a076b9..0000000
--- a/src/main/groovy/io/GroovyPrintWriter.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *  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 groovy.io;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-
-/**
- * A PrintWriter that outputs objects in Groovy style.
- * That means print(Object) uses InvokerHelper.toString(Object)
- * to produce the same results as Writer.print(Object).
- *
- * @author Jim White
- * @since 1.6
- */
-public class GroovyPrintWriter extends PrintWriter 
-{
-    public GroovyPrintWriter(File file) throws FileNotFoundException
-    {
-        super(file);
-    }
-
-    public GroovyPrintWriter(File file, String csn)
-        throws FileNotFoundException, UnsupportedEncodingException
-    {
-        super(file, csn);
-    }
-
-    public GroovyPrintWriter(Writer out) 
-    {
-        super(out);
-    }
-
-    public GroovyPrintWriter(Writer out, boolean autoflush) 
-    {
-        super(out, autoflush);
-    }
-
-    public GroovyPrintWriter(OutputStream out) 
-    {
-        super(out);
-    }
-
-    public GroovyPrintWriter(OutputStream out, boolean autoflush) 
-    {
-        super(out, autoflush);
-    }
-
-    public GroovyPrintWriter(String filename) throws FileNotFoundException 
-    {
-        super(filename);
-    }
-
-    public GroovyPrintWriter(String filename, String csn)
-        throws FileNotFoundException, UnsupportedEncodingException 
-    {
-        super(filename, csn);
-    }
-        
-// Don't need to do this if Groovy is going to print char[] like a string.
-//    public void print(char[] x) 
-//    {
-//        write(InvokerHelper.toString(x));
-//    }
-
-    public void print(Object x) 
-    {
-        write(InvokerHelper.toString(x));
-    }
-
-    public void println(Object x) 
-    {
-        // JDK 1.6 has changed the implementation to do a
-        // String.valueOf(x) rather than call print(x).
-        // Probably to improve performance by doing the conversion outside the lock.
-        // This will do the same thing for us, and we don't have to have access to the lock.
-        println(InvokerHelper.toString(x));
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/LineColumnReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/LineColumnReader.java b/src/main/groovy/io/LineColumnReader.java
deleted file mode 100644
index 49b7c94..0000000
--- a/src/main/groovy/io/LineColumnReader.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- *  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 groovy.io;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.nio.CharBuffer;
-
-/**
- * The <code>LineColumnReader</code> is an extension to <code>BufferedReader</code>
- * that keeps track of the line and column information of where the cursor is.
- *
- * @author Guillaume Laforge
- * @since 1.8.0
- */
-public class LineColumnReader extends BufferedReader {
-
-    /**
-     * The current line position
-     */
-    private long line = 1;
-
-    /**
-     * The current column position
-     */
-    private long column = 1;
-
-    /**
-     * The latest marked line position
-     */
-    private long lineMark = 1;
-
-    /**
-     * The latest marked line position
-     */
-    private long columnMark = 1;
-
-    private boolean newLineWasRead = false;
-
-    /**
-     * Constructor wrapping a <code>Reader</code>
-     * (<code>FileReader</code>, <code>FileReader</code>, <code>InputStreamReader</code>, etc.)
-     *
-     * @param reader the reader to wrap
-     */
-    public LineColumnReader(Reader reader) {
-        super(reader);
-    }
-
-    /**
-     * Marks the present position in the stream. Subsequent calls to reset() will attempt to reposition the stream to this point.
-     *
-     * @param readAheadLimit  Limit on the number of characters that may be read while still preserving the mark.
-     *      An attempt to reset the stream after reading characters up to this limit or beyond may fail.
-     *      A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit.
-     *      Therefore large values should be used with care.
-     */
-    @Override
-    public void mark(int readAheadLimit) throws IOException {
-        lineMark = line;
-        columnMark = column;
-        super.mark(readAheadLimit);
-    }
-
-    /**
-     * Resets the stream to the most recent mark.
-     */
-    @Override
-    public void reset() throws IOException {
-        line = lineMark;
-        column = columnMark;
-        super.reset();
-    }
-
-    /**
-     * Reads a single character.
-     *
-     * @return The character read, as an integer in the range 0 to 65535 (0x00-0xffff),
-     *      or -1 if the end of the stream has been reached
-     */
-    @Override
-    public int read() throws IOException {
-        if (newLineWasRead) {
-            line += 1;
-            column = 1;
-            newLineWasRead = false;
-        }
-
-        int charRead = super.read();
-        if (charRead > -1) {
-            char c = (char)charRead;
-            // found a \r or \n, like on Mac or Unix
-            // could also be Windows' \r\n
-            if (c == '\r' || c == '\n') {
-                newLineWasRead = true;
-                if (c == '\r') {
-                    mark(1);
-                    c = (char)super.read();
-                    // check if we have \r\n like on Windows
-                    // if it's not \r\n we reset, otherwise, the \n is just consummed
-                    if (c != '\n') {
-                        reset();
-                    }
-                }
-            } else {
-                column += 1;
-            }
-        }
-
-        return charRead;
-    }
-
-    /**
-     * Reads characters into a portion of an array.
-     *
-     * @param chars Destination array of char
-     * @param startOffset Offset at which to start storing characters
-     * @param length Maximum number of characters to read
-     * @return an exception if an error occurs
-     */
-    @Override
-    public int read(char[] chars, int startOffset, int length) throws IOException {
-        for (int i = startOffset; i <= startOffset + length; i++) {
-            int readInt = read();
-            if (readInt == -1) return i - startOffset;
-            chars[i] = (char)readInt;
-        }
-        return length;
-    }
-
-    /**
-     * Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'),
-     * a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
-     *
-     * @return A String containing the contents of the line, not including any line-termination characters,
-     *      or null if the end of the stream has been reached
-     */
-    @Override
-    public String readLine() throws IOException {
-        StringBuilder result = new StringBuilder();
-        for (;;) {
-            int intRead = read();
-            if (intRead == -1) {
-                return result.length() == 0 ? null : result.toString();
-            }
-
-            char c = (char)intRead;
-            if (c == '\n' || c == '\r') break;
-            result.append(c);
-        }
-        return result.toString();
-    }
-
-    /**
-     * Skips characters.
-     *
-     * @param toSkip the number of characters to skip
-     * @return The number of characters actually skipped
-     */
-    @Override
-    public long skip(long toSkip) throws IOException {
-        for (long i = 0; i < toSkip; i++) {
-            int intRead = read();
-            if (intRead == -1) return i;
-        }
-        return toSkip;
-    }
-
-    /**
-     * Reads characters into an array.
-     * This method will block until some input is available, an I/O error occurs,
-     *  or the end of the stream is reached.
-     *
-     * @param chars Destination buffer
-     * @return The number of characters read, or -1 if the end of the stream has been reached
-     */
-    @Override
-    public int read(char[] chars) throws IOException {
-        return read(chars, 0, chars.length - 1);
-    }
-
-    /**
-     * Not implemented.
-     *
-     * @param buffer Destination buffer
-     * @return The number of characters read, or -1 if the end of the stream has been reached
-     * @throws UnsupportedOperationException as the method is not implemented
-     */
-    @Override
-    public int read(CharBuffer buffer) {
-        throw new UnsupportedOperationException("read(CharBuffer) not yet implemented");
-    }
-
-    /**
-     * Closes the stream and releases any system resources associated with it.
-     * Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations
-     * will throw an IOException. Closing a previously closed stream has no effect.
-     */
-    @Override
-    public void close() throws IOException {
-        super.close();
-    }
-
-    public long getColumn() {
-        return column;
-    }
-
-    public void setColumn(long column) {
-        this.column = column;
-    }
-
-    public long getColumnMark() {
-        return columnMark;
-    }
-
-    public void setColumnMark(long columnMark) {
-        this.columnMark = columnMark;
-    }
-
-    public long getLine() {
-        return line;
-    }
-
-    public void setLine(long line) {
-        this.line = line;
-    }
-
-    public long getLineMark() {
-        return lineMark;
-    }
-
-    public void setLineMark(long lineMark) {
-        this.lineMark = lineMark;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/PlatformLineWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/PlatformLineWriter.java b/src/main/groovy/io/PlatformLineWriter.java
deleted file mode 100644
index 0071e0f..0000000
--- a/src/main/groovy/io/PlatformLineWriter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  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 groovy.io;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * A buffered writer that gobbles any \r characters
- * and replaces every \n with a platform specific newline.
- * In many places Groovy normalises streams to only have \n
- * characters but when creating files that must be used
- * by other platform-aware tools, you sometimes want the
- * newlines to match what the platform expects.
- *
- * @author Paul King
- */
-public class PlatformLineWriter extends Writer {
-    private final BufferedWriter writer;
-
-    public PlatformLineWriter(Writer out) {
-        writer = new BufferedWriter(out);
-    }
-
-    public PlatformLineWriter(Writer out, int sz) {
-        writer = new BufferedWriter(out, sz);
-    }
-
-    public void write(char cbuf[], int off, int len) throws IOException {
-        for (; len > 0; len--) {
-            char c = cbuf[off++];
-            if (c == '\n') {
-                writer.newLine();
-            } else if (c != '\r') {
-                writer.write(c);
-            }
-        }
-    }
-
-    public void flush() throws IOException {
-        writer.flush();
-    }
-
-    public void close() throws IOException {
-        writer.close();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/package.html b/src/main/groovy/io/package.html
deleted file mode 100644
index fef0d09..0000000
--- a/src/main/groovy/io/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-
-     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 groovy.io.*</title>
-  </head>
-  <body>
-    <p>Classes for Groovier Input/Output.</p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/AdaptingMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/AdaptingMetaClass.java b/src/main/groovy/lang/AdaptingMetaClass.java
deleted file mode 100644
index 81afc26..0000000
--- a/src/main/groovy/lang/AdaptingMetaClass.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * An interface for MetaClass instances that "adapt" other MetaClass instances such as a proxy or
- * delegating MetaClass.
- *
- * @author Graeme Rocher
- * @since 1.5
- */
-public interface AdaptingMetaClass extends MetaClass {
-
-    /**
-     * Returns the MetaClass that this adapter adapts
-     *
-     * @return The MetaClass instance
-     */
-    MetaClass getAdaptee();
-
-    /**
-     * Sets the MetaClass adapted by this MetaClass
-     *
-     * @param metaClass The MetaClass to adapt
-     */
-    void setAdaptee(MetaClass metaClass);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/BenchmarkInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/BenchmarkInterceptor.java b/src/main/groovy/lang/BenchmarkInterceptor.java
deleted file mode 100644
index 77bcb64..0000000
--- a/src/main/groovy/lang/BenchmarkInterceptor.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Interceptor that registers the timestamp of each method call
- * before and after invocation. The timestamps are stored internally
- * and can be retrieved through the with the <pre>getCalls()</pre> 
- * and <pre>statistic()</pre> API.
- * <p>
- * Example usage:
- * <pre>
- * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
- * proxy.interceptor = new BenchmarkInterceptor()
- * proxy.use {
- *     def list = (0..10000).collect{ it }
- *     4.times { list.size() }
- *     4000.times { list.set(it, it+1) }
- * }
- * proxy.interceptor.statistic()
- * </pre>
- * Which produces the following output: 
- * <pre>
- * [[size, 4, 0], [set, 4000, 21]]
- * </pre>
- */
-public class BenchmarkInterceptor implements Interceptor {
-
-    protected Map calls = new LinkedHashMap(); // keys to list of invocation times and before and after
-
-    /**
-    * Returns the raw data associated with the current benchmark run. 
-    */ 
-    public Map getCalls() {
-        return calls;
-    }
-    
-    /**
-    * Resets all the benchmark data on this object. 
-    */
-    public void reset() {
-        calls = new HashMap();
-    }
-    /**
-     * This code is executed before the method is called.
-     * @param object        receiver object for the method call
-     * @param methodName    name of the method to call
-     * @param arguments     arguments to the method call
-     * @return null
-     * relays this result.
-     */
-    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
-        if (!calls.containsKey(methodName)) calls.put(methodName, new LinkedList());
-        ((List) calls.get(methodName)).add(Long.valueOf(System.currentTimeMillis()));
-
-        return null;
-    }
-    /**
-     * This code is executed after the method is called.
-     * @param object        receiver object for the called method
-     * @param methodName    name of the called method
-     * @param arguments     arguments to the called method
-     * @param result        result of the executed method call or result of beforeInvoke if method was not called
-     * @return result
-     */
-    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
-        ((List) calls.get(methodName)).add(Long.valueOf(System.currentTimeMillis()));
-        return result;
-    }
-
-    /**
-     * The call should be invoked separately
-     * @return true
-     */
-    public boolean doInvoke() {
-        return true;
-    }
-
-    /**
-     * Returns benchmark statistics as a List&lt;Object[]&gt;. 
-     * AccumulateTime is measured in milliseconds and is as accurate as
-     * System.currentTimeMillis() allows it to be. 
-     * @return a list of lines, each item is [methodname, numberOfCalls, accumulatedTime]
-     */
-    public List statistic() {
-        List result = new LinkedList();
-        for (Iterator iter = calls.keySet().iterator(); iter.hasNext();) {
-            Object[] line = new Object[3];
-            result.add(line);
-            line[0] = iter.next();
-            List times = (List) calls.get(line[0]);
-            line[1] = Integer.valueOf(times.size() / 2);
-            int accTime = 0;
-            for (Iterator it = times.iterator(); it.hasNext();) {
-                Long start = (Long) it.next();
-                Long end = (Long) it.next();
-                accTime += end.longValue() - start.longValue();
-            }
-            line[2] = Long.valueOf(accTime);
-        }
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Binding.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Binding.java b/src/main/groovy/lang/Binding.java
deleted file mode 100644
index 6505ea5..0000000
--- a/src/main/groovy/lang/Binding.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Represents the variable bindings of a script which can be altered
- * from outside the script object or created outside of a script and passed
- * into it.
- * <p> Binding instances are not supposed to be used in a multi-threaded context.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class Binding extends GroovyObjectSupport {
-    private Map variables;
-
-    public Binding() {
-    }
-
-    public Binding(Map variables) {
-        this.variables = variables;
-    }
-
-    /**
-     * A helper constructor used in main(String[]) method calls
-     *
-     * @param args are the command line arguments from a main()
-     */
-    public Binding(String[] args) {
-        this();
-        setVariable("args", args);
-    }
-
-    /**
-     * @param name the name of the variable to lookup
-     * @return the variable value
-     */
-    public Object getVariable(String name) {
-        if (variables == null)
-            throw new MissingPropertyException(name, this.getClass());
-
-        Object result = variables.get(name);
-
-        if (result == null && !variables.containsKey(name)) {
-            throw new MissingPropertyException(name, this.getClass());
-        }
-
-        return result;
-    }
-
-    /**
-     * Sets the value of the given variable
-     *
-     * @param name  the name of the variable to set
-     * @param value the new value for the given variable
-     */
-    public void setVariable(String name, Object value) {
-        if (variables == null)
-            variables = new LinkedHashMap();
-        variables.put(name, value);
-    }
-    
-    /**
-     * Simple check for whether the binding contains a particular variable or not.
-     * 
-     * @param name the name of the variable to check for
-     */
-    public boolean hasVariable(String name) {
-        return variables != null && variables.containsKey(name);
-    }
-
-    public Map getVariables() {
-        if (variables == null)
-            variables = new LinkedHashMap();
-        return variables;
-    }
-
-    /**
-     * Overloaded to make variables appear as bean properties or via the subscript operator
-     */
-    public Object getProperty(String property) {
-        /** @todo we should check if we have the property with the metaClass instead of try/catch  */
-        try {
-            return super.getProperty(property);
-        }
-        catch (MissingPropertyException e) {
-            return getVariable(property);
-        }
-    }
-
-    /**
-     * Overloaded to make variables appear as bean properties or via the subscript operator
-     */
-    public void setProperty(String property, Object newValue) {
-        /** @todo we should check if we have the property with the metaClass instead of try/catch  */
-        try {
-            super.setProperty(property, newValue);
-        }
-        catch (MissingPropertyException e) {
-            setVariable(property, newValue);
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Buildable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Buildable.java b/src/main/groovy/lang/Buildable.java
deleted file mode 100644
index af22958..0000000
--- a/src/main/groovy/lang/Buildable.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  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 groovy.lang;
-
-
-public interface Buildable {
-    void build(GroovyObject builder);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Category.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Category.java b/src/main/groovy/lang/Category.java
deleted file mode 100644
index f880828..0000000
--- a/src/main/groovy/lang/Category.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Transforms an instance-style Groovy class or interface to become a static-style
- * conventional Groovy category.
- * <p>
- * Groovy categories are the original mechanism used
- * by Groovy when augmenting classes with new methods. Writing categories required
- * using a class writing style where all methods were static and an additional
- * self parameter was defined. The self parameter and static nature of the methods
- * disappeared once applied by Groovy's metaclass framework but some regarded
- * the writing style as a little noisy. This transformation allows you to write
- * your categories without the "apparent noise" but adds it back in during
- * compilation so that the classes appear as normal categories.
- * <p>
- * It might seem strange writing your class/object enhancements using a succinct
- * notation, then having "noise" added, then having the noise removed during
- * category application. If this worries you, then you may also like to consider
- * using Groovy's {@code ExpandoMetaClass} mechanism which avoids
- * the category definition altogether. If you already have an investment in
- * categories or like some of the other features which categories currently give you,
- * then read on.
- * <p>
- * The mechanics: during compilation, all methods are transformed to static ones with an additional
- * self parameter of the type you supply as the annotation parameter (the default type
- * for the self parameters is {@code Object} which might be more broad reaching than
- * you like so it is usually wise to specify a type).
- * Properties invoked using 'this' references are transformed so that
- * they are instead invoked on the additional self parameter and not on
- * the Category instance. (Remember that once the category is applied, the reverse
- * will occur and we will be back to conceptually having methods on the {@code this}
- * references again!)
- * <p>
- * Classes conforming to the conventional Groovy category conventions can be used
- * within {@code use} statements or mixed in at runtime with the {@code mixin} method on classes.
- * <p>
- * An example showing a {@code use} statement (allowing fine-grained application of
- * the category methods):
- * <pre class="groovyTestCase">
- * {@code @Category}(Integer)
- * class IntegerOps {
- *     def triple() {
- *         this * 3
- *     }
- * }
- *
- * use (IntegerOps) {
- *     assert 25.triple() == 75
- * }
- * </pre>
- * Or, "mixing in" your methods at runtime:
- * <pre class="groovyTestCase">
- * {@code @Category}(List)
- * class Shuffler {
- *     def shuffle() {
- *         def result = new ArrayList(this)
- *         Collections.shuffle(result)
- *         result
- *     }
- * }
- *
- * class Sentence extends ArrayList {
- *     Sentence(Collection initial) { super(initial) }
- * }
- * Sentence.mixin Shuffler
- *
- * def words = ["The", "quick", "brown", "fox"]
- * println new Sentence(words).shuffle()
- * // => [quick, fox, The, brown]       (order will vary)
- * </pre>
- *
- * @author Alex Tkachman
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target(ElementType.TYPE)
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.CategoryASTTransformation")
-public @interface Category {
-    Class value () default Object.class;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Closure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Closure.java b/src/main/groovy/lang/Closure.java
deleted file mode 100644
index 99d2ea9..0000000
--- a/src/main/groovy/lang/Closure.java
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.apache.groovy.internal.util.UncheckedThrow;
-import org.codehaus.groovy.reflection.ReflectionCache;
-import org.codehaus.groovy.reflection.stdclasses.CachedClosureClass;
-import org.codehaus.groovy.runtime.ComposedClosure;
-import org.codehaus.groovy.runtime.CurriedClosure;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
-import org.codehaus.groovy.runtime.memoize.LRUCache;
-import org.codehaus.groovy.runtime.memoize.Memoize;
-import org.codehaus.groovy.runtime.memoize.UnlimitedConcurrentCache;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * Represents any closure object in Groovy.
- * <p>
- * Groovy allows instances of Closures to be called in a
- * short form. For example:
- * <pre class="groovyTestCase">
- * def a = 1
- * def c = { a }
- * assert c() == 1
- * </pre>
- * To be able to use a Closure in this way with your own
- * subclass, you need to provide a doCall method with any
- * signature you want to. This ensures that
- * {@link #getMaximumNumberOfParameters()} and
- * {@link #getParameterTypes()} will work too without any
- * additional code. If no doCall method is provided a
- * closure must be used in its long form like
- * <pre class="groovyTestCase">
- * def a = 1
- * def c = {a}
- * assert c.call() == 1
- * </pre>
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author <a href="mailto:tug@wilson.co.uk">John Wilson</a>
- * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
- * @author Graeme Rocher
- * @author Paul King
- */
-public abstract class Closure<V> extends GroovyObjectSupport implements Cloneable, Runnable, GroovyCallable<V>, Serializable {
-
-    /**
-     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
-     * owner first, then the delegate (<b>this is the default strategy</b>).
-     *
-     * For example the following code:
-     * <pre>
-     * class Test {
-     *     def x = 30
-     *     def y = 40
-     *
-     *     def run() {
-     *         def data = [ x: 10, y: 20 ]
-     *         def cl = { y = x + y }
-     *         cl.delegate = data
-     *         cl()
-     *         assert x == 30
-     *         assert y == 70
-     *         assert data == [x:10, y:20]
-     *     }
-     * }
-     *
-     * new Test().run()
-     * </pre>
-     * Will succeed, because the x and y fields declared in the Test class shadow the variables in the delegate.<p>
-     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
-     */
-    public static final int OWNER_FIRST = 0;
-
-    /**
-     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
-     * delegate first then the owner.
-     *
-     * For example the following code:
-     * <pre class="groovyTestCase">
-     * class Test {
-     *     def x = 30
-     *     def y = 40
-     *
-     *     def run() {
-     *         def data = [ x: 10, y: 20 ]
-     *         def cl = { y = x + y }
-     *         cl.delegate = data
-     *         cl.resolveStrategy = Closure.DELEGATE_FIRST
-     *         cl()
-     *         assert x == 30
-     *         assert y == 40
-     *         assert data == [x:10, y:30]
-     *     }
-     * }
-     *
-     * new Test().run()
-     * </pre>
-     * This will succeed, because the x and y variables declared in the delegate shadow the fields in the owner class.<p>
-     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
-     */
-    public static final int DELEGATE_FIRST = 1;
-
-    /**
-     * With this resolveStrategy set the closure will resolve property references and methods to the owner only
-     * and not call the delegate at all. For example the following code :
-     *
-     * <pre>
-     * class Test {
-     *     def x = 30
-     *     def y = 40
-     *
-     *     def run() {
-     *         def data = [ x: 10, y: 20, z: 30 ]
-     *         def cl = { y = x + y + z }
-     *         cl.delegate = data
-     *         cl.resolveStrategy = Closure.OWNER_ONLY
-     *         cl()
-     *         println x
-     *         println y
-     *         println data
-     *     }
-     * }
-     *
-     * new Test().run()
-     * </pre>
-     *
-     * will throw "No such property: z" error because even if the z variable is declared in the delegate, no
-     * lookup is made.<p>
-     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
-     */
-    public static final int OWNER_ONLY = 2;
-
-    /**
-     * With this resolveStrategy set the closure will resolve property references and methods to the delegate
-     * only and entirely bypass the owner. For example the following code :
-     *
-     * <pre>
-     * class Test {
-     *     def x = 30
-     *     def y = 40
-     *     def z = 50
-     *
-     *     def run() {
-     *         def data = [ x: 10, y: 20 ]
-     *         def cl = { y = x + y + z }
-     *         cl.delegate = data
-     *         cl.resolveStrategy = Closure.DELEGATE_ONLY
-     *         cl()
-     *         println x
-     *         println y
-     *         println data
-     *     }
-     * }
-     *
-     * new Test().run()
-     * </pre>
-     *
-     * will throw an error because even if the owner declares a "z" field, the resolution strategy will bypass
-     * lookup in the owner.<p>
-     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
-     */
-    public static final int DELEGATE_ONLY = 3;
-
-    /**
-     * With this resolveStrategy set the closure will resolve property references to itself and go
-     * through the usual MetaClass look-up process. This means that properties and methods are neither resolved
-     * from the owner nor the delegate, but only on the closure object itself. This allows the developer to
-     * override getProperty using ExpandoMetaClass of the closure itself.<p>
-     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
-     */
-    public static final int TO_SELF = 4;
-
-    public static final int DONE = 1, SKIP = 2;
-    private static final Object[] EMPTY_OBJECT_ARRAY = {};
-    public static final Closure IDENTITY = new Closure<Object>(null) {
-        public Object doCall(Object args) {
-            return args;
-        }
-    };
-
-    private Object delegate;
-    private Object owner;
-    private Object thisObject;
-    private int resolveStrategy = OWNER_FIRST;
-    private int directive;
-    protected Class[] parameterTypes;
-    protected int maximumNumberOfParameters;
-    private static final long serialVersionUID = 4368710879820278874L;
-    private BooleanClosureWrapper bcw;
-
-    public Closure(Object owner, Object thisObject) {
-        this.owner = owner;
-        this.delegate = owner;
-        this.thisObject = thisObject;
-
-        final CachedClosureClass cachedClass = (CachedClosureClass) ReflectionCache.getCachedClass(getClass());
-        parameterTypes = cachedClass.getParameterTypes();
-        maximumNumberOfParameters = cachedClass.getMaximumNumberOfParameters();
-    }
-
-    /**
-     * Constructor used when the "this" object for the Closure is null.
-     * This is rarely the case in normal Groovy usage.
-     *
-     * @param owner the Closure owner
-     */
-    public Closure(Object owner) {
-        this(owner, null);
-    }
-
-    /**
-     * Sets the strategy which the closure uses to resolve property references and methods.
-     * The default is Closure.OWNER_FIRST
-     *
-     * @param resolveStrategy The resolve strategy to set
-     *
-     * @see groovy.lang.Closure#DELEGATE_FIRST
-     * @see groovy.lang.Closure#DELEGATE_ONLY
-     * @see groovy.lang.Closure#OWNER_FIRST
-     * @see groovy.lang.Closure#OWNER_ONLY
-     * @see groovy.lang.Closure#TO_SELF
-     */
-    public void setResolveStrategy(int resolveStrategy) {
-        this.resolveStrategy = resolveStrategy;
-    }
-
-    /**
-     * Gets the strategy which the closure uses to resolve methods and properties
-     *
-     * @return The resolve strategy
-     *
-     * @see groovy.lang.Closure#DELEGATE_FIRST
-     * @see groovy.lang.Closure#DELEGATE_ONLY
-     * @see groovy.lang.Closure#OWNER_FIRST
-     * @see groovy.lang.Closure#OWNER_ONLY
-     * @see groovy.lang.Closure#TO_SELF
-     */
-    public int getResolveStrategy() {
-        return resolveStrategy;
-    }
-
-    public Object getThisObject(){
-        return thisObject;
-    }
-
-    public Object getProperty(final String property) {
-        if ("delegate".equals(property)) {
-            return getDelegate();
-        } else if ("owner".equals(property)) {
-            return getOwner();
-        } else if ("maximumNumberOfParameters".equals(property)) {
-            return getMaximumNumberOfParameters();
-        } else if ("parameterTypes".equals(property)) {
-            return getParameterTypes();
-        } else if ("metaClass".equals(property)) {
-            return getMetaClass();
-        } else if ("class".equals(property)) {
-            return getClass();
-        } else if ("directive".equals(property)) {
-            return getDirective();
-        } else if ("resolveStrategy".equals(property)) {
-            return getResolveStrategy();
-        } else if ("thisObject".equals(property)) {
-            return getThisObject();
-        } else {
-            switch(resolveStrategy) {
-                case DELEGATE_FIRST:
-                    return getPropertyDelegateFirst(property);
-                case DELEGATE_ONLY:
-                    return InvokerHelper.getProperty(this.delegate, property);
-                case OWNER_ONLY:
-                    return InvokerHelper.getProperty(this.owner, property);
-                case TO_SELF:
-                    return super.getProperty(property);
-                default:
-                    return getPropertyOwnerFirst(property);
-            }
-        }
-    }
-
-    private Object getPropertyDelegateFirst(String property) {
-        if (delegate == null) return getPropertyOwnerFirst(property);
-        return getPropertyTryThese(property, this.delegate, this.owner);
-    }
-
-    private Object getPropertyOwnerFirst(String property) {
-        return getPropertyTryThese(property, this.owner, this.delegate);
-    }
-
-    private Object getPropertyTryThese(String property, Object firstTry, Object secondTry) {
-        try {
-            // let's try getting the property on the first object
-            return InvokerHelper.getProperty(firstTry, property);
-
-        } catch (MissingPropertyException e1) {
-            if (secondTry != null && firstTry != this && firstTry != secondTry) {
-                try {
-                    // let's try getting the property on the second object
-                    return InvokerHelper.getProperty(secondTry, property);
-                } catch (GroovyRuntimeException e2) {
-                    // ignore, we'll throw e1
-                }
-            }
-            throw e1;
-
-        } catch (MissingFieldException e2)  { // see GROOVY-5875
-            if (secondTry != null && firstTry != this && firstTry != secondTry) {
-                try {
-                    // let's try getting the property on the second object
-                    return InvokerHelper.getProperty(secondTry, property);
-                } catch (GroovyRuntimeException e3) {
-                    // ignore, we'll throw e2
-                }
-            }
-            throw e2;
-        }
-    }
-
-    public void setProperty(String property, Object newValue) {
-        if ("delegate".equals(property)) {
-            setDelegate(newValue);
-        } else if ("metaClass".equals(property)) {
-            setMetaClass((MetaClass) newValue);
-        } else if ("resolveStrategy".equals(property)) {
-            setResolveStrategy(((Number) newValue).intValue());
-        } else if ("directive".equals(property)) {
-            setDirective(((Number) newValue).intValue());
-        } else {
-            switch(resolveStrategy) {
-                case DELEGATE_FIRST:
-                    setPropertyDelegateFirst(property, newValue);
-                break;
-                case DELEGATE_ONLY:
-                    InvokerHelper.setProperty(this.delegate, property, newValue);
-                break;
-                case OWNER_ONLY:
-                    InvokerHelper.setProperty(this.owner, property, newValue);
-                break;
-                case TO_SELF:
-                    super.setProperty(property, newValue);
-                break;
-                default:
-                    setPropertyOwnerFirst(property, newValue);
-            }
-        }
-    }
-
-    private void setPropertyDelegateFirst(String property, Object newValue) {
-        if (delegate == null) setPropertyOwnerFirst(property, newValue);
-        else setPropertyTryThese(property, newValue, this.delegate, this.owner);
-    }
-
-    private void setPropertyOwnerFirst(String property, Object newValue) {
-        setPropertyTryThese(property, newValue, this.owner, this.delegate);
-    }
-
-    private void setPropertyTryThese(String property, Object newValue, Object firstTry, Object secondTry) {
-        try {
-            // let's try setting the property on the first object
-            InvokerHelper.setProperty(firstTry, property, newValue);
-        } catch (GroovyRuntimeException e1) {
-            if (firstTry != null && firstTry != this && firstTry != secondTry) {
-                try {
-                    // let's try setting the property on the second object
-                    InvokerHelper.setProperty(secondTry, property, newValue);
-                    return;
-                } catch (GroovyRuntimeException e2) {
-                    // ignore, we'll throw e1
-                }
-            }
-            throw e1;
-        }
-    }
-
-    public boolean isCase(Object candidate){
-        if (bcw==null) {
-            bcw = new BooleanClosureWrapper(this);
-        }
-        return bcw.call(candidate);
-    }
-
-    /**
-     * Invokes the closure without any parameters, returning any value if applicable.
-     *
-     * @return the value if applicable or null if there is no return statement in the closure
-     */
-    public V call() {
-        final Object[] NOARGS = EMPTY_OBJECT_ARRAY;
-        return call(NOARGS);
-    }
-
-    @SuppressWarnings("unchecked")
-    public V call(Object... args) {
-        try {
-            return (V) getMetaClass().invokeMethod(this,"doCall",args);
-        } catch (InvokerInvocationException e) {
-            UncheckedThrow.rethrow(e.getCause());
-            return null; // unreachable statement
-        }  catch (Exception e) {
-            return (V) throwRuntimeException(e);
-        }
-    }
-
-    /**
-     * Invokes the closure, returning any value if applicable.
-     *
-     * @param arguments could be a single value or a List of values
-     * @return the value if applicable or null if there is no return statement in the closure
-     */
-    public V call(final Object arguments) {
-        return call(new Object[]{arguments});
-    }
-
-    protected static Object throwRuntimeException(Throwable throwable) {
-        if (throwable instanceof RuntimeException) {
-            throw (RuntimeException) throwable;
-        } else {
-            throw new GroovyRuntimeException(throwable.getMessage(), throwable);
-        }
-    }
-
-    /**
-     * @return the owner Object to which method calls will go which is
-     *         typically the outer class when the closure is constructed
-     */
-    public Object getOwner() {
-        return this.owner;
-    }
-
-    /**
-     * @return the delegate Object to which method calls will go which is
-     *         typically the outer class when the closure is constructed
-     */
-    public Object getDelegate() {
-        return this.delegate;
-    }
-
-    /**
-     * Allows the delegate to be changed such as when performing markup building
-     *
-     * @param delegate the new delegate
-     */
-    public void setDelegate(Object delegate) {
-        this.delegate = delegate;
-    }
-
-    /**
-     * @return the parameter types of the longest doCall method
-     * of this closure
-     */
-    public Class[] getParameterTypes() {
-        return parameterTypes;
-    }
-
-    /**
-     * @return the maximum number of parameters a doCall method
-     * of this closure can take
-     */
-    public int getMaximumNumberOfParameters() {
-        return maximumNumberOfParameters;
-    }
-
-    /**
-     * @return a version of this closure which implements Writable.  Note that
-     * the returned Writable also overrides {@link #toString()} in order
-     * to allow rendering the result directly to a String.
-     */
-    public Closure asWritable() {
-        return new WritableClosure();
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Runnable#run()
-     */
-    public void run() {
-        call();
-    }
-
-    /**
-     * Support for Closure currying.
-     * <p>
-     * Typical usage:
-     * <pre class="groovyTestCase">
-     * def multiply = { a, b -> a * b }
-     * def doubler = multiply.curry(2)
-     * assert doubler(4) == 8
-     * </pre>
-     * Note: special treatment is given to Closure vararg-style capability.
-     * If you curry a vararg parameter, you don't consume the entire vararg array
-     * but instead the first parameter of the vararg array as the following example shows:
-     * <pre class="groovyTestCase">
-     * def a = { one, two, Object[] others -> one + two + others.sum() }
-     * assert a.parameterTypes.name == ['java.lang.Object', 'java.lang.Object', '[Ljava.lang.Object;']
-     * assert a(1,2,3,4) == 10
-     * def b = a.curry(1)
-     * assert b.parameterTypes.name == ['java.lang.Object', '[Ljava.lang.Object;']
-     * assert b(2,3,4) == 10
-     * def c = b.curry(2)
-     * assert c.parameterTypes.name == ['[Ljava.lang.Object;']
-     * assert c(3,4) == 10
-     * def d = c.curry(3)
-     * assert d.parameterTypes.name == ['[Ljava.lang.Object;']
-     * assert d(4) == 10
-     * def e = d.curry(4)
-     * assert e.parameterTypes.name == ['[Ljava.lang.Object;']
-     * assert e() == 10
-     * assert e(5) == 15
-     * </pre>
-     *
-     *
-     * @param arguments the arguments to bind
-     * @return the new closure with its arguments bound
-     */
-    public Closure<V> curry(final Object... arguments) {
-        return new CurriedClosure<V>(this, arguments);
-    }
-
-    /**
-     * Support for Closure currying.
-     *
-     * @param argument the argument to bind
-     * @return the new closure with the argument bound
-     * @see #curry(Object...)
-     */
-    public Closure<V> curry(final Object argument) {
-        return curry(new Object[]{argument});
-    }
-
-    /**
-     * Support for Closure "right" currying.
-     * Parameters are supplied on the right rather than left as per the normal curry() method.
-     * Typical usage:
-     * <pre class="groovyTestCase">
-     * def divide = { a, b -> a / b }
-     * def halver = divide.rcurry(2)
-     * assert halver(8) == 4
-     * </pre>
-     *
-     * The position of the curried parameters will be calculated lazily, for example,
-     * if two overloaded doCall methods are available, the supplied arguments plus the
-     * curried arguments will be concatenated and the result used for method selection.
-     *
-     * @param arguments the arguments to bind
-     * @return the new closure with its arguments bound
-     * @see #curry(Object...)
-     */
-    public Closure<V> rcurry(final Object... arguments) {
-        return new CurriedClosure<V>(-arguments.length, this, arguments);
-    }
-
-    /**
-     * Support for Closure "right" currying.
-     *
-     * @param argument the argument to bind
-     * @return the new closure with the argument bound
-     * @see #rcurry(Object...)
-     */
-    public Closure<V> rcurry(final Object argument) {
-        return rcurry(new Object[]{argument});
-    }
-
-    /**
-     * Support for Closure currying at a given index.
-     * Parameters are supplied from index position "n".
-     * Typical usage:
-     * <pre>
-     * def caseInsensitive = { a, b -> a.toLowerCase() <=> b.toLowerCase() } as Comparator
-     * def caseSensitive = { a, b -> a <=> b } as Comparator
-     * def animals1 = ['ant', 'dog', 'BEE']
-     * def animals2 = animals1 + ['Cat']
-     * // curry middle param of this utility method:
-     * // Collections#binarySearch(List list, Object key, Comparator c)
-     * def catSearcher = Collections.&binarySearch.ncurry(1, "cat")
-     * [[animals1, animals2], [caseInsensitive, caseSensitive]].combinations().each{ a, c ->
-     *   def idx = catSearcher(a.sort(c), c)
-     *   print a.sort(c).toString().padRight(22)
-     *   if (idx < 0) println "Not found but would belong in position ${-idx - 1}"
-     *   else println "Found at index $idx"
-     * }
-     * // =>
-     * // [ant, BEE, dog]       Not found but would belong in position 2
-     * // [ant, BEE, Cat, dog]  Found at index 2
-     * // [BEE, ant, dog]       Not found but would belong in position 2
-     * // [BEE, Cat, ant, dog]  Not found but would belong in position 3
-     * </pre>
-     *
-     * The position of the curried parameters will be calculated eagerly
-     * and implies all arguments prior to the specified n index are supplied.
-     * Default parameter values prior to the n index will not be available.
-     *
-     * @param n the index from which to bind parameters (may be -ve in which case it will be normalized)
-     * @param arguments the arguments to bind
-     * @return the new closure with its arguments bound
-     * @see #curry(Object...)
-     */
-    public Closure<V> ncurry(int n, final Object... arguments) {
-        return new CurriedClosure<V>(n, this, arguments);
-    }
-
-    /**
-     * Support for Closure currying at a given index.
-     *
-     * @param argument the argument to bind
-     * @return the new closure with the argument bound
-     * @see #ncurry(int, Object...)
-     */
-    public Closure<V> ncurry(int n, final Object argument) {
-        return ncurry(n, new Object[]{argument});
-    }
-
-    /**
-     * Support for Closure forward composition.
-     * <p>
-     * Typical usage:
-     * <pre class="groovyTestCase">
-     * def times2 = { a -> a * 2 }
-     * def add3 = { a -> a + 3 }
-     * def timesThenAdd = times2 >> add3
-     * // equivalent: timesThenAdd = { a -> add3(times2(a)) }
-     * assert timesThenAdd(3) == 9
-     * </pre>
-     *
-     * @param other the Closure to compose with the current Closure
-     * @return the new composed Closure
-     */
-    public <W> Closure<W> rightShift(final Closure<W> other) {
-        return new ComposedClosure<W>(this, other);
-    }
-
-    /**
-     * Support for Closure reverse composition.
-     * <p>
-     * Typical usage:
-     * <pre class="groovyTestCase">
-     * def times2 = { a -> a * 2 }
-     * def add3 = { a -> a + 3 }
-     * def addThenTimes = times2 << add3
-     * // equivalent: addThenTimes = { a -> times2(add3(a)) }
-     * assert addThenTimes(3) == 12
-     * </pre>
-     *
-     * @param other the Closure to compose with the current Closure
-     * @return the new composed Closure
-     */
-    public Closure<V> leftShift(final Closure other) {
-        return new ComposedClosure<V>(other, this);
-    }
-
-    /* *
-     * Alias for calling a Closure for non-closure arguments.
-     * <p>
-     * Typical usage:
-     * <pre class="groovyTestCase">
-     * def times2 = { a -> a * 2 }
-     * def add3 = { a -> a * 3 }
-     * assert add3 << times2 << 3 == 9
-     * </pre>
-     *
-     * @param arg the argument to call the closure with
-     * @return the result of calling the Closure
-     */
-    public V leftShift(final Object arg) {
-        return call(arg);
-    }
-
-    /**
-     * Creates a caching variant of the closure.
-     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
-     * making subsequent calls with the same arguments fast.
-     * This variant will keep all cached values forever, i.e. till the closure gets garbage-collected.
-     * The returned function can be safely used concurrently from multiple threads, however, the implementation
-     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
-     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
-     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
-     *
-     * The cache gets garbage-collected together with the memoized closure.
-     *
-     * @return A new closure forwarding to the original one while caching the results
-     */
-    public Closure<V> memoize() {
-        return Memoize.buildMemoizeFunction(new UnlimitedConcurrentCache(), this);
-    }
-
-    /**
-     * Creates a caching variant of the closure with upper limit on the cache size.
-     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
-     * making subsequent calls with the same arguments fast.
-     * This variant will keep all values until the upper size limit is reached. Then the values in the cache start rotating
-     * using the LRU (Last Recently Used) strategy.
-     * The returned function can be safely used concurrently from multiple threads, however, the implementation
-     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
-     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
-     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
-     *
-     * The cache gets garbage-collected together with the memoized closure.
-     *
-     * @param maxCacheSize The maximum size the cache can grow to
-     * @return A new function forwarding to the original one while caching the results
-     */
-    public Closure<V> memoizeAtMost(final int maxCacheSize) {
-        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeAtMost.");
-
-        return Memoize.buildMemoizeFunction(new LRUCache(maxCacheSize), this);
-    }
-
-    /**
-     * Creates a caching variant of the closure with automatic cache size adjustment and lower limit
-     * on the cache size.
-     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
-     * making subsequent calls with the same arguments fast.
-     * This variant allows the garbage collector to release entries from the cache and at the same time allows
-     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
-     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
-     * the LRU (Last Recently Used) strategy.
-     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the limits
-     * set by the user if memory is plentiful.
-     * The returned function can be safely used concurrently from multiple threads, however, the implementation
-     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
-     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
-     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
-     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
-     *
-     * The cache gets garbage-collected together with the memoized closure.
-     * @param protectedCacheSize Number of cached return values to protect from garbage collection
-     * @return A new function forwarding to the original one while caching the results
-     */
-    public Closure<V> memoizeAtLeast(final int protectedCacheSize) {
-        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeAtLeast.");
-
-        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new UnlimitedConcurrentCache(), this);
-    }
-
-    /**
-     * Creates a caching variant of the closure with automatic cache size adjustment and lower and upper limits
-     * on the cache size.
-     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
-     * making subsequent calls with the same arguments fast.
-     * This variant allows the garbage collector to release entries from the cache and at the same time allows
-     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
-     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
-     * the LRU (Last Recently Used) strategy.
-     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the protected
-     * size limits set by the user, if memory is plentiful.
-     * Also, this variant will never exceed in size the upper size limit. Once the upper size limit has been reached,
-     * the values in the cache start rotating using the LRU (Last Recently Used) strategy.
-     * The returned function can be safely used concurrently from multiple threads, however, the implementation
-     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
-     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
-     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
-     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
-     *
-     * The cache gets garbage-collected together with the memoized closure.
-     * @param protectedCacheSize Number of cached return values to protect from garbage collection
-     * @param maxCacheSize The maximum size the cache can grow to
-     * @return A new function forwarding to the original one while caching the results
-     */
-    public Closure<V> memoizeBetween(final int protectedCacheSize, final int maxCacheSize) {
-        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeBetween.");
-        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeBetween.");
-        if (protectedCacheSize > maxCacheSize) throw new IllegalArgumentException("The maxCacheSize parameter to memoizeBetween is required to be greater or equal to the protectedCacheSize parameter.");
-
-        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new LRUCache(maxCacheSize), this);
-    }
-
-    /**
-     * Builds a trampolined variant of the current closure.
-     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
-     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
-     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
-     * which will be executed by the trampoline as the next step.
-     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
-     * Here is an example:
-     * <pre>
-     * def fact
-     * fact = { n, total ->
-     *     n == 0 ? total : fact.trampoline(n - 1, n * total)
-     * }.trampoline()
-     * def factorial = { n -> fact(n, 1G)}
-     * println factorial(20) // => 2432902008176640000
-     * </pre>
-     *
-     * @param args Parameters to the closure, so as the trampoline mechanism can call it
-     * @return A closure, which will execute the original closure on a trampoline.
-     */
-    public Closure<V> trampoline(final Object... args) {
-        return new TrampolineClosure<V>(this.curry(args));
-    }
-
-    /**
-     * Builds a trampolined variant of the current closure.
-     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
-     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
-     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
-     * which will be executed by the trampoline as the next step.
-     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
-     * @return A closure, which will execute the original closure on a trampoline.
-     * @see #trampoline(Object...)
-     */
-    public Closure<V> trampoline() {
-        return new TrampolineClosure<V>(this);
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#clone()
-     */
-    public Object clone() {
-        try {
-            return super.clone();
-        } catch (final CloneNotSupportedException e) {
-            return null;
-        }
-    }
-
-    /*
-     * Implementation note:
-     *   This has to be an inner class!
-     *
-     * Reason:
-     *   Closure.this.call will call the outer call method, but
-     * with the inner class as executing object. This means any
-     * invokeMethod or getProperty call will be called on this
-     * inner class instead of the outer!
-     */
-    private class WritableClosure extends Closure implements Writable {
-        public WritableClosure() {
-            super(Closure.this);
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Writable#writeTo(java.io.Writer)
-         */
-        public Writer writeTo(Writer out) throws IOException {
-            Closure.this.call(new Object[]{out});
-
-            return out;
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
-         */
-        public Object invokeMethod(String method, Object arguments) {
-            if ("clone".equals(method)) {
-                return clone();
-            } else if ("curry".equals(method)) {
-                return curry((Object[]) arguments);
-            } else if ("asWritable".equals(method)) {
-                return asWritable();
-            } else {
-                return Closure.this.invokeMethod(method, arguments);
-            }
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
-         */
-        public Object getProperty(String property) {
-            return Closure.this.getProperty(property);
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
-         */
-        public void setProperty(String property, Object newValue) {
-            Closure.this.setProperty(property, newValue);
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#call()
-         */
-        public Object call() {
-            return ((Closure) getOwner()).call();
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#call(java.lang.Object)
-         */
-        public Object call(Object arguments) {
-            return ((Closure) getOwner()).call(arguments);
-        }
-
-        public Object call(Object... args) {
-            return ((Closure) getOwner()).call(args);
-        }
-
-        public Object doCall(Object... args) {
-            return call(args);
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#getDelegate()
-         */
-        public Object getDelegate() {
-            return Closure.this.getDelegate();
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#setDelegate(java.lang.Object)
-         */
-        public void setDelegate(Object delegate) {
-            Closure.this.setDelegate(delegate);
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#getParameterTypes()
-         */
-        public Class[] getParameterTypes() {
-            return Closure.this.getParameterTypes();
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#getParameterTypes()
-         */
-        public int getMaximumNumberOfParameters() {
-            return Closure.this.getMaximumNumberOfParameters();
-        }
-
-        /* (non-Javadoc)
-         * @see groovy.lang.Closure#asWritable()
-         */
-        public Closure asWritable() {
-            return this;
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Runnable#run()
-         */
-        public void run() {
-            Closure.this.run();
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Object#clone()
-         */
-        public Object clone() {
-            return ((Closure) Closure.this.clone()).asWritable();
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Object#hashCode()
-         */
-        public int hashCode() {
-            return Closure.this.hashCode();
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        public boolean equals(Object arg0) {
-            return Closure.this.equals(arg0);
-        }
-
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
-        public String toString() {
-            final StringWriter writer = new StringWriter();
-
-            try {
-                writeTo(writer);
-            } catch (IOException e) {
-                return null;
-            }
-
-            return writer.toString();
-        }
-
-        public Closure curry(final Object... arguments) {
-            return (new CurriedClosure(this, arguments)).asWritable();
-        }
-
-        public void setResolveStrategy(int resolveStrategy) {
-            Closure.this.setResolveStrategy(resolveStrategy);
-        }
-
-        public int getResolveStrategy() {
-            return Closure.this.getResolveStrategy();
-        }
-    }
-
-    /**
-     * @return Returns the directive.
-     */
-    public int getDirective() {
-        return directive;
-    }
-
-    /**
-     * @param directive The directive to set.
-     */
-    public void setDirective(int directive) {
-        this.directive = directive;
-    }
-
-    /**
-     * Returns a copy of this closure where the "owner", "delegate" and "thisObject"
-     * fields are null, allowing proper serialization when one of them is not serializable.
-     *
-     * @return a serializable closure.
-     *
-     * @since 1.8.5
-     */
-    @SuppressWarnings("unchecked")
-    public Closure<V> dehydrate() {
-        Closure<V> result = (Closure<V>) this.clone();
-        result.delegate = null;
-        result.owner = null;
-        result.thisObject = null;
-        return result;
-    }
-
-    /**
-     * Returns a copy of this closure for which the delegate, owner and thisObject are
-     * replaced with the supplied parameters. Use this when you want to rehydrate a
-     * closure which has been made serializable thanks to the {@link #dehydrate()}
-     * method.
-     * @param delegate the closure delegate
-     * @param owner the closure owner
-     * @param thisObject the closure "this" object
-     * @return a copy of this closure where owner, delegate and thisObject are replaced
-     *
-     * @since 1.8.5
-     */
-    @SuppressWarnings("unchecked")
-    public Closure<V> rehydrate(Object delegate, Object owner, Object thisObject) {
-        Closure<V> result = (Closure<V>) this.clone();
-        result.delegate = delegate;
-        result.owner = owner;
-        result.thisObject = thisObject;
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ClosureException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ClosureException.java b/src/main/groovy/lang/ClosureException.java
deleted file mode 100644
index 12986ad..0000000
--- a/src/main/groovy/lang/ClosureException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * An exception thrown by a closure invocation
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class ClosureException extends RuntimeException {
-
-    private final Closure closure;
-    
-    public ClosureException(Closure closure, Throwable cause) {
-        super("Exception thrown by call to closure: " + closure + " reason: " + cause, cause);
-        this.closure = closure;
-    }
-
-    public Closure getClosure() {
-        return closure;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ClosureInvokingMethod.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ClosureInvokingMethod.java b/src/main/groovy/lang/ClosureInvokingMethod.java
deleted file mode 100644
index 3e54278..0000000
--- a/src/main/groovy/lang/ClosureInvokingMethod.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * An interface for MetaMethods that invoke closures to implements. Used by ExpandoMetaClass
- *
- * @see groovy.lang.ExpandoMetaClass
- * 
- * @author Graeme Rocher
- * @since 1.5
- */
-public interface ClosureInvokingMethod {
-
-    /**
-     * Returns the original closure that this method invokes
-     * @return The closure
-     */
-    Closure getClosure();
-
-    /**
-     * Is it a static method?
-     * @return True if it is
-     */
-    boolean isStatic();
-
-    /**
-     * The method name
-     * @return The method name
-     */
-    String getName();
-}


[10/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
new file mode 100644
index 0000000..0605f18
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
@@ -0,0 +1,261 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import groovy.transform.Memoized
+import groovy.transform.TailRecursive
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.TernaryExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.classgen.ReturnAdder
+import org.codehaus.groovy.classgen.VariableScopeVisitor
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.transform.AbstractASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformation
+
+/**
+ * Handles generation of code for the @TailRecursive annotation.
+ *
+ * It's doing its work in the earliest possible compile phase
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+class TailRecursiveASTTransformation extends AbstractASTTransformation {
+
+    private static final Class MY_CLASS = TailRecursive.class;
+    private static final ClassNode MY_TYPE = new ClassNode(MY_CLASS);
+    static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage()
+    private HasRecursiveCalls hasRecursiveCalls = new HasRecursiveCalls()
+    private TernaryToIfStatementConverter ternaryToIfStatement = new TernaryToIfStatementConverter()
+
+
+    @Override
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        init(nodes, source);
+
+        MethodNode method = nodes[1] as MethodNode
+
+        if (method.isAbstract()) {
+            addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", method);
+            return;
+        }
+
+        if (hasAnnotation(method, ClassHelper.make(Memoized))) {
+            ClassNode memoizedClassNode = ClassHelper.make(Memoized)
+            for (AnnotationNode annotationNode in method.annotations) {
+                if (annotationNode.classNode == MY_TYPE)
+                    break
+                if (annotationNode.classNode == memoizedClassNode) {
+                    addError("Annotation " + MY_TYPE_NAME + " must be placed before annotation @Memoized.", annotationNode)
+                    return
+                }
+            }
+        }
+
+        if (!hasRecursiveMethodCalls(method)) {
+            AnnotationNode annotationNode = method.getAnnotations(ClassHelper.make(TailRecursive))[0]
+            addError("No recursive calls detected. You must remove annotation " + MY_TYPE_NAME + ".", annotationNode)
+            return;
+        }
+
+        transformToIteration(method, source)
+        ensureAllRecursiveCallsHaveBeenTransformed(method)
+    }
+
+    private boolean hasAnnotation(MethodNode methodNode, ClassNode annotation) {
+        List annots = methodNode.getAnnotations(annotation);
+        return (annots != null && annots.size() > 0);
+    }
+
+
+    private void transformToIteration(MethodNode method, SourceUnit source) {
+        if (method.isVoidMethod()) {
+            transformVoidMethodToIteration(method, source)
+        } else {
+            transformNonVoidMethodToIteration(method, source)
+        }
+    }
+
+    private void transformVoidMethodToIteration(MethodNode method, SourceUnit source) {
+        addError("Void methods are not supported by @TailRecursive yet.", method)
+    }
+
+    private void transformNonVoidMethodToIteration(MethodNode method, SourceUnit source) {
+        addMissingDefaultReturnStatement(method)
+        replaceReturnsWithTernariesToIfStatements(method)
+        wrapMethodBodyWithWhileLoop(method)
+
+        Map<String, Map> nameAndTypeMapping = name2VariableMappingFor(method)
+        replaceAllAccessToParams(method, nameAndTypeMapping)
+        addLocalVariablesForAllParameters(method, nameAndTypeMapping) //must happen after replacing access to params
+
+        Map<Integer, Map> positionMapping = position2VariableMappingFor(method)
+        replaceAllRecursiveReturnsWithIteration(method, positionMapping)
+        repairVariableScopes(source, method)
+    }
+
+    private void repairVariableScopes(SourceUnit source, MethodNode method) {
+        new VariableScopeVisitor(source).visitClass(method.declaringClass)
+    }
+
+    private void replaceReturnsWithTernariesToIfStatements(MethodNode method) {
+        Closure<Boolean> whenReturnWithTernary = { ASTNode node ->
+            if (!(node instanceof ReturnStatement)) {
+                return false
+            }
+            return (((ReturnStatement) node).expression instanceof TernaryExpression)
+        }
+        Closure<Statement> replaceWithIfStatement = { ReturnStatement statement ->
+            ternaryToIfStatement.convert(statement)
+        }
+        StatementReplacer replacer = new StatementReplacer(when: whenReturnWithTernary, replaceWith: replaceWithIfStatement)
+        replacer.replaceIn(method.code)
+
+    }
+
+    private void addLocalVariablesForAllParameters(MethodNode method, Map<String, Map> nameAndTypeMapping) {
+        BlockStatement code = method.code as BlockStatement
+        nameAndTypeMapping.each { String paramName, Map localNameAndType ->
+            code.statements.add(0, AstHelper.createVariableDefinition(
+                    (String) localNameAndType['name'],
+                    (ClassNode) localNameAndType['type'],
+                    new VariableExpression(paramName, (ClassNode) localNameAndType['type'])
+            ))
+        }
+    }
+
+    private void replaceAllAccessToParams(MethodNode method, Map<String, Map> nameAndTypeMapping) {
+        new VariableAccessReplacer(nameAndTypeMapping: nameAndTypeMapping).replaceIn(method.code)
+    }
+
+    // Public b/c there are tests for this method
+    Map<String, Map> name2VariableMappingFor(MethodNode method) {
+        Map<String, Map> nameAndTypeMapping = [:]
+        method.parameters.each { Parameter param ->
+            String paramName = param.name
+            ClassNode paramType = param.type as ClassNode
+            String iterationVariableName = iterationVariableName(paramName)
+            nameAndTypeMapping[paramName] = [name: iterationVariableName, type: paramType]
+        }
+        return nameAndTypeMapping
+    }
+
+    // Public b/c there are tests for this method
+    Map<Integer, Map> position2VariableMappingFor(MethodNode method) {
+        Map<Integer, Map> positionMapping = [:]
+        method.parameters.eachWithIndex { Parameter param, int index ->
+            String paramName = param.name
+            ClassNode paramType = param.type as ClassNode
+            String iterationVariableName = this.iterationVariableName(paramName)
+            positionMapping[index] = [name: iterationVariableName, type: paramType]
+        }
+        return positionMapping
+    }
+
+    private String iterationVariableName(String paramName) {
+        '_' + paramName + '_'
+    }
+
+    private void replaceAllRecursiveReturnsWithIteration(MethodNode method, Map positionMapping) {
+        replaceRecursiveReturnsOutsideClosures(method, positionMapping)
+        replaceRecursiveReturnsInsideClosures(method, positionMapping)
+    }
+
+    private void replaceRecursiveReturnsOutsideClosures(MethodNode method, Map<Integer, Map> positionMapping) {
+        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean inClosure ->
+            if (inClosure)
+                return false
+            if (!(statement instanceof ReturnStatement)) {
+                return false
+            }
+            Expression inner = ((ReturnStatement) statement).expression
+            if (!(inner instanceof MethodCallExpression) && !(inner instanceof StaticMethodCallExpression)) {
+                return false
+            }
+            return isRecursiveIn(inner, method)
+        }
+        Closure<Statement> replaceWithContinueBlock = { ReturnStatement statement ->
+            new ReturnStatementToIterationConverter().convert(statement, positionMapping)
+        }
+        def replacer = new StatementReplacer(when: whenRecursiveReturn, replaceWith: replaceWithContinueBlock)
+        replacer.replaceIn(method.code)
+    }
+
+    private void replaceRecursiveReturnsInsideClosures(MethodNode method, Map<Integer, Map> positionMapping) {
+        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean inClosure ->
+            if (!inClosure)
+                return false
+            if (!(statement instanceof ReturnStatement)) {
+                return false
+            }
+            Expression inner = ((ReturnStatement )statement).expression
+            if (!(inner instanceof MethodCallExpression) && !(inner instanceof StaticMethodCallExpression)) {
+                return false
+            }
+            return isRecursiveIn(inner, method)
+        }
+        Closure<Statement> replaceWithThrowLoopException = { ReturnStatement statement ->
+            new ReturnStatementToIterationConverter(recurStatement: AstHelper.recurByThrowStatement()).convert(statement, positionMapping)
+        }
+        StatementReplacer replacer = new StatementReplacer(when: whenRecursiveReturn, replaceWith: replaceWithThrowLoopException)
+        replacer.replaceIn(method.code)
+    }
+
+    private void wrapMethodBodyWithWhileLoop(MethodNode method) {
+        new InWhileLoopWrapper().wrap(method)
+    }
+
+    private void addMissingDefaultReturnStatement(MethodNode method) {
+        new ReturnAdder().visitMethod(method)
+        new ReturnAdderForClosures().visitMethod(method)
+    }
+
+    private void ensureAllRecursiveCallsHaveBeenTransformed(MethodNode method) {
+        List<Expression> remainingRecursiveCalls = new CollectRecursiveCalls().collect(method)
+        for(Expression expression : remainingRecursiveCalls) {
+            addError("Recursive call could not be transformed by @TailRecursive. Maybe it's not a tail call.", expression)
+        }
+    }
+
+    private boolean hasRecursiveMethodCalls(MethodNode method) {
+        hasRecursiveCalls.test(method)
+    }
+
+    private boolean isRecursiveIn(Expression methodCall, MethodNode method) {
+        if (methodCall instanceof MethodCallExpression)
+            return new RecursivenessTester().isRecursive(method, (MethodCallExpression) methodCall)
+        if (methodCall instanceof StaticMethodCallExpression)
+            return new RecursivenessTester().isRecursive(method, (StaticMethodCallExpression) methodCall)
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
new file mode 100644
index 0000000..c47e1d2
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
@@ -0,0 +1,42 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.expr.TernaryExpression
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+
+/**
+ * Since a ternary statement has more than one exit point tail-recursiveness testing cannot be easily done.
+ * Therefore this class translates a ternary statement (or Elvis operator) into the equivalent if-else statement.
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class TernaryToIfStatementConverter {
+
+    Statement convert(ReturnStatement statementWithInnerTernaryExpression) {
+        if (!(statementWithInnerTernaryExpression.expression instanceof TernaryExpression))
+            return statementWithInnerTernaryExpression
+        TernaryExpression ternary = statementWithInnerTernaryExpression.expression as TernaryExpression
+        return new IfStatement(ternary.booleanExpression, new ReturnStatement(ternary.trueExpression), new ReturnStatement(ternary.falseExpression))
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
new file mode 100644
index 0000000..d62dc46
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
@@ -0,0 +1,73 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.expr.VariableExpression
+
+/**
+ * Replace all access to variables and args by new variables.
+ * The variable names to replace as well as their replacement name and type have to be configured
+ * in nameAndTypeMapping before calling replaceIn().
+ *
+ * The VariableReplacedListener can be set if clients want to react to variable replacement.
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableAccessReplacer {
+
+    /**
+     * Nested map of variable accesses to replace
+     * e.g.: [
+     *          'varToReplace': [name: 'newVar', type: TypeOfVar],
+     *          'varToReplace2': [name: 'newVar2', type: TypeOfVar2],
+     *       ]
+     */
+    Map<String, Map> nameAndTypeMapping = [:]
+
+    VariableReplacedListener listener = VariableReplacedListener.NULL
+
+    void replaceIn(ASTNode root) {
+        Closure<Boolean> whenParam = { VariableExpression expr ->
+            return nameAndTypeMapping.containsKey(expr.name)
+        }
+        Closure<VariableExpression> replaceWithLocalVariable = { VariableExpression expr ->
+            Map nameAndType = nameAndTypeMapping[expr.name]
+            VariableExpression newVar = AstHelper.createVariableReference(nameAndType)
+            listener.variableReplaced(expr, newVar)
+            return newVar
+        }
+        new VariableExpressionReplacer(when: whenParam, replaceWith: replaceWithLocalVariable).replaceIn(root)
+    }
+
+}
+
+@CompileStatic
+interface VariableReplacedListener {
+    void variableReplaced(VariableExpression oldVar, VariableExpression newVar)
+
+    static VariableReplacedListener NULL = new VariableReplacedListener() {
+        @Override
+        void variableReplaced(VariableExpression oldVar, VariableExpression newVar) {
+            //do nothing
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
new file mode 100644
index 0000000..1f14490
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
@@ -0,0 +1,171 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.expr.BinaryExpression
+import org.codehaus.groovy.ast.expr.BooleanExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ExpressionTransformer
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.AssertStatement
+import org.codehaus.groovy.ast.stmt.CaseStatement
+import org.codehaus.groovy.ast.stmt.DoWhileStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.SwitchStatement
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement
+import org.codehaus.groovy.ast.stmt.ThrowStatement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+
+import java.lang.reflect.Method
+
+/**
+ * Tool for replacing VariableExpression instances in an AST by other VariableExpression instances.
+ * Regardless of a real change taking place in nested expressions, all considered expression (trees) will be replaced.
+ * This could be optimized to accelerate compilation.
+ *
+ * Within @TailRecursive it is used
+ * - to swap the access of method args with the access to iteration variables
+ * - to swap the access of iteration variables with the access of temp vars
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableExpressionReplacer extends CodeVisitorSupport {
+
+    Closure<Boolean> when = { VariableExpression node -> false }
+    Closure<VariableExpression> replaceWith = { VariableExpression variableExpression -> variableExpression }
+
+    private ExpressionTransformer transformer
+
+    synchronized void replaceIn(ASTNode root) {
+        transformer = new VariableExpressionTransformer(when: when, replaceWith: replaceWith)
+        root.visit(this)
+    }
+
+    public void visitReturnStatement(ReturnStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitReturnStatement(statement);
+    }
+
+    public void visitIfElse(IfStatement ifElse) {
+        replaceExpressionPropertyWhenNecessary(ifElse, 'booleanExpression', BooleanExpression)
+        super.visitIfElse(ifElse);
+    }
+
+    public void visitForLoop(ForStatement forLoop) {
+        replaceExpressionPropertyWhenNecessary(forLoop, 'collectionExpression')
+        super.visitForLoop(forLoop);
+    }
+
+    /**
+     * It's the only Expression type in which replacing is considered.
+     * That's an abuse of the class, but I couldn't think of a better way.
+     */
+    public void visitBinaryExpression(BinaryExpression expression) {
+        //A hack: Only replace right expression b/c ReturnStatementToIterationConverter needs it that way :-/
+        replaceExpressionPropertyWhenNecessary(expression, 'rightExpression')
+        expression.getRightExpression().visit(this);
+        super.visitBinaryExpression(expression)
+    }
+
+    public void visitWhileLoop(WhileStatement loop) {
+        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', BooleanExpression)
+        super.visitWhileLoop(loop);
+    }
+
+    public void visitDoWhileLoop(DoWhileStatement loop) {
+        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', BooleanExpression)
+        super.visitDoWhileLoop(loop);
+    }
+
+    public void visitSwitch(SwitchStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitSwitch(statement)
+    }
+
+    public void visitCaseStatement(CaseStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitCaseStatement(statement)
+    }
+
+    public void visitExpressionStatement(ExpressionStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitExpressionStatement(statement);
+    }
+
+    public void visitThrowStatement(ThrowStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitThrowStatement(statement)
+    }
+
+    public void visitAssertStatement(AssertStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement, 'booleanExpression', BooleanExpression)
+        replaceExpressionPropertyWhenNecessary(statement, 'messageExpression')
+        super.visitAssertStatement(statement)
+    }
+
+    public void visitSynchronizedStatement(SynchronizedStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitSynchronizedStatement(statement)
+    }
+
+    private void replaceExpressionPropertyWhenNecessary(ASTNode node, String propName = "expression", Class propClass = Expression) {
+        Expression expr = getExpression(node, propName)
+
+        if (expr instanceof VariableExpression) {
+            if (when(expr)) {
+                VariableExpression newExpr = replaceWith(expr)
+                replaceExpression(node, propName, propClass, expr, newExpr)
+            }
+        } else {
+            Expression newExpr = expr.transformExpression(transformer)
+            replaceExpression(node, propName, propClass, expr, newExpr)
+        }
+    }
+
+    private void replaceExpression(ASTNode node, String propName, Class propClass, Expression oldExpr, Expression newExpr) {
+        //Use reflection to enable CompileStatic
+        String setterName = 'set' + capitalizeFirst(propName)
+        Method setExpressionMethod = node.class.getMethod(setterName, [propClass].toArray(new Class[1]))
+        newExpr.setSourcePosition(oldExpr);
+        newExpr.copyNodeMetaData(oldExpr);
+        setExpressionMethod.invoke(node, [newExpr].toArray())
+    }
+
+    private Expression getExpression(ASTNode node, String propName) {
+        //Use reflection to enable CompileStatic
+        String getterName = 'get' + capitalizeFirst(propName)
+        Method getExpressionMethod = node.class.getMethod(getterName, new Class[0])
+        getExpressionMethod.invoke(node, new Object[0]) as Expression
+    }
+
+    private String capitalizeFirst(String propName) {
+        propName[0].toUpperCase() + propName[1..-1]
+    }
+
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
new file mode 100644
index 0000000..106a2f1
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
@@ -0,0 +1,47 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ExpressionTransformer
+import org.codehaus.groovy.ast.expr.VariableExpression
+
+/**
+ * An expression transformer used in the process of replacing the access to variables
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableExpressionTransformer implements ExpressionTransformer {
+
+    Closure<Boolean> when
+    Closure<VariableExpression> replaceWith
+
+    @Override
+    Expression transform(Expression expr) {
+        if ((expr instanceof VariableExpression) && when(expr)) {
+            VariableExpression newExpr = replaceWith(expr)
+            newExpr.setSourcePosition(expr);
+            newExpr.copyNodeMetaData(expr);
+            return newExpr
+        }
+        return expr.transformExpression(this)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
new file mode 100644
index 0000000..339d92c
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
@@ -0,0 +1,57 @@
+/*
+ *  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.util
+
+import groovy.transform.CompileStatic
+
+/**
+ * String utility functions.
+ */
+@CompileStatic
+class StringUtil {
+    /**
+     * Provides Groovy with functionality similar to the unix tr command
+     * which translates a string replacing characters from a source set
+     * with characters from a replacement set.
+     *
+     * @since 1.7.3
+     */
+    static String tr(String text, String source, String replacement) {
+        if (!text || !source) { return text }
+        source = expandHyphen(source)
+        replacement = expandHyphen(replacement)
+
+        // padding replacement with a last character, if necessary
+        replacement = replacement.padRight(source.size(), replacement[replacement.size() - 1])
+
+        return text.collect { String original ->
+            if (source.contains(original)) {
+                replacement[source.lastIndexOf(original)]
+            } else {
+                original
+            }
+        }.join('')
+    }
+
+    // no expansion for hyphen at start or end of Strings
+    private static String expandHyphen(String text) {
+        if (!text.contains('-')) { return text }
+        return text.replaceAll(/(.)-(.)/, { all, begin, end -> (begin..end).join('') })
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/security/GroovyCodeSourcePermission.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/security/GroovyCodeSourcePermission.java b/src/main/groovy/security/GroovyCodeSourcePermission.java
deleted file mode 100644
index e723e0b..0000000
--- a/src/main/groovy/security/GroovyCodeSourcePermission.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  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 groovy.security;
-
-import java.security.BasicPermission;
-
-/**
- * Permission required to explicitly specify a codebase for a groovy script whose
- * codebase cannot be determined.  Typically this permission is only
- * required by clients that want to associate a code source with a script which
- * is a String or an InputStream.
- *
- * @author Steve Goetze
- */
-public final class GroovyCodeSourcePermission extends BasicPermission {
-
-    public GroovyCodeSourcePermission(String name) {
-        super(name);
-    }
-
-    public GroovyCodeSourcePermission(String name, String actions) {
-        super(name, actions);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/security/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/security/package.html b/src/main/groovy/security/package.html
deleted file mode 100644
index cb094ff..0000000
--- a/src/main/groovy/security/package.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-
-     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 groovy.security.*</title>
-  </head>
-  <body>
-    <p>
-      Security-related classes
-    </p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/BaseDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/BaseDuration.java b/src/main/groovy/time/BaseDuration.java
deleted file mode 100644
index e2cc023..0000000
--- a/src/main/groovy/time/BaseDuration.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  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 groovy.time;
-
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.StringGroovyMethods;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Base class for date and time durations.
- *
- * @author John Wilson tug@wilson.co.uk
- * @see Duration
- */
-public abstract class BaseDuration implements Comparable<BaseDuration> {
-    protected final int years;
-    protected final int months;
-    protected final int days;
-    protected final int hours;
-    protected final int minutes;
-    protected final int seconds;
-    protected final int millis;
-
-    protected BaseDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
-        this.years = years;
-        this.months = months;
-        this.days = days;
-        this.hours = hours;
-        this.minutes = minutes;
-        this.seconds = seconds;
-        this.millis = millis;
-    }
-
-    protected BaseDuration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
-        this(0, 0, days, hours, minutes, seconds, millis);
-    }
-
-    public int getYears() {
-        return this.years;
-    }
-
-    public int getMonths() {
-        return this.months;
-    }
-
-    public int getDays() {
-        return this.days;
-    }
-
-    public int getHours() {
-        return this.hours;
-    }
-
-    public int getMinutes() {
-        return this.minutes;
-    }
-
-    public int getSeconds() {
-        return this.seconds;
-    }
-
-    public int getMillis() {
-        return this.millis;
-    }
-
-    public Date plus(final Date date) {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.setTime(date);
-        cal.add(Calendar.YEAR, this.years);
-        cal.add(Calendar.MONTH, this.months);
-        cal.add(Calendar.DAY_OF_YEAR, this.days);
-        cal.add(Calendar.HOUR_OF_DAY, this.hours);
-        cal.add(Calendar.MINUTE, this.minutes);
-        cal.add(Calendar.SECOND, this.seconds);
-        cal.add(Calendar.MILLISECOND, this.millis);
-
-        return cal.getTime();
-    }
-
-    public String toString() {
-        List buffer = new ArrayList();
-
-        if (this.years != 0) buffer.add(this.years + " years");
-        if (this.months != 0) buffer.add(this.months + " months");
-        if (this.days != 0) buffer.add(this.days + " days");
-        if (this.hours != 0) buffer.add(this.hours + " hours");
-        if (this.minutes != 0) buffer.add(this.minutes + " minutes");
-
-        if (this.seconds != 0 || this.millis != 0) {
-            int norm_millis = this.millis % 1000;
-            int norm_seconds = this.seconds + DefaultGroovyMethods.intdiv(this.millis - norm_millis, 1000).intValue();
-            CharSequence millisToPad = "" + Math.abs(norm_millis);
-            buffer.add((norm_seconds == 0 ? (norm_millis < 0 ? "-0" : "0") : norm_seconds) + "." + StringGroovyMethods.padLeft(millisToPad, 3, "0") + " seconds");
-        }
-
-        if (!buffer.isEmpty()) {
-            return DefaultGroovyMethods.join(buffer.iterator(), ", ");
-        } else {
-            return "0";
-        }
-    }
-
-    public abstract long toMilliseconds();
-
-    public abstract Date getAgo();
-
-    public abstract From getFrom();
-
-    public int compareTo(BaseDuration otherDuration) {
-        return Long.signum(toMilliseconds() - otherDuration.toMilliseconds());
-    }
-
-    public abstract static class From {
-        public abstract Date getNow();
-
-        public Date getToday() {
-            return getNow();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/DatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/DatumDependentDuration.java b/src/main/groovy/time/DatumDependentDuration.java
deleted file mode 100644
index c73d9aa..0000000
--- a/src/main/groovy/time/DatumDependentDuration.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  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 groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * DatumDependentDuration represents durations whose length in milliseconds 
- * cannot be determined without knowing the datum point.
- * <p>
- * I don't know how many days in a year unless I know if it's a leap year or not.
- * <p>
- * I don't know how many days in a month unless I know the name of the month 
- * (and if it's a leap year if the month is February)
- *
- * @author John Wilson tug@wilson.co.uk
- */
-public class DatumDependentDuration extends BaseDuration {
-    public DatumDependentDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
-        super(years, months, days, hours, minutes, seconds, millis);
-    }
-
-    public int getMonths() {
-        return this.months;
-    }
-
-    public int getYears() {
-        return this.years;
-    }
-
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
-                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                this.getMillis() + rhs.getMillis());
-    }
-
-    public DatumDependentDuration plus(final TimeDatumDependentDuration rhs) {
-        return rhs.plus(this);
-    }
-
-    public DatumDependentDuration plus(final Duration rhs) {
-        return new DatumDependentDuration(this.getYears(), this.getMonths(),
-                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                this.getMillis() + rhs.getMillis());
-
-    }
-
-    public DatumDependentDuration plus(final TimeDuration rhs) {
-        return rhs.plus(this);
-
-    }
-
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
-                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                this.getMillis() - rhs.getMillis());
-
-    }
-
-    public DatumDependentDuration minus(final Duration rhs) {
-        return new DatumDependentDuration(this.getYears(), this.getMonths(),
-                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                this.getMillis() - rhs.getMillis());
-
-    }
-
-    /**
-     * @see groovy.time.BaseDuration#toMilliseconds()
-     *
-     * Change the duration into milliseconds, relative to 'now.'  Therefore
-     * things like timezone and time of year will affect how this conversion 
-     * occurs.
-     */
-    public long toMilliseconds() {
-        final Date now = new Date();
-        return TimeCategory.minus(plus(now), now).toMilliseconds();
-    }
-
-    public Date getAgo() {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.YEAR, -this.getYears());
-        cal.add(Calendar.MONTH, -this.getMonths());
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-
-        return new Date(cal.getTimeInMillis());
-    }
-
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-                final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.YEAR, DatumDependentDuration.this.getYears());
-                cal.add(Calendar.MONTH, DatumDependentDuration.this.getMonths());
-                cal.add(Calendar.DAY_OF_YEAR, DatumDependentDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, DatumDependentDuration.this.getHours());
-                cal.add(Calendar.MINUTE, DatumDependentDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, DatumDependentDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, DatumDependentDuration.this.getMillis());
-
-                cal.set(Calendar.HOUR_OF_DAY, 0);
-                cal.set(Calendar.MINUTE, 0);
-                cal.set(Calendar.SECOND, 0);
-                cal.set(Calendar.MILLISECOND, 0);
-
-                return new Date(cal.getTimeInMillis());
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/Duration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/Duration.java b/src/main/groovy/time/Duration.java
deleted file mode 100644
index e187957..0000000
--- a/src/main/groovy/time/Duration.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  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 groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * Duration represents time periods which have values independent of the context.
- * So, whilst we can't say how long a month is without knowing the year and the name of the month,
- * we know how long a day is independent of the date.
- * <p>
- * This is not 100% true for days.
- * Days can actually be 23, 24 or 25 hours long (due to daylight saving adjustments.)
- * <p>
- * If you ask Duration to convert itself to milliseconds then it will work on the basis of 24 hours
- * in a day. If you add or subtract it from a date it will take daylight saving into account.
- *
- * @author John Wilson tug@wilson.co.uk
- */
-public class Duration extends BaseDuration {
-    public Duration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
-        super(days, hours, minutes, seconds, millis);
-    }
-    
-    public Duration plus(final Duration rhs) {
-        return new Duration(this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                            this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                            this.getMillis() + rhs.getMillis());
-    }
-
-    public Duration plus(final TimeDuration rhs) {
-        return rhs.plus(this);
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return rhs.plus(this);
-    }
-    
-    public Duration minus(final Duration rhs) {
-        return new Duration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                            this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                            this.getMillis() - rhs.getMillis());
-    }
-    
-    public TimeDuration minus(final TimeDuration rhs) {
-        return new TimeDuration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                this.getMillis() - rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
-                                          this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                          this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                          this.getMillis() - rhs.getMillis());
-    }
-    
-    public TimeDatumDependentDuration minus(final TimeDatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - rhs.getMillis());
-    }
-    
-    public long toMilliseconds() {
-        return ((((((long)(this.getDays() * 24 ) + this.getHours()) * 60 + this.getMinutes()) * 60) + this.getSeconds()) * 1000) + this.getMillis();
-    }
-    
-    public Date getAgo() {
-    final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-        
-        return new Date(cal.getTimeInMillis());
-    }
-     
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-            final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.DAY_OF_YEAR, Duration.this.getDays());
-
-                cal.set(Calendar.HOUR_OF_DAY, 0);
-                cal.set(Calendar.MINUTE, 0);
-                cal.set(Calendar.SECOND, 0);
-                cal.set(Calendar.MILLISECOND, 0);
-
-                return new Date(cal.getTimeInMillis());
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/TimeCategory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeCategory.java b/src/main/groovy/time/TimeCategory.java
deleted file mode 100644
index dbc08cd..0000000
--- a/src/main/groovy/time/TimeCategory.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *  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 groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Apply a number of methods to allow convenient Date/Time manipulation,such as:
- * <pre class="groovyTestCase">
- * use (groovy.time.TimeCategory) {
- *     // application on numbers:
- *     println 1.minute.from.now
- *     println 10.hours.ago
- *
- *     // application on dates
- *     def someDate = new Date()
- *     println someDate - 3.months
- * }
- * </pre>
- *
- * @see BaseDuration
- */
-public class TimeCategory {
-    /*
-     * Methods to allow Date Duration arithmetic
-     */
-
-    public static Date plus(final Date date, final BaseDuration duration) {
-        return duration.plus(date);
-    }
-
-    public static Date minus(final Date date, final BaseDuration duration) {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.setTime(date);
-        cal.add(Calendar.YEAR, -duration.getYears());
-        cal.add(Calendar.MONTH, -duration.getMonths());
-        cal.add(Calendar.DAY_OF_YEAR, -duration.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -duration.getHours());
-        cal.add(Calendar.MINUTE, -duration.getMinutes());
-        cal.add(Calendar.SECOND, -duration.getSeconds());
-        cal.add(Calendar.MILLISECOND, -duration.getMillis());
-
-        return cal.getTime();
-    }
-
-    /**
-     * Retrieves the default TimeZone for a date by using the default Locale
-     * settings. Recommended that you use {@code TimeZone.getDefault()} instead.
-     *
-     * @param self a Date
-     * @return the TimeZone
-     */
-    @Deprecated
-    public static TimeZone getTimeZone(Date self) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(self);
-        return calendar.getTimeZone();
-    }
-
-    /**
-     * Get the DST offset (if any) for the default locale and the given date.
-     *
-     * @param self a Date
-     * @return the DST offset as a Duration.
-     */
-    public static Duration getDaylightSavingsOffset(Date self) {
-        TimeZone timeZone = getTimeZone(self);
-        int millis = (timeZone.useDaylightTime() && timeZone.inDaylightTime(self))
-                ? timeZone.getDSTSavings() : 0;
-        return new TimeDuration(0, 0, 0, millis);
-    }
-
-    public static Duration getDaylightSavingsOffset(BaseDuration self) {
-        return getDaylightSavingsOffset(new Date(self.toMilliseconds() + 1));
-    }
-
-    /**
-     * Return a Duration representing the DST difference (if any) between two
-     * dates.  i.e. if one date is before the DST changeover, and the other
-     * date is after, the resulting duration will represent the DST offset.
-     *
-     * @param self  a Date
-     * @param other another Date
-     * @return a Duration
-     */
-    public static Duration getRelativeDaylightSavingsOffset(Date self, Date other) {
-        Duration d1 = getDaylightSavingsOffset(self);
-        Duration d2 = getDaylightSavingsOffset(other);
-        return new TimeDuration(0, 0, 0, (int) (d2.toMilliseconds() - d1.toMilliseconds()));
-    }
-
-    /**
-     * Subtract one date from the other.
-     *
-     * @param lhs a Date
-     * @param rhs another Date
-     * @return a Duration
-     */
-    public static TimeDuration minus(final Date lhs, final Date rhs) {
-        long milliseconds = lhs.getTime() - rhs.getTime();
-        long days = milliseconds / (24 * 60 * 60 * 1000);
-        milliseconds -= days * 24 * 60 * 60 * 1000;
-        int hours = (int) (milliseconds / (60 * 60 * 1000));
-        milliseconds -= hours * 60 * 60 * 1000;
-        int minutes = (int) (milliseconds / (60 * 1000));
-        milliseconds -= minutes * 60 * 1000;
-        int seconds = (int) (milliseconds / 1000);
-        milliseconds -= seconds * 1000;
-
-        return new TimeDuration((int) days, hours, minutes, seconds, (int) milliseconds);
-    }
-
-    /*
-    * Methods on Integer to implement 1.month, 4.years etc.
-    */
-
-    public static DatumDependentDuration getMonths(final Integer self) {
-        return new DatumDependentDuration(0, self, 0, 0, 0, 0, 0);
-    }
-
-    public static DatumDependentDuration getMonth(final Integer self) {
-        return getMonths(self);
-    }
-
-    public static DatumDependentDuration getYears(final Integer self) {
-        return new DatumDependentDuration(self, 0, 0, 0, 0, 0, 0);
-    }
-
-    public static DatumDependentDuration getYear(final Integer self) {
-        return getYears(self);
-    }
-
-    /*
-    * Methods on Integer to implement 1.week, 4.days etc.
-    */
-
-    public static Duration getWeeks(final Integer self) {
-        return new Duration(self * 7, 0, 0, 0, 0);
-    }
-
-    public static Duration getWeek(final Integer self) {
-        return getWeeks(self);
-    }
-
-    public static Duration getDays(final Integer self) {
-        return new Duration(self, 0, 0, 0, 0);
-    }
-
-    public static Duration getDay(final Integer self) {
-        return getDays(self);
-    }
-
-    public static TimeDuration getHours(final Integer self) {
-        return new TimeDuration(0, self, 0, 0, 0);
-    }
-
-    public static TimeDuration getHour(final Integer self) {
-        return getHours(self);
-    }
-
-    public static TimeDuration getMinutes(final Integer self) {
-        return new TimeDuration(0, 0, self, 0, 0);
-    }
-
-    public static TimeDuration getMinute(final Integer self) {
-        return getMinutes(self);
-    }
-
-    public static TimeDuration getSeconds(final Integer self) {
-        return new TimeDuration(0, 0, 0, self, 0);
-    }
-
-    public static TimeDuration getSecond(final Integer self) {
-        return getSeconds(self);
-    }
-
-    public static TimeDuration getMilliseconds(final Integer self) {
-        return new TimeDuration(0, 0, 0, 0, self);
-    }
-
-    public static TimeDuration getMillisecond(final Integer self) {
-        return getMilliseconds(self);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/TimeDatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeDatumDependentDuration.java b/src/main/groovy/time/TimeDatumDependentDuration.java
deleted file mode 100644
index eead45a..0000000
--- a/src/main/groovy/time/TimeDatumDependentDuration.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  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 groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * TimeDatumDuration represents a time period which results from an
- * arithmetic operation between a TimeDuration object and a DatumDuration object
- * 
- * @author John Wilson tug@wilson.co.uk
- */
-public class TimeDatumDependentDuration extends DatumDependentDuration {
-    public TimeDatumDependentDuration(int years, int months, int days, int hours, int minutes, int seconds, int millis) {
-        super(years, months, days, hours, minutes, seconds, millis);
-    }
-    
-    public DatumDependentDuration plus(final Duration rhs) {
-        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
-                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + rhs.getMillis());
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
-                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final Duration rhs) {
-        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
-                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - rhs.getMillis());
-    }
-    
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-            final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.YEAR, TimeDatumDependentDuration.this.getYears());
-                cal.add(Calendar.MONTH, TimeDatumDependentDuration.this.getMonths());
-                cal.add(Calendar.DAY_OF_YEAR, TimeDatumDependentDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, TimeDatumDependentDuration.this.getHours());
-                cal.add(Calendar.MINUTE, TimeDatumDependentDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, TimeDatumDependentDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, TimeDatumDependentDuration.this.getMillis());
-                
-                return cal.getTime();
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/TimeDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeDuration.java b/src/main/groovy/time/TimeDuration.java
deleted file mode 100644
index 767b8e6..0000000
--- a/src/main/groovy/time/TimeDuration.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  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 groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * TimeDuration represents time periods expressed in units of hours, minutes,
- * seconds and milliseconds.
- * <p>
- * Whilst we can't say how long a month is without knowing the year and the name of the month,
- * we know how long a second is independent of the date.
- * <p>
- * This is not 100% true for minutes.
- * Minutes can be 59, 60 or 61 seconds long (due to leap seconds.)
- * <p>
- * If you ask Duration to convert itself to milliseconds then it will work on the basis of 60 seconds in a minute.
- * If you add or subtract it from a date it will take leap seconds into account.
- *
- * @author John Wilson tug@wilson.co.uk
- */
-
-public class TimeDuration extends Duration {
-    public TimeDuration(final int hours, final int minutes, final int seconds, final int millis) {
-        super(0, hours, minutes, seconds, millis);
-     }
-    
-    public TimeDuration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
-        super(days, hours, minutes, seconds, millis);
-     }
-    
-    public Duration plus(final Duration rhs) {
-        return new TimeDuration(this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                this.getMillis() + rhs.getMillis());
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(rhs.getYears(), rhs.getMonths(),
-                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + rhs.getMillis());
-    }
-    
-    public Duration minus(final Duration rhs) {
-        return new TimeDuration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                this.getMillis() - rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - rhs.getMillis());
-    }
-    
-    public Date getAgo() {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-        
-        return cal.getTime();
-    }        
-
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-                final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.DAY_OF_YEAR, TimeDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, TimeDuration.this.getHours());
-                cal.add(Calendar.MINUTE, TimeDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, TimeDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, TimeDuration.this.getMillis());
-                
-                return cal.getTime();
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/time/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/package.html b/src/main/groovy/time/package.html
deleted file mode 100644
index 94fb458..0000000
--- a/src/main/groovy/time/package.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
-
-     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 groovy.time.*</title>
-  </head>
-  <body>
-    <p>
-      Classes for easily manipulating Dates and times.  While 
-      <code>java.util.Date</code> has GDK methods for adding or subtracting days,
-      this is not so useful for different durations of time.  
-      {@link groovy.time.TimeCategory TimeCategory} creates a simple internal DSL
-      for manipulating dates and times in a clean and precise fashion.  
-    </p>
-    <h3>Examples</h3>
-    <pre>
-  use ( TimeCategory ) {
-  	// application on numbers:
-  	println 1.minute.from.now
-  	println 10.days.ago
-  
-  	// application on dates
-  	def someDate = new Date()
-  	println someDate - 3.months 
-  }</pre>
-     
-    @see groovy.time.TimeCategory
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ASTTest.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ASTTest.java b/src/main/groovy/transform/ASTTest.java
deleted file mode 100644
index 1cdb480..0000000
--- a/src/main/groovy/transform/ASTTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This AST transformation aims at helping in debugging other AST transformations. It provides a basic
- * infrastructure for performing tests on AST nodes. You can place this annotation on any node which
- * accepts an annotation (types, methods, annotations, constructors, fields, local variables, packages
- * or parameters), then use a script which is run against this AST node at a specific phase. For example,
- * you could test the {@link Field} AST transformation this way:
- *
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * {@code @ASTTest}(value = {
- *    def owner = node.declaringClass
- *    assert owner.fields.any { it.name == 'x' }
- *  })
- * {@code @Field int x}
- *
- * </pre>
- *
- * The closure code is executed after the specified phase has completed. If no phase is selected, then the
- * code is executed after the {@link org.codehaus.groovy.control.CompilePhase#SEMANTIC_ANALYSIS semantic analysis} phase.
- * The <code>node</code> variable refers to the AST node where the AST test annotation is put. In the previous example,
- * it means that <i>node</i> refers to the declaration node (int x).
- *
- * @author Cedric Champeau
- * @since 2.0.0
- *
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD,
-ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.PARAMETER})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ASTTestTransformation")
-public @interface ASTTest {
-    /**
-     * The compile phase after which the test code should run.
-     */
-    CompilePhase phase() default CompilePhase.SEMANTIC_ANALYSIS;
-
-    /**
-     * A closure which is executed against the annotated node after the specified phase has completed.
-     */
-    Class value();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AnnotationCollector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollector.java b/src/main/groovy/transform/AnnotationCollector.java
deleted file mode 100644
index b9f2161..0000000
--- a/src/main/groovy/transform/AnnotationCollector.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The AnnotationCollector can be used to define aliases for groups of 
- * annotations. The Alias needs to be a class or annotation annotated with 
- * AnnotationCollector, otherwise nothing is required. The alias will be 
- * replaced on the AST level and will never appear in later. Any members of the 
- * class or annotation will be ignored, but could be used by a custom processor.
- * Annotation arguments are mapped to the aliased annotations
- * if existing. Should the default processor not be able to map one of the
- * arguments and error will be given. Is this not wished or if you want a 
- * different mapping a custom processor has to be used. There are two ways of 
- * using the alias. The first way is by providing the annotations as list/array:
- * <pre class="groovyTestCase">
- *          import groovy.transform.*
- *          &#64;AnnotationCollector([ToString, EqualsAndHashCode, Immutable])
- *          &#64;interface Alias {}
-
- *          &#64;Alias(excludes=["a"])
- *          class Foo {
- *              Integer a, b
- *          }
- *          assert Foo.class.annotations.size()==3 
- *          assert new Foo(1,2).toString() == "Foo(2)"
- * </pre>
- * In the example above we have Alias as the alias annotation and an argument
- * excludes which will be mapped to ToString and EqualsAndHashCode. Immutable 
- * doesn't have excludes, thus nothing will be done there.<br>
- * The other way is to add annotations to the alias:
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- * &#64;ToString(excludes=["a"])
- * &#64;EqualsAndHashCode
- * &#64;Immutable
- * &#64;AnnotationCollector
- * &#64;interface Alias {}
- *
- * &#64;Alias
- * class Foo {
- *     Integer a, b
- * }
- * assert Foo.class.annotations.size()==3
- * assert new Foo(1,2).toString() == "Foo(2)"
- * </pre>
- * In the example above we have again Alias as the alias annotation, but
- * this time the argument is part of the alias. Instead of mapping excludes to
- * ToString as well as EqualsAndHashCode, only ToString will have the excludes.
- * Again the alias can have an argument excludes, which would overwrite the 
- * excludes given in from the definition and be mapped to ToString as well as
- * EqualsAndHashCode.
- * If both ways are combined, then the list overwrites annotation usage.
- * NOTE: The aliasing does not support aliasing of aliased annotations. 
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.*
- * &#64;AnnotationCollector([EqualsAndHashCode, ToString])
- * &#64;interface Simple {}
- *
- *
- * &#64;Simple
- * class User {
- *     String username
- *     int age
- * }
- *
- * def user = new User(username: 'mrhaki', age: 39)
- * assert user.toString() == 'User(mrhaki, 39)'
- *
- * // We still have 2 annotations:
- * assert User.class.annotations.size() == 2
- *
- *
- * // We can use the attributes from the 
- * // grouped annotations.
- * &#64;Simple(excludes = 'street')
- * class Address {
- *     String street, town
- * }
- *
- * def address = new Address(street: 'Evergreen Terrace', town: 'Springfield') 
- * assert address.toString() == 'Address(Springfield)'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Use a custom processor to handle attributes.
- * import org.codehaus.groovy.transform.*
- * import org.codehaus.groovy.ast.*
- * import org.codehaus.groovy.control.*
- *
- * class SimpleProcessor extends AnnotationCollectorTransform {
- *
- *     public List&lt;AnnotationNode&gt; visit(AnnotationNode collector, 
- *                                       AnnotationNode aliasAnnotationUsage, 
- *                                       AnnotatedNode aliasAnnotated, 
- *                                       SourceUnit source) {
- *
- *         // Get attributes and attribute value for dontUse.
- *         def attributes = aliasAnnotationUsage.getMembers()
- *         def dontUse = attributes.get('dontUse')
- *         attributes.remove('dontUse')
- *
- *         if (dontUse) {
- *             // Assign value of dontUse to excludes attributes.
- *             aliasAnnotationUsage.addMember("excludes", dontUse)
- *         }
- *
- *         super.visit(collector, aliasAnnotationUsage, aliasAnnotated, source)
- *     }
- *
- * }
- *
- * new GroovyShell(this.class.classLoader).evaluate '''
- * import groovy.transform.*
- *
- * &#64;AnnotationCollector(value = [EqualsAndHashCode, ToString], processor = 'SimpleProcessor')
- * &#64;interface Simple {}
- *
- *
- * &#64;Simple(dontUse = 'age')
- * class User {
- *     String username
- *     int age
- * }
- *
- * def user = new User(username: 'mrhaki', age: 39)
- * assert user.toString() == 'User(mrhaki)'
- * '''
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Use AnnotationCollector as last annotation to group the
- * // previous annotations.
- * import groovy.transform.*
- * &#64;EqualsAndHashCode
- * &#64;ToString
- * &#64;AnnotationCollector
- * &#64;interface Simple {}
- *
- *
- * &#64;Simple
- * class User {
- *     String username
- * }
- *
- * def user = new User(username: 'mrhaki')
- * assert user.toString() == 'User(mrhaki)'
- * </pre>
- * 
- * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
- * @see org.codehaus.groovy.transform.AnnotationCollectorTransform
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
-public @interface AnnotationCollector {
-    /**
-     * Processor used for computing custom logic or the list of annotations, or 
-     * both. The default is org.codehaus.groovy.transform.AnnotationCollectorTransform.
-     * Custom processors need to extend that class. 
-     */
-    String processor() default "org.codehaus.groovy.transform.AnnotationCollectorTransform";
-
-    /**
-     * When the collector annotation is replaced, whether to check for duplicates between
-     * the replacement annotations and existing explicit annotations.
-     * If you use a custom processor, it is up to that processor whether it honors or ignores
-     * this parameter. The default processor honors the parameter.
-     */
-    AnnotationCollectorMode mode() default AnnotationCollectorMode.DUPLICATE;
-
-    /**
-     * List of aliased annotations.
-     */
-    Class[] value() default {};
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AnnotationCollectorMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollectorMode.java b/src/main/groovy/transform/AnnotationCollectorMode.java
deleted file mode 100644
index 308d0c0..0000000
--- a/src/main/groovy/transform/AnnotationCollectorMode.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 groovy.transform;
-
-public enum AnnotationCollectorMode {
-    // TODO should we support @Repeatable from Java 8?
-    /**
-     * Annotations from the annotation collection will always be inserted. After all transforms have been run, it will
-     * be an error if multiple annotations (excluding those with SOURCE retention) exist.
-     */
-    DUPLICATE,
-
-    /**
-     * Annotations from the collector will be added and any existing annotations with the same name will be removed.
-     */
-    PREFER_COLLECTOR,
-
-    /**
-     * Annotations from the collector will be ignored if any existing annotations with the same name are found.
-     */
-    PREFER_EXPLICIT,
-
-    /**
-     * Annotations from the collector will be added and any existing annotations with the same name will be removed but any new parameters found within existing annotations will be merged into the added annotation.
-     */
-    PREFER_COLLECTOR_MERGED,
-
-    /**
-     * Annotations from the collector will be ignored if any existing annotations with the same name are found but any new parameters on the collector annotation will be added to existing annotations.
-     */
-    PREFER_EXPLICIT_MERGED
-}


[25/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/FactoryBuilderSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/FactoryBuilderSupport.java b/src/main/groovy/groovy/util/FactoryBuilderSupport.java
new file mode 100644
index 0000000..8dbcff0
--- /dev/null
+++ b/src/main/groovy/groovy/util/FactoryBuilderSupport.java
@@ -0,0 +1,1363 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Binding;
+import groovy.lang.Closure;
+import groovy.lang.DelegatingMetaClass;
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.MetaClass;
+import groovy.lang.MissingMethodException;
+import groovy.lang.MissingPropertyException;
+import groovy.lang.Reference;
+import groovy.lang.Script;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Mix of BuilderSupport and SwingBuilder's factory support.
+ *
+ * Warning: this implementation is not thread safe and should not be used
+ * across threads in a multi-threaded environment.  A locking mechanism
+ * should be implemented by the subclass if use is expected across
+ * multiple threads.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
+ * @author Danno Ferrin
+ */
+public abstract class FactoryBuilderSupport extends Binding {
+    public static final String CURRENT_FACTORY = "_CURRENT_FACTORY_";
+    public static final String PARENT_FACTORY = "_PARENT_FACTORY_";
+    public static final String PARENT_NODE = "_PARENT_NODE_";
+    public static final String CURRENT_NODE = "_CURRENT_NODE_";
+    public static final String PARENT_CONTEXT = "_PARENT_CONTEXT_";
+    public static final String PARENT_NAME = "_PARENT_NAME_";
+    public static final String CURRENT_NAME = "_CURRENT_NAME_";
+    public static final String OWNER = "owner";
+    public static final String PARENT_BUILDER = "_PARENT_BUILDER_";
+    public static final String CURRENT_BUILDER = "_CURRENT_BUILDER_";
+    public static final String CHILD_BUILDER = "_CHILD_BUILDER_";
+    public static final String SCRIPT_CLASS_NAME = "_SCRIPT_CLASS_NAME_";
+    private static final Logger LOG = Logger.getLogger(FactoryBuilderSupport.class.getName());
+    private static final Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() {
+        public int compare(final Method o1, final Method o2) {
+            int cmp = o1.getName().compareTo(o2.getName());
+            if (cmp != 0) return cmp;
+            cmp = o1.getParameterTypes().length - o2.getParameterTypes().length;
+            return cmp;
+        }
+    };
+
+    /**
+     * Throws an exception if value is null.
+     *
+     * @param value the node's value
+     * @param name  the node's name
+     */
+    public static void checkValueIsNull(Object value, Object name) {
+        if (value != null) {
+            throw new RuntimeException("'" + name + "' elements do not accept a value argument.");
+        }
+    }
+
+    /**
+     * Checks type of value against builder type
+     *
+     * @param value the node's value
+     * @param name  the node's name
+     * @param type  a Class that may be assignable to the value's class
+     * @return true if type is assignable to the value's class, false if value
+     *         is null.
+     */
+    public static boolean checkValueIsType(Object value, Object name, Class type) {
+        if (value != null) {
+            if (type.isAssignableFrom(value.getClass())) {
+                return true;
+            } else {
+                throw new RuntimeException("The value argument of '" + name + "' must be of type "
+                        + type.getName() + ". Found: " + value.getClass());
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Checks values against factory's type
+     *
+     * @param value the node's value
+     * @param name  the node's name
+     * @param type  a Class that may be assignable to the value's class
+     * @return Returns true if type is assignable to the value's class, false if value is
+     *         null or a String.
+     */
+    public static boolean checkValueIsTypeNotString(Object value, Object name, Class type) {
+        if (value != null) {
+            if (type.isAssignableFrom(value.getClass())) {
+                return true;
+            } else if (value instanceof String) {
+                return false;
+            } else {
+                throw new RuntimeException("The value argument of '" + name + "' must be of type "
+                        + type.getName() + " or a String. Found: " + value.getClass());
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private final ThreadLocal<LinkedList<Map<String, Object>>> contexts = new ThreadLocal<LinkedList<Map<String, Object>>>();
+    protected LinkedList<Closure> attributeDelegates = new LinkedList<Closure>(); //
+    private final List<Closure> disposalClosures = new ArrayList<Closure>(); // because of reverse iteration use ArrayList
+    private final Map<String, Factory> factories = new HashMap<String, Factory>();
+    private Closure nameMappingClosure;
+    private final ThreadLocal<FactoryBuilderSupport> localProxyBuilder = new ThreadLocal<FactoryBuilderSupport>();
+    private FactoryBuilderSupport globalProxyBuilder;
+    protected LinkedList<Closure> preInstantiateDelegates = new LinkedList<Closure>();
+    protected LinkedList<Closure> postInstantiateDelegates = new LinkedList<Closure>();
+    protected LinkedList<Closure> postNodeCompletionDelegates = new LinkedList<Closure>();
+    protected Closure methodMissingDelegate;
+    protected Closure propertyMissingDelegate;
+    protected Map<String, Closure[]> explicitProperties = new HashMap<String, Closure[]>();
+    protected Map<String, Closure> explicitMethods = new HashMap<String, Closure>();
+    protected Map<String, Set<String>> registrationGroup = new HashMap<String, Set<String>>();
+    protected String registrationGroupName = ""; // use binding to store?
+
+    protected boolean autoRegistrationRunning = false;
+    protected boolean autoRegistrationComplete = false;
+
+    public FactoryBuilderSupport() {
+        this(false);
+    }
+
+    public FactoryBuilderSupport(boolean init) {
+        globalProxyBuilder = this;
+        registrationGroup.put(registrationGroupName, new TreeSet<String>());
+        if (init) {
+            autoRegisterNodes();
+        }
+    }
+
+    private Set<String> getRegistrationGroup(String name) {
+        Set<String> group = registrationGroup.get(name);
+        if (group == null ) {
+            group = new TreeSet<String>();
+            registrationGroup.put(name, group);
+        }
+        return group;
+    }
+
+    /**
+     * Ask the nodes to be registered
+     */
+    public void autoRegisterNodes() {
+        // if java did atomic blocks, this would be one
+        synchronized (this) {
+            if (autoRegistrationRunning || autoRegistrationComplete) {
+                // registration already done or in process, abort
+                return;
+            }
+        }
+        autoRegistrationRunning = true;
+        try {
+            callAutoRegisterMethods(getClass());
+        } finally {
+            autoRegistrationComplete = true;
+            autoRegistrationRunning = false;
+        }
+    }
+
+    private void callAutoRegisterMethods(Class declaredClass) {
+        if (declaredClass == null) {
+            return;
+        }
+        callAutoRegisterMethods(declaredClass.getSuperclass());
+
+        Method[] declaredMethods = declaredClass.getDeclaredMethods();
+        Arrays.sort(declaredMethods, METHOD_COMPARATOR);
+        for (Method method : declaredMethods) {
+            if (method.getName().startsWith("register") && method.getParameterTypes().length == 0) {
+                registrationGroupName = method.getName().substring("register".length());
+                registrationGroup.put(registrationGroupName, new TreeSet<String>());
+                try {
+                    if (Modifier.isPublic(method.getModifiers())) {
+                        method.invoke(this);
+                    }
+                } catch (IllegalAccessException e) {
+                    throw new RuntimeException("Could not init " + getClass().getName() + " because of an access error in " + declaredClass.getName() + "." + method.getName(), e);
+                } catch (InvocationTargetException e) {
+                    throw new RuntimeException("Could not init " + getClass().getName() + " because of an exception in " + declaredClass.getName() + "." + method.getName(), e);
+                } finally {
+                    registrationGroupName = "";
+                }
+            }
+        }
+    }
+
+    /**
+     * @param name the name of the variable to lookup
+     * @return the variable value
+     */
+    public Object getVariable(String name) {
+        try {
+            return getProxyBuilder().doGetVariable(name);
+        } catch(MissingPropertyException mpe) {
+            if(mpe.getProperty().equals(name) && propertyMissingDelegate != null) {
+                return propertyMissingDelegate.call(new Object[]{name});
+            }
+            throw mpe;
+        }
+    }
+
+    private Object doGetVariable(String name) {
+        return super.getVariable(name);
+    }
+
+    /**
+     * Sets the value of the given variable
+     *
+     * @param name  the name of the variable to set
+     * @param value the new value for the given variable
+     */
+    public void setVariable(String name, Object value) {
+        getProxyBuilder().doSetVariable(name, value);
+    }
+
+    private void doSetVariable(String name, Object value) {
+        super.setVariable(name, value);
+    }
+
+    public Map getVariables() {
+        return getProxyBuilder().doGetVariables();
+    }
+
+    private Map doGetVariables() {
+        return super.getVariables();
+    }
+
+    /**
+     * Overloaded to make variables appear as bean properties or via the subscript operator
+     */
+    public Object getProperty(String property) {
+        try {
+            return getProxyBuilder().doGetProperty(property);
+        } catch (MissingPropertyException mpe) {
+            if ((getContext() != null) && (getContext().containsKey(property))) {
+                return getContext().get(property);
+            } else {
+                try {
+                    return getMetaClass().getProperty(this, property);
+                } catch(MissingPropertyException mpe2) {
+                    if(mpe2.getProperty().equals(property) && propertyMissingDelegate != null) {
+                        return propertyMissingDelegate.call(new Object[]{property});
+                    }
+                    throw mpe2;
+                }
+            }
+        }
+    }
+
+    private Object doGetProperty(String property) {
+        Closure[] accessors = resolveExplicitProperty(property);
+        if (accessors != null) {
+            if (accessors[0] == null) {
+                // write only property
+                throw new MissingPropertyException(property + " is declared as write only");
+            } else {
+                return accessors[0].call();
+            }
+        } else {
+            return super.getProperty(property);
+        }
+    }
+
+    /**
+     * Overloaded to make variables appear as bean properties or via the subscript operator
+     */
+    public void setProperty(String property, Object newValue) {
+        getProxyBuilder().doSetProperty(property, newValue);
+    }
+
+    private void doSetProperty(String property, Object newValue) {
+        Closure[] accessors = resolveExplicitProperty(property);
+        if (accessors != null) {
+            if (accessors[1] == null) {
+                // read only property
+                throw new MissingPropertyException(property + " is declared as read only");
+            } else {
+                accessors[1].call(newValue);
+            }
+        } else {
+            super.setProperty(property, newValue);
+        }
+    }
+
+    /**
+     * @return the factory map (Unmodifiable Map).
+     */
+    public Map<String, Factory> getFactories() {
+        return Collections.unmodifiableMap(getProxyBuilder().factories);
+    }
+
+    /**
+     * @return the explicit methods map (Unmodifiable Map).
+     */
+    public Map<String, Closure> getExplicitMethods() {
+        return Collections.unmodifiableMap(getProxyBuilder().explicitMethods);
+    }
+
+    /**
+     * @return the explicit properties map (Unmodifiable Map).
+     */
+    public Map<String, Closure[]> getExplicitProperties() {
+        return Collections.unmodifiableMap(getProxyBuilder().explicitProperties);
+    }
+
+    /**
+     * @return the factory map (Unmodifiable Map).
+     */
+    public Map<String, Factory> getLocalFactories() {
+        return Collections.unmodifiableMap(factories);
+    }
+
+    /**
+     * @return the explicit methods map (Unmodifiable Map).
+     */
+    public Map<String, Closure> getLocalExplicitMethods() {
+        return Collections.unmodifiableMap(explicitMethods);
+    }
+
+    /**
+     * @return the explicit properties map (Unmodifiable Map).
+     */
+    public Map<String, Closure[]> getLocalExplicitProperties() {
+        return Collections.unmodifiableMap(explicitProperties);
+    }
+
+    public Set<String> getRegistrationGroups() {
+        return Collections.unmodifiableSet(registrationGroup.keySet());
+    }
+
+    public Set<String> getRegistrationGroupItems(String group) {
+        Set<String> groupSet = registrationGroup.get(group);
+        if (groupSet != null) {
+            return Collections.unmodifiableSet(groupSet);
+        } else {
+            return Collections.emptySet();
+        }
+    }
+
+    public List<Closure> getAttributeDelegates() {
+        return Collections.unmodifiableList(attributeDelegates);
+    }
+
+    public List<Closure> getPreInstantiateDelegates() {
+        return Collections.unmodifiableList(preInstantiateDelegates);
+    }
+
+    public List<Closure> getPostInstantiateDelegates() {
+        return Collections.unmodifiableList(postInstantiateDelegates);
+    }
+
+    public List<Closure> getPostNodeCompletionDelegates() {
+        return Collections.unmodifiableList(postNodeCompletionDelegates);
+    }
+
+    public Closure getMethodMissingDelegate() {
+        return methodMissingDelegate;
+    }
+
+    public void setMethodMissingDelegate(Closure delegate) {
+        methodMissingDelegate = delegate;
+    }
+
+    public Closure getPropertyMissingDelegate() {
+        return propertyMissingDelegate;
+    }
+
+    public void setPropertyMissingDelegate(Closure delegate) {
+        propertyMissingDelegate = delegate;
+    }
+
+    /**
+     * @return the context of the current node.
+     */
+    public Map<String, Object> getContext() {
+        LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
+        if (contexts != null && !contexts.isEmpty()) {
+            return contexts.getFirst();
+        }
+        return null;
+    }
+
+    /**
+     * @return the current node being built.
+     */
+    public Object getCurrent() {
+        return getContextAttribute(CURRENT_NODE);
+    }
+
+    /**
+     * @return the factory that built the current node.
+     */
+    public Factory getCurrentFactory() {
+        return (Factory) getContextAttribute(CURRENT_FACTORY);
+    }
+
+    /**
+     * @return the factory of the parent of the current node.
+     */
+    public String getCurrentName() {
+        return (String) getContextAttribute(CURRENT_NAME);
+    }
+
+    /**
+     * @return the builder that built the current node.
+     */
+    public FactoryBuilderSupport getCurrentBuilder() {
+        return (FactoryBuilderSupport) getContextAttribute(CURRENT_BUILDER);
+    }
+
+    /**
+     * @return the node of the parent of the current node.
+     */
+    public Object getParentNode() {
+        return getContextAttribute(PARENT_NODE);
+    }
+
+    /**
+     * @return the factory of the parent of the current node.
+     */
+    public Factory getParentFactory() {
+        return (Factory) getContextAttribute(PARENT_FACTORY);
+    }
+
+    /**
+     * @return the context of the parent of the current node.
+     */
+    public Map getParentContext() {
+        return (Map) getContextAttribute(PARENT_CONTEXT);
+    }
+
+    /**
+     * @return the name of the parent of the current node.
+     */
+    public String getParentName() {
+        return (String) getContextAttribute(PARENT_NAME);
+    }
+
+    public FactoryBuilderSupport getChildBuilder() {
+        return (FactoryBuilderSupport) getContextAttribute(CHILD_BUILDER);
+    }
+
+    public Object getContextAttribute(String key) {
+        Map context = getContext();
+        if (context != null) {
+            return context.get(key);
+        }
+        return null;
+    }
+
+    /**
+     * Convenience method when no arguments are required
+     *
+     * @param methodName the name of the method to invoke
+     * @return the result of the call
+     */
+    public Object invokeMethod(String methodName) {
+        return getProxyBuilder().invokeMethod(methodName, null);
+    }
+
+    public Object invokeMethod(String methodName, Object args) {
+        Object name = getProxyBuilder().getName(methodName);
+        Object result;
+        Object previousContext = getProxyBuilder().getContext();
+        try {
+            result = getProxyBuilder().doInvokeMethod(methodName, name, args);
+        } catch (RuntimeException e) {
+            // remove contexts created after we started
+            if (getContexts().contains(previousContext)) {
+                Map<String, Object> context = getProxyBuilder().getContext();
+                while (context != null && context != previousContext) {
+                    getProxyBuilder().popContext();
+                    context = getProxyBuilder().getContext();
+                }
+            }
+            throw e;
+        }
+        return result;
+    }
+
+    /**
+     * Add an attribute delegate so it can intercept attributes being set.
+     * Attribute delegates are fired in a FILO pattern, so that nested delegates
+     * get first crack.
+     *
+     * @param attrDelegate the closure to be called
+     * @return attrDelegate
+     */
+    public Closure addAttributeDelegate(Closure attrDelegate) {
+        getProxyBuilder().attributeDelegates.addFirst(attrDelegate);
+        return attrDelegate;
+    }
+
+    /**
+     * Remove the most recently added instance of the attribute delegate.
+     *
+     * @param attrDelegate the instance of the closure to be removed
+     */
+    public void removeAttributeDelegate(Closure attrDelegate) {
+        getProxyBuilder().attributeDelegates.remove(attrDelegate);
+    }
+
+    /**
+     * Add a preInstantiate delegate so it can intercept nodes before they are
+     * created. PreInstantiate delegates are fired in a FILO pattern, so that
+     * nested delegates get first crack.
+     *
+     * @param delegate the closure to invoke
+     * @return delegate
+     */
+    public Closure addPreInstantiateDelegate(Closure delegate) {
+        getProxyBuilder().preInstantiateDelegates.addFirst(delegate);
+        return delegate;
+    }
+
+    /**
+     * Remove the most recently added instance of the preInstantiate delegate.
+     *
+     * @param delegate the closure to invoke
+     */
+    public void removePreInstantiateDelegate(Closure delegate) {
+        getProxyBuilder().preInstantiateDelegates.remove(delegate);
+    }
+
+    /**
+     * Add a postInstantiate delegate so it can intercept nodes after they are
+     * created. PostInstantiate delegates are fired in a FILO pattern, so that
+     * nested delegates get first crack.
+     *
+     * @param delegate the closure to invoke
+     * @return delegate
+     */
+    public Closure addPostInstantiateDelegate(Closure delegate) {
+        getProxyBuilder().postInstantiateDelegates.addFirst(delegate);
+        return delegate;
+    }
+
+    /**
+     * Remove the most recently added instance of the postInstantiate delegate.
+     *
+     * @param delegate the closure to invoke
+     */
+    public void removePostInstantiateDelegate(Closure delegate) {
+        getProxyBuilder().postInstantiateDelegates.remove(delegate);
+    }
+
+    /**
+     * Add a nodeCompletion delegate so it can intercept nodes after they done
+     * with building. NodeCompletion delegates are fired in a FILO pattern, so
+     * that nested delegates get first crack.
+     *
+     * @param delegate the closure to invoke
+     * @return delegate
+     */
+    public Closure addPostNodeCompletionDelegate(Closure delegate) {
+        getProxyBuilder().postNodeCompletionDelegates.addFirst(delegate);
+        return delegate;
+    }
+
+    /**
+     * Remove the most recently added instance of the nodeCompletion delegate.
+     *
+     * @param delegate the closure to be removed
+     */
+    public void removePostNodeCompletionDelegate(Closure delegate) {
+        getProxyBuilder().postNodeCompletionDelegates.remove(delegate);
+    }
+
+    public void registerExplicitProperty(String name, Closure getter, Closure setter) {
+        registerExplicitProperty(name, registrationGroupName, getter, setter);
+    }
+
+    public void registerExplicitProperty(String name, String groupName, Closure getter, Closure setter) {
+        // set the delegate to FBS so the closure closes over the builder
+        if (getter != null) getter.setDelegate(this);
+        if (setter != null) setter.setDelegate(this);
+        explicitProperties.put(name, new Closure[]{getter, setter});
+        String methodNameBase = MetaClassHelper.capitalize(name);
+        if (getter != null) {
+            getRegistrationGroup(groupName).add("get" + methodNameBase);
+        }
+        if (setter != null) {
+            getRegistrationGroup(groupName).add("set" + methodNameBase);
+        }
+    }
+
+    public void registerExplicitMethod(String name, Closure closure) {
+        registerExplicitMethod(name, registrationGroupName, closure);
+    }
+
+    public void registerExplicitMethod(String name, String groupName, Closure closure) {
+        // set the delegate to FBS so the closure closes over the builder
+        closure.setDelegate(this);
+        explicitMethods.put(name, closure);
+        getRegistrationGroup(groupName).add(name);
+    }
+
+    /**
+     * Registers a factory for a JavaBean.<br>
+     * The JavaBean class should have a no-args constructor.
+     *
+     * @param theName   name of the node
+     * @param beanClass the factory to handle the name
+     */
+    public void registerBeanFactory(String theName, Class beanClass) {
+        registerBeanFactory(theName, registrationGroupName, beanClass);
+    }
+
+    /**
+     * Registers a factory for a JavaBean.<br>
+     * The JavaBean class should have a no-args constructor.
+     *
+     * @param theName   name of the node
+     * @param groupName thr group to register this node in
+     * @param beanClass the factory to handle the name
+     */
+    public void registerBeanFactory(String theName, String groupName, final Class beanClass) {
+        getProxyBuilder().registerFactory(theName, new AbstractFactory() {
+            public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
+                                      Map properties) throws InstantiationException, IllegalAccessException {
+                if (checkValueIsTypeNotString(value, name, beanClass)) {
+                    return value;
+                } else {
+                    return beanClass.newInstance();
+                }
+            }
+        });
+        getRegistrationGroup(groupName).add(theName);
+    }
+
+    /**
+     * Registers a factory for a node name.
+     *
+     * @param name    the name of the node
+     * @param factory the factory to return the values
+     */
+    public void registerFactory(String name, Factory factory) {
+        registerFactory(name, registrationGroupName, factory);
+    }
+
+    /**
+     * Registers a factory for a node name.
+     *
+     * @param name      the name of the node
+     * @param groupName thr group to register this node in
+     * @param factory   the factory to return the values
+     */
+    public void registerFactory(String name, String groupName, Factory factory) {
+        getProxyBuilder().factories.put(name, factory);
+        getRegistrationGroup(groupName).add(name);
+        factory.onFactoryRegistration(this, name, groupName);
+    }
+
+    /**
+     * This method is responsible for instantiating a node and configure its
+     * properties.
+     *
+     * @param name       the name of the node
+     * @param attributes the attributes for the node
+     * @param value      the value arguments for the node
+     * @return the object return from the factory
+     */
+    protected Object createNode(Object name, Map attributes, Object value) {
+        Object node;
+
+        Factory factory = getProxyBuilder().resolveFactory(name, attributes, value);
+        if (factory == null) {
+            LOG.log(Level.WARNING, "Could not find match for name '" + name + "'");
+            throw new MissingMethodExceptionNoStack((String) name, Object.class, new Object[]{attributes, value});
+            //return null;
+        }
+        getProxyBuilder().getContext().put(CURRENT_FACTORY, factory);
+        getProxyBuilder().getContext().put(CURRENT_NAME, String.valueOf(name));
+        getProxyBuilder().preInstantiate(name, attributes, value);
+        try {
+            node = factory.newInstance(getProxyBuilder().getChildBuilder(), name, value, attributes);
+            if (node == null) {
+                LOG.log(Level.WARNING, "Factory for name '" + name + "' returned null");
+                return null;
+            }
+
+            if (LOG.isLoggable(Level.FINE)) {
+                LOG.fine("For name: " + name + " created node: " + node);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create component for '" + name + "' reason: "
+                    + e, e);
+        }
+        getProxyBuilder().postInstantiate(name, attributes, node);
+        getProxyBuilder().handleNodeAttributes(node, attributes);
+        return node;
+    }
+
+    /**
+     * This is a hook for subclasses to plugin a custom strategy for mapping
+     * names to factories.
+     *
+     * @param name       the name of the factory
+     * @param attributes the attributes from the node
+     * @param value      value arguments from te node
+     * @return the Factory associated with name.<br>
+     */
+    protected Factory resolveFactory(Object name, Map attributes, Object value) {
+        getProxyBuilder().getContext().put(CHILD_BUILDER, getProxyBuilder());
+        return getProxyBuilder().getFactories().get(name);
+    }
+
+    /**
+     * This is a hook for subclasses to plugin a custom strategy for mapping
+     * names to explicit methods.
+     *
+     * @param methodName the name of the explicit method
+     * @param args       the arguments for the method
+     * @return the closure for the matched explicit method.<br>
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected Closure resolveExplicitMethod(String methodName, Object args) {
+        return getExplicitMethods().get(methodName);
+    }
+
+    /**
+     * This is a hook for subclasses to plugin a custom strategy for mapping
+     * names to property methods.
+     *
+     * @param propertyName the name of the explicit method
+     * @return the get and set closures (in that order) for the matched explicit property.<br>
+     */
+    protected Closure[] resolveExplicitProperty(String propertyName) {
+        return getExplicitProperties().get(propertyName);
+    }
+
+    /**
+     * This method is the workhorse of the builder.
+     *
+     * @param methodName the name of the method being invoked
+     * @param name       the name of the node
+     * @param args       the arguments passed into the node
+     * @return the object from the factory
+     */
+    private Object doInvokeMethod(String methodName, Object name, Object args) {
+        Reference explicitResult = new Reference();
+        if (checkExplicitMethod(methodName, args, explicitResult)) {
+            return explicitResult.get();
+        } else {
+            try {
+                return dispatchNodeCall(name, args);
+            } catch(MissingMethodException mme) {
+                if(mme.getMethod().equals(methodName) && methodMissingDelegate != null) {
+                    return methodMissingDelegate.call(new Object[]{methodName, args});
+                }
+                throw mme;
+            }
+        }
+    }
+
+    protected boolean checkExplicitMethod(String methodName, Object args, Reference result) {
+        Closure explicitMethod = resolveExplicitMethod(methodName, args);
+        if (explicitMethod != null) {
+            if (args instanceof Object[]) {
+                result.set(explicitMethod.call((Object[]) args));
+            } else {
+                //todo push through InvokerHelper.asList?
+                result.set(explicitMethod.call(args));
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Use {@link FactoryBuilderSupport#dispatchNodeCall(Object, Object)} instead.
+     */
+    @Deprecated
+    protected Object dispathNodeCall(Object name, Object args) {
+        return dispatchNodeCall(name, args);
+    }
+
+    protected Object dispatchNodeCall(Object name, Object args) {
+        Object node;
+        Closure closure = null;
+        List list = InvokerHelper.asList(args);
+
+        final boolean needToPopContext;
+        if (getProxyBuilder().getContexts().isEmpty()) {
+            // should be called on first build method only
+            getProxyBuilder().newContext();
+            needToPopContext = true;
+        } else {
+            needToPopContext = false;
+        }
+
+        try {
+            Map namedArgs = Collections.EMPTY_MAP;
+
+            // the arguments come in like [named_args?, args..., closure?]
+            // so peel off a hashmap from the front, and a closure from the
+            // end and presume that is what they meant, since there is
+            // no way to distinguish node(a:b,c,d) {..} from
+            // node([a:b],[c,d], {..}), i.e. the user can deliberately confuse
+            // the builder and there is nothing we can really do to prevent
+            // that
+
+            if ((!list.isEmpty())
+                    && (list.get(0) instanceof LinkedHashMap)) {
+                namedArgs = (Map) list.get(0);
+                list = list.subList(1, list.size());
+            }
+            if ((!list.isEmpty())
+                    && (list.get(list.size() - 1) instanceof Closure)) {
+                closure = (Closure) list.get(list.size() - 1);
+                list = list.subList(0, list.size() - 1);
+            }
+            Object arg;
+            if (list.isEmpty()) {
+                arg = null;
+            } else if (list.size() == 1) {
+                arg = list.get(0);
+            } else {
+                arg = list;
+            }
+            node = getProxyBuilder().createNode(name, namedArgs, arg);
+
+            Object current = getProxyBuilder().getCurrent();
+            if (current != null) {
+                getProxyBuilder().setParent(current, node);
+            }
+
+            if (closure != null) {
+                Factory parentFactory = getProxyBuilder().getCurrentFactory();
+                if (parentFactory.isLeaf()) {
+                    throw new RuntimeException("'" + name + "' doesn't support nesting.");
+                }
+                boolean processContent = true;
+                if (parentFactory.isHandlesNodeChildren()) {
+                    processContent = parentFactory.onNodeChildren(this, node, closure);
+                }
+                if (processContent) {
+                    // push new node on stack
+                    String parentName = getProxyBuilder().getCurrentName();
+                    Map parentContext = getProxyBuilder().getContext();
+                    getProxyBuilder().newContext();
+                    try {
+                        getProxyBuilder().getContext().put(OWNER, closure.getOwner());
+                        getProxyBuilder().getContext().put(CURRENT_NODE, node);
+                        getProxyBuilder().getContext().put(PARENT_FACTORY, parentFactory);
+                        getProxyBuilder().getContext().put(PARENT_NODE, current);
+                        getProxyBuilder().getContext().put(PARENT_CONTEXT, parentContext);
+                        getProxyBuilder().getContext().put(PARENT_NAME, parentName);
+                        getProxyBuilder().getContext().put(PARENT_BUILDER, parentContext.get(CURRENT_BUILDER));
+                        getProxyBuilder().getContext().put(CURRENT_BUILDER, parentContext.get(CHILD_BUILDER));
+                        // lets register the builder as the delegate
+                        getProxyBuilder().setClosureDelegate(closure, node);
+                        closure.call();
+                    } finally {
+                        getProxyBuilder().popContext();
+                    }
+                }
+            }
+
+            getProxyBuilder().nodeCompleted(current, node);
+            node = getProxyBuilder().postNodeCompletion(current, node);
+        } finally {
+            if (needToPopContext) {
+                // pop the first context
+                getProxyBuilder().popContext();
+            }
+        }
+        return node;
+    }
+
+    /**
+     * A hook to allow names to be converted into some other object such as a
+     * QName in XML or ObjectName in JMX.
+     *
+     * @param methodName the name of the desired method
+     * @return the object representing the name
+     */
+    public Object getName(String methodName) {
+        if (getProxyBuilder().nameMappingClosure != null) {
+            return getProxyBuilder().nameMappingClosure.call(methodName);
+        }
+        return methodName;
+    }
+
+    /**
+     * Proxy builders are useful for changing the building context, thus
+     * enabling mix &amp; match builders.
+     *
+     * @return the current builder that serves as a proxy.<br>
+     */
+    protected FactoryBuilderSupport getProxyBuilder() {
+        FactoryBuilderSupport proxy = localProxyBuilder.get();
+        if (proxy == null) {
+            return globalProxyBuilder;
+        } else {
+            return proxy;
+        }
+    }
+
+    /**
+     * Sets the builder to be used as a proxy.
+     *
+     * @param proxyBuilder the new proxy
+     */
+    protected void setProxyBuilder(FactoryBuilderSupport proxyBuilder) {
+        globalProxyBuilder = proxyBuilder;
+    }
+
+    public Closure getNameMappingClosure() {
+        return nameMappingClosure;
+    }
+
+    public void setNameMappingClosure(Closure nameMappingClosure) {
+        this.nameMappingClosure = nameMappingClosure;
+    }
+
+    /**
+     * Assigns any existing properties to the node.<br>
+     * It will call attributeDelegates before passing control to the factory
+     * that built the node.
+     *
+     * @param node       the object returned by tne node factory
+     * @param attributes the attributes for the node
+     */
+    protected void handleNodeAttributes(Object node, Map attributes) {
+        // first, short circuit
+        if (node == null) {
+            return;
+        }
+
+        for (Closure attrDelegate : getProxyBuilder().getAttributeDelegates()) {
+            FactoryBuilderSupport builder = this;
+            if (attrDelegate.getOwner() instanceof FactoryBuilderSupport) {
+                builder = (FactoryBuilderSupport) attrDelegate.getOwner();
+            } else if (attrDelegate.getDelegate() instanceof FactoryBuilderSupport) {
+                builder = (FactoryBuilderSupport) attrDelegate.getDelegate();
+            }
+
+            attrDelegate.call(new Object[]{builder, node, attributes});
+        }
+
+        if (getProxyBuilder().getCurrentFactory().onHandleNodeAttributes(getProxyBuilder().getChildBuilder(), node, attributes)) {
+            getProxyBuilder().setNodeAttributes(node, attributes);
+        }
+    }
+
+    /**
+     * Pushes a new context on the stack.
+     */
+    protected void newContext() {
+        getContexts().addFirst(new HashMap<String, Object>());
+    }
+
+    /**
+     * A hook to allow nodes to be processed once they have had all of their
+     * children applied.
+     *
+     * @param node   the current node being processed
+     * @param parent the parent of the node being processed
+     */
+    protected void nodeCompleted(Object parent, Object node) {
+        getProxyBuilder().getCurrentFactory().onNodeCompleted(getProxyBuilder().getChildBuilder(), parent, node);
+    }
+
+    /**
+     * Removes the last context from the stack.
+     *
+     * @return the content just removed
+     */
+    protected Map<String, Object> popContext() {
+        if (!getProxyBuilder().getContexts().isEmpty()) {
+            return getProxyBuilder().getContexts().removeFirst();
+        }
+        return null;
+    }
+
+    /**
+     * A hook after the factory creates the node and before attributes are set.<br>
+     * It will call any registered postInstantiateDelegates, if you override
+     * this method be sure to call this impl somewhere in your code.
+     *
+     * @param name       the name of the node
+     * @param attributes the attributes for the node
+     * @param node       the object created by the node factory
+     */
+    protected void postInstantiate(Object name, Map attributes, Object node) {
+        for (Closure postInstantiateDelegate : getProxyBuilder().getPostInstantiateDelegates()) {
+            (postInstantiateDelegate).call(new Object[]{this, attributes, node});
+        }
+    }
+
+    /**
+     * A hook to allow nodes to be processed once they have had all of their
+     * children applied and allows the actual node object that represents the
+     * Markup element to be changed.<br>
+     * It will call any registered postNodeCompletionDelegates, if you override
+     * this method be sure to call this impl at the end of your code.
+     *
+     * @param node   the current node being processed
+     * @param parent the parent of the node being processed
+     * @return the node, possibly new, that represents the markup element
+     */
+    protected Object postNodeCompletion(Object parent, Object node) {
+        for (Closure postNodeCompletionDelegate : getProxyBuilder().getPostNodeCompletionDelegates()) {
+            (postNodeCompletionDelegate).call(new Object[]{this, parent, node});
+        }
+
+        return node;
+    }
+
+    /**
+     * A hook before the factory creates the node.<br>
+     * It will call any registered preInstantiateDelegates, if you override this
+     * method be sure to call this impl somewhere in your code.
+     *
+     * @param name       the name of the node
+     * @param attributes the attributes of the node
+     * @param value      the value argument(s) of the node
+     */
+    protected void preInstantiate(Object name, Map attributes, Object value) {
+        for (Closure preInstantiateDelegate : getProxyBuilder().getPreInstantiateDelegates()) {
+            (preInstantiateDelegate).call(new Object[]{this, attributes, value});
+        }
+    }
+
+    /**
+     * Clears the context stack.
+     */
+    protected void reset() {
+        getProxyBuilder().getContexts().clear();
+    }
+
+    /**
+     * A strategy method to allow derived builders to use builder-trees and
+     * switch in different kinds of builders. This method should call the
+     * setDelegate() method on the closure which by default passes in this but
+     * if node is-a builder we could pass that in instead (or do something wacky
+     * too)
+     *
+     * @param closure the closure on which to call setDelegate()
+     * @param node    the node value that we've just created, which could be a
+     *                builder
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected void setClosureDelegate(Closure closure, Object node) {
+        closure.setDelegate(this);
+    }
+
+    /**
+     * Maps attributes key/values to properties on node.
+     *
+     * @param node       the object from the node
+     * @param attributes the attributes to be set
+     */
+    protected void setNodeAttributes(Object node, Map attributes) {
+        // set the properties
+        //noinspection unchecked
+        for (Map.Entry entry : (Set<Map.Entry>) attributes.entrySet()) {
+            String property = entry.getKey().toString();
+            Object value = entry.getValue();
+            InvokerHelper.setProperty(node, property, value);
+        }
+    }
+
+    /**
+     * Strategy method to establish parent/child relationships.
+     *
+     * @param parent the object from the parent node
+     * @param child  the object from the child node
+     */
+    protected void setParent(Object parent, Object child) {
+        getProxyBuilder().getCurrentFactory().setParent(getProxyBuilder().getChildBuilder(), parent, child);
+        Factory parentFactory = getProxyBuilder().getParentFactory();
+        if (parentFactory != null) {
+            parentFactory.setChild(getProxyBuilder().getCurrentBuilder(), parent, child);
+        }
+    }
+
+    /**
+     * @return the stack of available contexts.
+     */
+    protected LinkedList<Map<String, Object>> getContexts() {
+        LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
+        if (contexts == null) {
+            contexts = new LinkedList<Map<String, Object>>();
+            getProxyBuilder().contexts.set(contexts);
+        }
+        return contexts;
+    }
+
+    /**
+     * Stores the thread local states in a Map that can be passed across threads
+     * @return the map
+     */
+    protected Map<String, Object> getContinuationData() {
+        Map<String, Object> data = new HashMap<String, Object>();
+        data.put("proxyBuilder", localProxyBuilder.get());
+        data.put("contexts", contexts.get());
+        return data;
+    }
+
+    /**
+     * Restores the state of the current builder to the same state as an older build.
+     * 
+     * Caution, this will destroy rather than merge the current build context if there is any,
+     * @param data the data retrieved from a compatible getContinuationData call
+     */
+    protected void restoreFromContinuationData(Map<String, Object> data) {
+        //noinspection unchecked
+        localProxyBuilder.set((FactoryBuilderSupport) data.get("proxyBuilder"));
+        //noinspection unchecked
+        contexts.set((LinkedList<Map<String, Object>>) data.get("contexts"));
+    }
+
+    public Object build(Class viewClass) {
+        if (Script.class.isAssignableFrom(viewClass)) {
+            Script script = InvokerHelper.createScript(viewClass, this);
+            return build(script);
+        } else {
+            throw new RuntimeException("Only scripts can be executed via build(Class)");
+        }
+    }
+
+    public Object build(Script script) {
+        // this used to be synchronized, but we also used to remove the
+        // metaclass.  Since adding the metaclass is now a side effect, we
+        // don't need to ensure the meta-class won't be observed and don't
+        // need to hide the side effect.
+        MetaClass scriptMetaClass = script.getMetaClass();
+        script.setMetaClass(new FactoryInterceptorMetaClass(scriptMetaClass, this));
+        script.setBinding(this);
+        Object oldScriptName = getProxyBuilder().getVariables().get(SCRIPT_CLASS_NAME);
+        try {
+            getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, script.getClass().getName());
+            return script.run();
+        } finally {
+            if(oldScriptName != null) {
+                getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, oldScriptName);
+            } else {
+                getProxyBuilder().getVariables().remove(SCRIPT_CLASS_NAME);
+            }
+        }
+    }
+
+    public Object build(final String script, GroovyClassLoader loader) {
+        return build(loader.parseClass(script));
+    }
+
+    /**
+     * Switches the builder's proxyBuilder during the execution of a closure.<br>
+     * This is useful to temporary change the building context to another builder
+     * without the need for a contrived setup. It will also take care of restoring
+     * the previous proxyBuilder when the execution finishes, even if an exception
+     * was thrown from inside the closure.
+     *
+     * @param builder the temporary builder to switch to as proxyBuilder.
+     * @param closure the closure to be executed under the temporary builder.
+     * @return the execution result of the closure.
+     * @throws RuntimeException - any exception the closure might have thrown during
+     *                          execution.
+     */
+    public Object withBuilder(FactoryBuilderSupport builder, Closure closure) {
+        if (builder == null || closure == null) {
+            return null;
+        }
+
+        Object result = null;
+        Object previousContext = getProxyBuilder().getContext();
+        FactoryBuilderSupport previousProxyBuilder = localProxyBuilder.get();
+        try {
+            localProxyBuilder.set(builder);
+            closure.setDelegate(builder);
+            result = closure.call();
+        }
+        catch (RuntimeException e) {
+            // remove contexts created after we started
+            localProxyBuilder.set(previousProxyBuilder);
+            if (getProxyBuilder().getContexts().contains(previousContext)) {
+                Map<String, Object> context = getProxyBuilder().getContext();
+                while (context != null && context != previousContext) {
+                    getProxyBuilder().popContext();
+                    context = getProxyBuilder().getContext();
+                }
+            }
+            throw e;
+        }
+        finally {
+            localProxyBuilder.set(previousProxyBuilder);
+        }
+
+        return result;
+    }
+
+    /**
+     * Switches the builder's proxyBuilder during the execution of a closure.<br>
+     * This is useful to temporary change the building context to another builder
+     * without the need for a contrived setup. It will also take care of restoring
+     * the previous proxyBuilder when the execution finishes, even if an exception
+     * was thrown from inside the closure. Additionally it will use the closure's
+     * result as the value for the node identified by 'name'.
+     *
+     * @param builder the temporary builder to switch to as proxyBuilder.
+     * @param name    the node to build on the 'parent' builder.
+     * @param closure the closure to be executed under the temporary builder.
+     * @return a node that responds to value of name with the closure's result as its
+     *         value.
+     * @throws RuntimeException - any exception the closure might have thrown during
+     *                          execution.
+     */
+    public Object withBuilder(FactoryBuilderSupport builder, String name, Closure closure) {
+        if (name == null) {
+            return null;
+        }
+        Object result = getProxyBuilder().withBuilder(builder, closure);
+        return getProxyBuilder().invokeMethod(name, new Object[]{result});
+    }
+
+    /**
+     * Switches the builder's proxyBuilder during the execution of a closure.<br>
+     * This is useful to temporary change the building context to another builder
+     * without the need for a contrived setup. It will also take care of restoring
+     * the previous proxyBuilder when the execution finishes, even if an exception
+     * was thrown from inside the closure. Additionally it will use the closure's
+     * result as the value for the node identified by 'name' and assign any attributes
+     * that might have been set.
+     *
+     * @param attributes additional properties for the node on the parent builder.
+     * @param builder    the temporary builder to switch to as proxyBuilder.
+     * @param name       the node to build on the 'parent' builder.
+     * @param closure    the closure to be executed under the temporary builder.
+     * @return a node that responds to value of name with the closure's result as its
+     *         value.
+     * @throws RuntimeException - any exception the closure might have thrown during
+     *                          execution.
+     */
+    public Object withBuilder(Map attributes, FactoryBuilderSupport builder, String name, Closure closure) {
+        if (name == null) {
+            return null;
+        }
+        Object result = getProxyBuilder().withBuilder(builder, closure);
+        return getProxyBuilder().invokeMethod(name, new Object[]{attributes, result});
+    }
+
+    public void addDisposalClosure(Closure closure) {
+        disposalClosures.add(closure);
+    }
+
+    public List<Closure> getDisposalClosures() {
+        return Collections.unmodifiableList(disposalClosures);
+    }
+
+    public void dispose() {
+        for (int i = disposalClosures.size() - 1; i >= 0; i--) {
+            disposalClosures.get(i).call();
+        }
+    }
+}
+
+class FactoryInterceptorMetaClass extends DelegatingMetaClass {
+
+    FactoryBuilderSupport builder;
+
+    public FactoryInterceptorMetaClass(MetaClass delegate, FactoryBuilderSupport builder) {
+        super(delegate);
+        this.builder = builder;
+    }
+
+    public Object invokeMethod(Object object, String methodName, Object arguments) {
+        try {
+            return delegate.invokeMethod(object, methodName, arguments);
+        } catch (MissingMethodException mme) {
+            // attempt builder resolution
+            try {
+                if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
+                    // dispatch to factories if it is not a literal method
+                    return builder.invokeMethod(methodName, arguments);
+                } else {
+                    return InvokerHelper.invokeMethod(builder, methodName, arguments);
+                }
+            } catch (MissingMethodException mme2) {
+                // chain secondary exception
+                Throwable root = mme;
+                while (root.getCause() != null) {
+                    root = root.getCause();
+                }
+                root.initCause(mme2);
+                // throw original
+                throw mme;
+            }
+        }
+    }
+
+    public Object invokeMethod(Object object, String methodName, Object[] arguments) {
+        try {
+            return delegate.invokeMethod(object, methodName, arguments);
+        } catch (MissingMethodException mme) {
+            // attempt builder resolution
+            try {
+                if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
+                    // dispatch to factories if it is not a literal method
+                    return builder.invokeMethod(methodName, arguments);
+                } else {
+                    return InvokerHelper.invokeMethod(builder, methodName, arguments);
+                }
+            } catch (MissingMethodException mme2) {
+                // chain secondary exception
+                Throwable root = mme;
+                while (root.getCause() != null) {
+                    root = root.getCause();
+                }
+                root.initCause(mme2);
+                // throw original
+                throw mme;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/FileNameByRegexFinder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/FileNameByRegexFinder.groovy b/src/main/groovy/groovy/util/FileNameByRegexFinder.groovy
new file mode 100644
index 0000000..fbb16e7
--- /dev/null
+++ b/src/main/groovy/groovy/util/FileNameByRegexFinder.groovy
@@ -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 groovy.util
+
+/**
+ * Find files according to a base directory and an includes and excludes pattern.
+ * The include and exclude patterns conform to regex conventions.
+ *
+ * @author Dierk Koenig
+ * @author Paul King
+ */
+class FileNameByRegexFinder implements IFileNameFinder {
+
+    List<String> getFileNames(String basedir, String pattern) {
+        getFileNames(basedir, pattern, "")
+    }
+
+    List<String> getFileNames(String basedir, String pattern, String excludesPattern) {
+        def result = []
+        new File(basedir).eachFileRecurse {
+            if (it.path =~ pattern && (!excludesPattern || !(it.path =~ excludesPattern))) {
+                result << it.absolutePath
+            }
+        }
+        return result
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/FileTreeBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/FileTreeBuilder.groovy b/src/main/groovy/groovy/util/FileTreeBuilder.groovy
new file mode 100644
index 0000000..f76c95a
--- /dev/null
+++ b/src/main/groovy/groovy/util/FileTreeBuilder.groovy
@@ -0,0 +1,183 @@
+/*
+ *  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 groovy.util
+
+import groovy.transform.CompileStatic
+
+/**
+ * A builder dedicated at generating a file directory structure from a
+ * specification. For example, imagine that you want to create the following tree:
+ * <pre>
+ * src/
+ *  |--- main
+ *  |     |--- groovy
+ *  |            |--- Foo.groovy
+ *  |--- test
+ *        |--- groovy
+ *               |--- FooTest.groovy
+ *
+ * </pre>
+ *
+ * <p>Then you can create the structure using:</p>
+ * <pre><code>
+ *     def tree = new FileTreeBuilder()
+ *     tree.dir('src') {
+ *        dir('main') {
+ *           dir('groovy') {
+ *              file('Foo.groovy', 'println "Hello"')
+ *           }
+ *        }
+ *        dir('test') {
+ *           dir('groovy') {
+ *              file('FooTest.groovy', 'class FooTest extends GroovyTestCase {}')
+ *           }
+ *        }
+ *     }
+ * </code></pre>
+ *
+ * <p>or with this shorthand syntax:</p>
+ * <pre><code>
+ *     def tree = new FileTreeBuilder()
+ *     tree.src {
+ *        main {
+ *           groovy {
+ *              'Foo.groovy'('println "Hello"')
+ *           }
+ *        }
+ *        test {
+ *           groovy {
+ *              'FooTest.groovy'('class FooTest extends GroovyTestCase {}')
+ *           }
+ *        }
+ *     }
+ * </code></pre>
+ *
+ * @since 2.4.2
+ */
+@CompileStatic
+class FileTreeBuilder {
+
+    File baseDir
+
+    FileTreeBuilder(File baseDir = new File('.')) {
+        this.baseDir = baseDir
+    }
+
+    /**
+     * Creates a file with the specified name and the text contents using the system default encoding.
+     * @param name name of the file to be created
+     * @param contents the contents of the file, written using the system default encoding
+     * @return the file being created
+     */
+    File file(String name, CharSequence contents) {
+        new File(baseDir, name) << contents
+    }
+
+    /**
+     * Creates a file with the specified name and the specified binary contents
+     * @param name name of the file to be created
+     * @param contents the contents of the file
+     * @return the file being created
+     */
+    File file(String name, byte[] contents) {
+        new File(baseDir, name) << contents
+    }
+
+    /**
+     * Creates a file with the specified name and the contents from the source file (copy).
+     * @param name name of the file to be created
+     * @param contents the contents of the file
+     * @return the file being created
+     */
+    File file(String name, File source) {
+        // TODO: Avoid using bytes and prefer streaming copy
+        file(name, source.bytes)
+    }
+
+    /**
+     * Creates a new file in the current directory, whose contents is going to be generated in the
+     * closure. The delegate of the closure is the file being created.
+     * @param name name of the file to create
+     * @param spec closure for generating the file contents
+     * @return the created file
+     */
+    File file(String name, @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) {
+        def file = new File(baseDir, name)
+        def clone = (Closure) spec.clone()
+        clone.delegate = file
+        clone.resolveStrategy = Closure.DELEGATE_FIRST
+        clone(file)
+        file
+    }
+
+    /**
+     * Creates a new empty directory
+     * @param name the name of the directory to create
+     * @return the created directory
+     */
+    File dir(String name) {
+        def f = new File(baseDir, name)
+        f.mkdirs()
+        f
+    }
+
+    /**
+     * Creates a new directory and allows to specify a subdirectory structure using the closure as a specification
+     * @param name name of the directory to be created
+     * @param cl specification of the subdirectory structure
+     * @return the created directory
+     */
+    File dir(String name, @DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure cl) {
+        def oldBase = baseDir
+        def newBase = dir(name)
+        try {
+            baseDir = newBase
+            cl.delegate = this
+            cl.resolveStrategy = Closure.DELEGATE_FIRST
+            cl()
+        } finally {
+            baseDir = oldBase
+        }
+        newBase
+    }
+
+    File call(@DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure spec) {
+        def clone = (Closure) spec.clone()
+        clone.delegate = this
+        clone.resolveStrategy = Closure.DELEGATE_FIRST
+        clone.call()
+        baseDir
+    }
+
+
+    def methodMissing(String name, args) {
+        if (args instanceof Object[] && ((Object[]) args).length == 1) {
+            def arg = ((Object[]) args)[0]
+            if (arg instanceof Closure) {
+                dir(name, arg)
+            } else if (arg instanceof CharSequence) {
+                file(name, arg.toString())
+            } else if (arg instanceof byte[]) {
+                file(name, arg)
+            } else if (arg instanceof File) {
+                file(name, arg)
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/GroovyCollections.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/GroovyCollections.java b/src/main/groovy/groovy/util/GroovyCollections.java
new file mode 100644
index 0000000..dff062d
--- /dev/null
+++ b/src/main/groovy/groovy/util/GroovyCollections.java
@@ -0,0 +1,293 @@
+/*
+ *  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 groovy.util;
+
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A Collections utility class
+ *
+ * @author Paul King
+ * @author Jim White
+ */
+public class GroovyCollections {
+    /**
+     * Finds all combinations of items from the given collections.
+     *
+     * @param collections the given collections
+     * @return a List of the combinations found
+     * @see #combinations(Collection)
+     */
+    public static List combinations(Object[] collections) {
+        return combinations((Iterable)Arrays.asList(collections));
+    }
+
+    /**
+     * Finds all non-null subsequences of a list.
+     * E.g. <code>subsequences([1, 2, 3])</code> would be:
+     * [[1, 2, 3], [1, 3], [2, 3], [1, 2], [1], [2], [3]]
+     *
+     * @param items the List of items
+     * @return the subsequences from items
+     */
+    public static <T> Set<List<T>> subsequences(List<T> items) {
+        // items.inject([]){ ss, h -> ss.collect { it + [h] }  + ss + [[h]] }
+        Set<List<T>> ans = new HashSet<List<T>>();
+        for (T h : items) {
+            Set<List<T>> next = new HashSet<List<T>>();
+            for (List<T> it : ans) {
+                List<T> sublist = new ArrayList<T>(it);
+                sublist.add(h);
+                next.add(sublist);
+            }
+            next.addAll(ans);
+            List<T> hlist = new ArrayList<T>();
+            hlist.add(h);
+            next.add(hlist);
+            ans = next;
+        }
+        return ans;
+    }
+
+    /**
+     * @param collections the given collections
+     * @deprecated use combinations(Iterable)
+     */
+    @Deprecated
+    public static List combinations(Collection collections) {
+        return combinations((Iterable)collections);
+    }
+
+    /**
+     * Finds all combinations of items from the given Iterable aggregate of collections.
+     * So, <code>combinations([[true, false], [true, false]])</code>
+     * is <code>[[true, true], [false, true], [true, false], [false, false]]</code>
+     * and <code>combinations([['a', 'b'],[1, 2, 3]])</code>
+     * is <code>[['a', 1], ['b', 1], ['a', 2], ['b', 2], ['a', 3], ['b', 3]]</code>.
+     * If a non-collection item is given, it is treated as a singleton collection,
+     * i.e. <code>combinations([[1, 2], 'x'])</code> is <code>[[1, 'x'], [2, 'x']]</code>.
+     *
+     * @param collections the Iterable of given collections
+     * @return a List of the combinations found
+     * @since 2.2.0
+     */
+    public static List combinations(Iterable collections) {
+        List collectedCombos = new ArrayList();
+        for (Object collection : collections) {
+            Iterable items = DefaultTypeTransformation.asCollection(collection);
+            if (collectedCombos.isEmpty()) {
+                for (Object item : items) {
+                    List l = new ArrayList();
+                    l.add(item);
+                    collectedCombos.add(l);
+                }
+            } else {
+                List savedCombos = new ArrayList(collectedCombos);
+                List newCombos = new ArrayList();
+                for (Object value : items) {
+                    for (Object savedCombo : savedCombos) {
+                        List oldList = new ArrayList((List) savedCombo);
+                        oldList.add(value);
+                        newCombos.add(oldList);
+                    }
+                }
+                collectedCombos = newCombos;
+            }
+        }
+        return collectedCombos;
+    }
+
+    public static <T> List<List<T>> inits(Iterable<T> collections) {
+        List<T> copy = DefaultGroovyMethods.toList(collections);
+        List<List<T>> result = new ArrayList<List<T>>();
+        for (int i = copy.size(); i >= 0; i--) {
+            List<T> next = copy.subList(0, i);
+            result.add(next);
+        }
+        return result;
+    }
+
+    public static <T> List<List<T>> tails(Iterable<T> collections) {
+        List<T> copy = DefaultGroovyMethods.toList(collections);
+        List<List<T>> result = new ArrayList<List<T>>();
+        for (int i = 0; i <= copy.size(); i++) {
+            List<T> next = copy.subList(i, copy.size());
+            result.add(next);
+        }
+        return result;
+    }
+
+    /**
+     * Transposes an array of lists.
+     *
+     * @param lists the given lists
+     * @return a List of the transposed lists
+     * @see #transpose(List)
+     */
+    public static List transpose(Object[] lists) {
+        return transpose(Arrays.asList(lists));
+    }
+
+    /**
+     * Transposes the given lists.
+     * So, <code>transpose([['a', 'b'], [1, 2]])</code>
+     * is <code>[['a', 1], ['b', 2]]</code> and
+     * <code>transpose([['a', 'b', 'c']])</code>
+     * is <code>[['a'], ['b'], ['c']]</code>.
+     *
+     * @param lists the given lists
+     * @return a List of the transposed lists
+     */
+    public static List transpose(List lists) {
+        List result = new ArrayList();
+        if (lists.isEmpty()) return result;
+        int minSize = Integer.MAX_VALUE;
+        for (Object listLike : lists) {
+            List list = (List) DefaultTypeTransformation.castToType(listLike, List.class);
+            if (list.size() < minSize) minSize = list.size();
+        }
+        if (minSize == 0) return result;
+        for (int i = 0; i < minSize; i++) {
+            result.add(new ArrayList());
+        }
+        for (Object listLike : lists) {
+            List list = (List) DefaultTypeTransformation.castToType(listLike, List.class);
+            for (int i = 0; i < minSize; i++) {
+                List resultList = (List) result.get(i);
+                resultList.add(list.get(i));
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Selects the minimum value found in an array of items, so
+     * min([2, 4, 6] as Object[]) == 2.
+     *
+     * @param items an array of items
+     * @return the minimum value
+     */
+    public static <T> T min(T[] items) {
+        return min((Iterable<T>)Arrays.asList(items));
+    }
+
+    /**
+     * @deprecated use min(Iterable)
+     */
+    @Deprecated
+    public static <T> T min(Collection<T> items) {
+        return min((Iterable<T>)items);
+    }
+
+    /**
+     * Selects the minimum value found in an Iterable of items.
+     *
+     * @param items an Iterable
+     * @return the minimum value
+     * @since 2.2.0
+     */
+    public static <T> T min(Iterable<T> items) {
+        T answer = null;
+        for (T value : items) {
+            if (value != null) {
+                if (answer == null || ScriptBytecodeAdapter.compareLessThan(value, answer)) {
+                    answer = value;
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Selects the maximum value found in an array of items, so
+     * min([2, 4, 6] as Object[]) == 6.
+     *
+     * @param items an array of items
+     * @return the maximum value
+     */
+    public static <T> T max(T[] items) {
+        return max((Iterable<T>)Arrays.asList(items));
+    }
+
+    /**
+     * @deprecated use max(Iterable)
+     */
+    @Deprecated
+    public static <T> T max(Collection<T> items) {
+        return max((Iterable<T>)items);
+    }
+
+    /**
+     * Selects the maximum value found in an Iterable.
+     *
+     * @param items a Collection
+     * @return the maximum value
+     * @since 2.2.0
+     */
+    public static <T> T max(Iterable<T> items) {
+        T answer = null;
+        for (T value : items) {
+            if (value != null) {
+                if (answer == null || ScriptBytecodeAdapter.compareGreaterThan(value, answer)) {
+                    answer = value;
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Sums all the items from an array of items.
+     *
+     * @param items an array of items
+     * @return the sum of the items
+     */
+    public static Object sum(Object[] items) {
+        return sum((Iterable)Arrays.asList(items));
+    }
+
+    /**
+     * @deprecated use sum(Iterable)
+     */
+    @Deprecated
+    public static Object sum(Collection items) {
+        return sum((Iterable)items);
+    }
+
+    /**
+     * Sums all the given items.
+     *
+     * @param items an Iterable of items
+     * @return the sum of the item
+     * @since 2.2.0
+     */
+    public static Object sum(Iterable items) {
+        return DefaultGroovyMethods.sum(items);
+    }
+
+}


[31/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ASTTest.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ASTTest.java b/src/main/groovy/groovy/transform/ASTTest.java
new file mode 100644
index 0000000..1cdb480
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ASTTest.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 groovy.transform;
+
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This AST transformation aims at helping in debugging other AST transformations. It provides a basic
+ * infrastructure for performing tests on AST nodes. You can place this annotation on any node which
+ * accepts an annotation (types, methods, annotations, constructors, fields, local variables, packages
+ * or parameters), then use a script which is run against this AST node at a specific phase. For example,
+ * you could test the {@link Field} AST transformation this way:
+ *
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ *
+ * {@code @ASTTest}(value = {
+ *    def owner = node.declaringClass
+ *    assert owner.fields.any { it.name == 'x' }
+ *  })
+ * {@code @Field int x}
+ *
+ * </pre>
+ *
+ * The closure code is executed after the specified phase has completed. If no phase is selected, then the
+ * code is executed after the {@link org.codehaus.groovy.control.CompilePhase#SEMANTIC_ANALYSIS semantic analysis} phase.
+ * The <code>node</code> variable refers to the AST node where the AST test annotation is put. In the previous example,
+ * it means that <i>node</i> refers to the declaration node (int x).
+ *
+ * @author Cedric Champeau
+ * @since 2.0.0
+ *
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD,
+ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.PARAMETER})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ASTTestTransformation")
+public @interface ASTTest {
+    /**
+     * The compile phase after which the test code should run.
+     */
+    CompilePhase phase() default CompilePhase.SEMANTIC_ANALYSIS;
+
+    /**
+     * A closure which is executed against the annotated node after the specified phase has completed.
+     */
+    Class value();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AnnotationCollector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AnnotationCollector.java b/src/main/groovy/groovy/transform/AnnotationCollector.java
new file mode 100644
index 0000000..b9f2161
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AnnotationCollector.java
@@ -0,0 +1,199 @@
+/*
+ *  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 groovy.transform;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The AnnotationCollector can be used to define aliases for groups of 
+ * annotations. The Alias needs to be a class or annotation annotated with 
+ * AnnotationCollector, otherwise nothing is required. The alias will be 
+ * replaced on the AST level and will never appear in later. Any members of the 
+ * class or annotation will be ignored, but could be used by a custom processor.
+ * Annotation arguments are mapped to the aliased annotations
+ * if existing. Should the default processor not be able to map one of the
+ * arguments and error will be given. Is this not wished or if you want a 
+ * different mapping a custom processor has to be used. There are two ways of 
+ * using the alias. The first way is by providing the annotations as list/array:
+ * <pre class="groovyTestCase">
+ *          import groovy.transform.*
+ *          &#64;AnnotationCollector([ToString, EqualsAndHashCode, Immutable])
+ *          &#64;interface Alias {}
+
+ *          &#64;Alias(excludes=["a"])
+ *          class Foo {
+ *              Integer a, b
+ *          }
+ *          assert Foo.class.annotations.size()==3 
+ *          assert new Foo(1,2).toString() == "Foo(2)"
+ * </pre>
+ * In the example above we have Alias as the alias annotation and an argument
+ * excludes which will be mapped to ToString and EqualsAndHashCode. Immutable 
+ * doesn't have excludes, thus nothing will be done there.<br>
+ * The other way is to add annotations to the alias:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ * &#64;ToString(excludes=["a"])
+ * &#64;EqualsAndHashCode
+ * &#64;Immutable
+ * &#64;AnnotationCollector
+ * &#64;interface Alias {}
+ *
+ * &#64;Alias
+ * class Foo {
+ *     Integer a, b
+ * }
+ * assert Foo.class.annotations.size()==3
+ * assert new Foo(1,2).toString() == "Foo(2)"
+ * </pre>
+ * In the example above we have again Alias as the alias annotation, but
+ * this time the argument is part of the alias. Instead of mapping excludes to
+ * ToString as well as EqualsAndHashCode, only ToString will have the excludes.
+ * Again the alias can have an argument excludes, which would overwrite the 
+ * excludes given in from the definition and be mapped to ToString as well as
+ * EqualsAndHashCode.
+ * If both ways are combined, then the list overwrites annotation usage.
+ * NOTE: The aliasing does not support aliasing of aliased annotations. 
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.*
+ * &#64;AnnotationCollector([EqualsAndHashCode, ToString])
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki, 39)'
+ *
+ * // We still have 2 annotations:
+ * assert User.class.annotations.size() == 2
+ *
+ *
+ * // We can use the attributes from the 
+ * // grouped annotations.
+ * &#64;Simple(excludes = 'street')
+ * class Address {
+ *     String street, town
+ * }
+ *
+ * def address = new Address(street: 'Evergreen Terrace', town: 'Springfield') 
+ * assert address.toString() == 'Address(Springfield)'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Use a custom processor to handle attributes.
+ * import org.codehaus.groovy.transform.*
+ * import org.codehaus.groovy.ast.*
+ * import org.codehaus.groovy.control.*
+ *
+ * class SimpleProcessor extends AnnotationCollectorTransform {
+ *
+ *     public List&lt;AnnotationNode&gt; visit(AnnotationNode collector, 
+ *                                       AnnotationNode aliasAnnotationUsage, 
+ *                                       AnnotatedNode aliasAnnotated, 
+ *                                       SourceUnit source) {
+ *
+ *         // Get attributes and attribute value for dontUse.
+ *         def attributes = aliasAnnotationUsage.getMembers()
+ *         def dontUse = attributes.get('dontUse')
+ *         attributes.remove('dontUse')
+ *
+ *         if (dontUse) {
+ *             // Assign value of dontUse to excludes attributes.
+ *             aliasAnnotationUsage.addMember("excludes", dontUse)
+ *         }
+ *
+ *         super.visit(collector, aliasAnnotationUsage, aliasAnnotated, source)
+ *     }
+ *
+ * }
+ *
+ * new GroovyShell(this.class.classLoader).evaluate '''
+ * import groovy.transform.*
+ *
+ * &#64;AnnotationCollector(value = [EqualsAndHashCode, ToString], processor = 'SimpleProcessor')
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple(dontUse = 'age')
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki)'
+ * '''
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Use AnnotationCollector as last annotation to group the
+ * // previous annotations.
+ * import groovy.transform.*
+ * &#64;EqualsAndHashCode
+ * &#64;ToString
+ * &#64;AnnotationCollector
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ * }
+ *
+ * def user = new User(username: 'mrhaki')
+ * assert user.toString() == 'User(mrhaki)'
+ * </pre>
+ * 
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
+ * @see org.codehaus.groovy.transform.AnnotationCollectorTransform
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+public @interface AnnotationCollector {
+    /**
+     * Processor used for computing custom logic or the list of annotations, or 
+     * both. The default is org.codehaus.groovy.transform.AnnotationCollectorTransform.
+     * Custom processors need to extend that class. 
+     */
+    String processor() default "org.codehaus.groovy.transform.AnnotationCollectorTransform";
+
+    /**
+     * When the collector annotation is replaced, whether to check for duplicates between
+     * the replacement annotations and existing explicit annotations.
+     * If you use a custom processor, it is up to that processor whether it honors or ignores
+     * this parameter. The default processor honors the parameter.
+     */
+    AnnotationCollectorMode mode() default AnnotationCollectorMode.DUPLICATE;
+
+    /**
+     * List of aliased annotations.
+     */
+    Class[] value() default {};
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AnnotationCollectorMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AnnotationCollectorMode.java b/src/main/groovy/groovy/transform/AnnotationCollectorMode.java
new file mode 100644
index 0000000..308d0c0
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AnnotationCollectorMode.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 groovy.transform;
+
+public enum AnnotationCollectorMode {
+    // TODO should we support @Repeatable from Java 8?
+    /**
+     * Annotations from the annotation collection will always be inserted. After all transforms have been run, it will
+     * be an error if multiple annotations (excluding those with SOURCE retention) exist.
+     */
+    DUPLICATE,
+
+    /**
+     * Annotations from the collector will be added and any existing annotations with the same name will be removed.
+     */
+    PREFER_COLLECTOR,
+
+    /**
+     * Annotations from the collector will be ignored if any existing annotations with the same name are found.
+     */
+    PREFER_EXPLICIT,
+
+    /**
+     * Annotations from the collector will be added and any existing annotations with the same name will be removed but any new parameters found within existing annotations will be merged into the added annotation.
+     */
+    PREFER_COLLECTOR_MERGED,
+
+    /**
+     * Annotations from the collector will be ignored if any existing annotations with the same name are found but any new parameters on the collector annotation will be added to existing annotations.
+     */
+    PREFER_EXPLICIT_MERGED
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AutoClone.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AutoClone.java b/src/main/groovy/groovy/transform/AutoClone.java
new file mode 100644
index 0000000..995a187
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AutoClone.java
@@ -0,0 +1,281 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of {@code Cloneable} classes.
+ * The {@code @AutoClone} annotation instructs the compiler to execute an
+ * AST transformation which adds a public {@code clone()} method and adds
+ * {@code Cloneable} to the list of interfaces which the class implements.
+ * <p>
+ * Because the JVM doesn't have a one-size fits all cloning strategy, several
+ * customizations exist for the cloning implementation. By default, the {@code clone()}
+ * method will call {@code super.clone()} before calling {@code clone()} on each
+ * {@code Cloneable} property of the class.
+ * <p>
+ * Example usage:
+ * <pre>
+ * import groovy.transform.AutoClone
+ * {@code @AutoClone}
+ * class Person {
+ *   String first, last
+ *   List favItems
+ *   Date since
+ * }
+ * </pre>
+ * Which will create a class equivalent to the following:
+ * <pre>
+ * class Person implements Cloneable {
+ *   ...
+ *   public Person clone() throws CloneNotSupportedException {
+ *     Person result = (Person) super.clone()
+ *     result.favItems = favItems instanceof Cloneable ? (List) favItems.clone() : favItems
+ *     result.since = (Date) since.clone()
+ *     return result
+ *   }
+ *   ...
+ * }
+ * </pre>
+ * Which can be used as follows:
+ * <pre>
+ * def p = new Person(first:'John', last:'Smith', favItems:['ipod', 'shiraz'], since:new Date())
+ * def p2 = p.clone()
+ *
+ * assert p instanceof Cloneable
+ * assert p.favItems instanceof Cloneable
+ * assert p.since instanceof Cloneable
+ * assert !(p.first instanceof Cloneable)
+ *
+ * assert !p.is(p2)
+ * assert !p.favItems.is(p2.favItems)
+ * assert !p.since.is(p2.since)
+ * assert p.first.is(p2.first)
+ * </pre>
+ * In the above example, {@code super.clone()} is called which in this case
+ * calls {@code clone()} from {@code java.lang.Object}. This does a bit-wise
+ * copy of all the properties (references and primitive values). Properties
+ * like {@code first} has type {@code String} which is not {@code Cloneable}
+ * so it is left as the bit-wise copy. Both {@code Date} and {@code ArrayList}
+ * are {@code Cloneable} so the {@code clone()} method on each of those properties
+ * will be called. For the list, a shallow copy is made during its {@code clone()} method.
+ * <p>
+ * If your classes require deep cloning, it is up to you to provide the appropriate
+ * deep cloning logic in the respective {@code clone()} method for your class.
+ * <p>
+ * If one of your properties contains an object that doesn't support cloning
+ * or attempts deep copying of a data structure containing an object that
+ * doesn't support cloning, then a {@code CloneNotSupportedException} may occur
+ * at runtime.
+ * <p>
+ * Another popular cloning strategy is known as the copy constructor pattern.
+ * If any of your fields are {@code final} and {@code Cloneable} you should set
+ * {@code style=COPY_CONSTRUCTOR} which will then use the copy constructor pattern.
+ * Here is an example making use of the copy constructor pattern:
+ * <pre>
+ * import groovy.transform.AutoClone
+ * import static groovy.transform.AutoCloneStyle.*
+ * {@code @AutoClone(style=COPY_CONSTRUCTOR)}
+ * class Person {
+ *   final String first, last
+ *   final Date birthday
+ * }
+ * {@code @AutoClone(style=COPY_CONSTRUCTOR)}
+ * class Customer extends Person {
+ *   final int numPurchases
+ *   final List favItems
+ * }
+ * </pre>
+ * Which will create classes equivalent to the following:
+ * <pre>
+ * class Person implements Cloneable {
+ *   ...
+ *   protected Person(Person other) throws CloneNotSupportedException {
+ *     first = other.first
+ *     last = other.last
+ *     birthday = (Date) other.birthday.clone()
+ *   }
+ *   public Person clone() throws CloneNotSupportedException {
+ *     return new Person(this)
+ *   }
+ *   ...
+ * }
+ * class Customer extends Person {
+ *   ...
+ *   protected Customer(Customer other) throws CloneNotSupportedException {
+ *     super(other)
+ *     numPurchases = other.numPurchases
+ *     favItems = other.favItems instanceof Cloneable ? (List) other.favItems.clone() : other.favItems
+ *   }
+ *   public Customer clone() throws CloneNotSupportedException {
+ *     return new Customer(this)
+ *   }
+ *   ...
+ * }
+ * </pre>
+ * If you use this style on a child class, the parent class must
+ * also have a copy constructor (created using this annotation or by hand).
+ * This approach can be slightly slower than the traditional cloning approach
+ * but the {@code Cloneable} fields of your class can be final. When using the copy constructor style,
+ * you can provide your own custom constructor by hand if you wish. If you do so, it is up to you to
+ * correctly copy, clone or deep clone the properties of your class.
+ * <p>
+ * As a variation of the last two styles, if you set {@code style=SIMPLE}
+ * then the no-arg constructor will be called followed by setting the
+ * individual properties (and/or fields) calling {@code clone()} if the
+ * property/field implements {@code Cloneable}. Here is an example:
+ * <pre>
+ * import groovy.transform.AutoClone
+ * import static groovy.transform.AutoCloneStyle.*
+ * {@code @AutoClone(style=SIMPLE)}
+ * class Person {
+ *   final String first, last
+ *   final Date birthday
+ * }
+ * {@code @AutoClone(style=SIMPLE)}
+ * class Customer {
+ *   final List favItems
+ * }
+ * </pre>
+ * Which will create classes equivalent to the following:
+ * <pre>
+ * class Person implements Cloneable {
+ *   ...
+ *   public Person clone() throws CloneNotSupportedException {
+ *     def result = new Person()
+ *     copyOrCloneMembers(result)
+ *     return result
+ *   }
+ *   protected void copyOrCloneMembers(Person other) {
+ *     other.first = first
+ *     other.last = last
+ *     other.birthday = (Date) birthday.clone()
+ *   }
+ *   ...
+ * }
+ * class Customer extends Person {
+ *   ...
+ *   public Customer clone() throws CloneNotSupportedException {
+ *     def result = new Customer()
+ *     copyOrCloneMembers(result)
+ *     return result
+ *   }
+ *   protected void copyOrCloneMembers(Customer other) {
+ *     super.copyOrCloneMembers(other)
+ *     other.favItems = favItems instanceof Cloneable ? (List) favItems.clone() : favItems
+ *   }
+ *   ...
+ * }
+ * </pre>
+ * You would typically use this style only for base classes where you didn't
+ * want the normal {@code Object} {@code clone()} method to be called and
+ * you would typically need to use the {@code SIMPLE} style for any child classes.
+ * <p>
+ * As a final example, if your class already implements the {@code Serializable}
+ * or {@code Externalizable} interface, you can choose the following cloning style:
+ * <pre>
+ * {@code @AutoClone(style=SERIALIZATION)}
+ * class Person implements Serializable {
+ *   String first, last
+ *   Date birthday
+ * }
+ * </pre>
+ * which outputs a class with the following form:
+ * <pre>
+ * class Person implements Cloneable, Serializable {
+ *   ...
+ *   Person clone() throws CloneNotSupportedException {
+ *     def baos = new ByteArrayOutputStream()
+ *     baos.withObjectOutputStream{ it.writeObject(this) }
+ *     def bais = new ByteArrayInputStream(baos.toByteArray())
+ *     bais.withObjectInputStream(getClass().classLoader){ (Person) it.readObject() }
+ *   }
+ *   ...
+ * }
+ * </pre>
+ * This will output an error if your class doesn't implement one of
+ * {@code Serializable} or {@code Externalizable}, will typically be
+ * significantly slower than the other approaches, also doesn't
+ * allow fields to be final, will take up more memory as even immutable classes
+ * like String will be cloned but does have the advantage that it performs
+ * deep cloning automatically.
+ * <p>
+ * Further references on cloning:
+ * <ul>
+ * <li><a href="http://www.codeguru.com/java/tij/tij0128.shtml">http://www.codeguru.com/java/tij/tij0128.shtml</a>
+ * <li><a href="http://www.artima.com/objectsandjava/webuscript/ClonCollInner1.html">http://www.artima.com/objectsandjava/webuscript/ClonCollInner1.html</a>
+ * <li><a href="http://courses.dce.harvard.edu/~cscie160/JDCTipsCloning">http://courses.dce.harvard.edu/~cscie160/JDCTipsCloning</a>
+ * <li><a href="http://www.agiledeveloper.com/articles/cloning072002.htm">http://www.agiledeveloper.com/articles/cloning072002.htm</a>
+ * </ul>
+ *
+ * @author Paul King
+ * @see AutoCloneStyle
+ * @see ExternalizeMethods
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoCloneASTTransformation")
+public @interface AutoClone {
+    /**
+     * Comma separated list of property (and/or field) names to exclude from cloning.
+     * For convenience, a String with comma separated names can be used in addition
+     * to an array (using Groovy's literal list notation) of String values.
+     * <p>
+     * NOTE: When using the {@code CLONE} style, property (and/or field) copying might occur as part of
+     * calling {@code super.clone()} which will ignore this list. You can then use this list to
+     * streamline the provided {@code clone()} implementation by selecting which Cloneable properties
+     * (and/or fields) will have a subsequent call to their {@code clone()} method. If you have
+     * immutable properties (and/or fields) this can be useful as the extra {@code clone()} will
+     * not be necessary and cloning will be more efficient.
+     * <p>
+     * NOTE: This doesn't affect property (and/or field) copying that might occur as part
+     * of serialization when using the {@code SERIALIZATION} style, i.e. this flag is ignored;
+     * instead adjust your serialization code to include or exclude the desired
+     * properties (and/or fields) which should carry over during cloning.
+     */
+    String[] excludes() default {};
+
+    /**
+     * Include fields as well as properties when cloning.
+     * <p>
+     * NOTE: When using the {@code CLONE} style, field copying might occur as part of
+     * calling {@code super.clone()} and might be all you require; if you turn on
+     * this flag, the provided {@code clone()} implementation will also
+     * subsequently call {@code clone()} for each {@code Cloneable} field which can be
+     * useful if you have mutable fields.
+     * <p>
+     * NOTE: This doesn't affect field copying that might occur as part of
+     * serialization when using the {@code SERIALIZATION} style, i.e. this flag is ignored;
+     * instead adjust your serialization code to include or exclude your fields.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Style to use when cloning.
+     */
+    AutoCloneStyle style() default AutoCloneStyle.CLONE;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AutoCloneStyle.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AutoCloneStyle.java b/src/main/groovy/groovy/transform/AutoCloneStyle.java
new file mode 100644
index 0000000..81b0ebd
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AutoCloneStyle.java
@@ -0,0 +1,48 @@
+/*
+ *  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 groovy.transform;
+
+/**
+ * Intended style to use for cloning when using the {@code @}AutoClone annotation.
+ *
+ * @author Paul King
+ * @since 1.8.0
+ * @see groovy.transform.AutoClone
+ */
+public enum AutoCloneStyle {
+    /**
+     * Uses only cloning.
+     */
+    CLONE,
+
+    /**
+     * Uses the no-arg constructor followed by property/field copying/cloning.
+     */
+    SIMPLE,
+
+    /**
+     * Uses the copy constructor pattern.
+     */
+    COPY_CONSTRUCTOR,
+
+    /**
+     * Uses serialization to clone.
+     */
+    SERIALIZATION
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AutoExternalize.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AutoExternalize.groovy b/src/main/groovy/groovy/transform/AutoExternalize.groovy
new file mode 100644
index 0000000..d1356b9
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AutoExternalize.groovy
@@ -0,0 +1,66 @@
+/*
+ *  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 groovy.transform
+
+/**
+ * Class annotation used to assist in the creation of {@code Externalizable} classes.
+ * The {@code @AutoExternalize} annotation instructs the compiler to execute an
+ * AST transformation which adds {@code writeExternal()} and {@code readExternal()} methods
+ * to a class and adds {@code Externalizable} to the interfaces which the class implements.
+ * The {@code writeExternal()} method writes each property (or field) for the class while the
+ * {@code readExternal()} method will read each one back in the same order. Properties or fields
+ * marked as {@code transient} are ignored.
+ * <p>
+ * Example usage:
+ * <pre>
+ * import groovy.transform.*
+ * {@code @AutoExternalize}
+ * class Person {
+ *   String first, last
+ *   List favItems
+ *   Date since
+ * }
+ * </pre>
+ * Which will create a class of the following form:
+ * <pre>
+ * class Person implements Externalizable {
+ *   ...
+ *   public void writeExternal(ObjectOutput out) throws IOException {
+ *     out.writeObject(first)
+ *     out.writeObject(last)
+ *     out.writeObject(favItems)
+ *     out.writeObject(since)
+ *   }
+ *
+ *   public void readExternal(ObjectInput oin) {
+ *     first = oin.readObject()
+ *     last = oin.readObject()
+ *     favItems = oin.readObject()
+ *     since = oin.readObject()
+ *   }
+ *   ...
+ * }
+ * </pre>
+ * <p>
+ * The {@code @AutoExternalize} transform is implemented as a combination of the {@code @ExternalizeMethods} and {@code @ExternalizeVerifier} transforms.
+ *
+ * @since 1.8.0
+ */
+@AnnotationCollector([ExternalizeMethods, ExternalizeVerifier])
+@interface AutoExternalize { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AutoFinal.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AutoFinal.java b/src/main/groovy/groovy/transform/AutoFinal.java
new file mode 100644
index 0000000..58ce3ba
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AutoFinal.java
@@ -0,0 +1,99 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to automatically add the final qualifier to method, constructor,
+ * and closure parameters.
+ * <p>The annotation can be placed at the class level in which case it applies to
+ * all methods, constructors, and closures within the class and any inner classes.
+ * It can also be applied to an individual method, constructor, field with a
+ * Closure initial value or a Closure assigned to a local variable. In the case
+ * of fields (or local variables) it only adjusts the parameters of the referenced
+ * Closure not the field (or local variable) itself.
+ * <p>If you wish to automatically apply the
+ * annotation to all classes of a project, consider using
+ * {@code groovyc --configscript}. Google "Customising The Groovy Compiler",
+ * or see {@link CompilerConfiguration} for further details.
+ * This will ensure that all arguments will automatically be final,
+ * completely eliminating the need to clutter the code with final keywords
+ * in any parameter list.
+ * <p>
+ * <em>Example usage:</em>
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.AutoFinal}
+ * class Person {
+ *     final String first, last
+ *     Person(String first, String last) {
+ *         this.first = first
+ *         this.last = last
+ *     }
+ *     String fullName(boolean reversed = false, String separator = ' ') {
+ *         final concatCls = { String n0, String n1 -> "$n0$separator$n1" }
+ *         concatCls(reversed ? last : first, reversed ? first : last)
+ *     }
+ * }
+ *
+ * final js = new Person('John', 'Smith')
+ * assert js.fullName() == 'John Smith'
+ * assert js.fullName(true, ', ') == 'Smith, John'
+ * </pre>
+ * for this case, the constructor for the <code>Person</code> class will be
+ * equivalent to the following code:
+ * <pre>
+ * Person(final String first, final String last) {
+ *   ...
+ * }
+ * </pre>
+ * And after normal default parameter processing takes place, the following overloaded methods will exist:
+ * <pre>
+ * String fullName(final boolean reversed, final String separator) { ... }
+ * String fullName(final boolean reversed) { fullName(reversed, ' ') }
+ * String fullName() { fullName(false) }
+ * </pre>
+ * and the closure will have become:
+ * <pre>
+ * { final String n0, final String n1 -> "$n0$separator$n1" }
+ * </pre>
+ *
+ * @since 2.5.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoFinalASTTransformation")
+public @interface AutoFinal {
+    /**
+     * Indicates that adding final to parameters should not be applied on this node.
+     * <p>Normally not required since leaving off the annotation will achieve the same affect.
+     * However, it can be useful for selectively disabling this annotation in just a small part
+     * of an otherwise annotated class. As an example, it would make sense to set this to {@code false} on
+     * a method which altered parameters in a class already marked as {@code @AutoFinal}.
+     * All nodes in the class except that single method would be processed.
+     */
+    boolean enabled() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/AutoImplement.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/AutoImplement.java b/src/main/groovy/groovy/transform/AutoImplement.java
new file mode 100644
index 0000000..57e8152
--- /dev/null
+++ b/src/main/groovy/groovy/transform/AutoImplement.java
@@ -0,0 +1,128 @@
+/*
+ * 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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to provide default dummy methods for a class extending an abstract super class or
+ * implementing one or more interfaces.
+ * <p>
+ * Example usage:
+ * <pre>
+ * import groovy.transform.AutoImplement
+ *
+ * {@code @AutoImplement}
+ * class EmptyStringIterator implements Iterator<String> {
+ *     boolean hasNext() { false }
+ * }
+ *
+ * assert !new EmptyStringIterator().hasNext()
+ * </pre>
+ * In the above example, since {@code hasNext} returns false, the {@code next} method
+ * should never be called, so any dummy implementation would do for {@code next}.
+ * The "empty" implementation provided by default when using {@code @AutoImplement}
+ * will suffice - which effectively returns {@code null} in Groovy for non-void,
+ * non-primitive methods.
+ *
+ * As a point of interest, the default implementation for methods returning primitive
+ * types is to return the default value (which incidentally never satisfies Groovy truth).
+ * For {@code boolean} this means returning {@code false}, so for the above example we
+ * could have (albeit perhaps less instructive of our intent) by just using:
+ * <pre>
+ * {@code @AutoImplement}
+ * class EmptyStringIterator implements Iterator<String> { }
+ * </pre>
+ * If we didn't want to assume that callers of our {@code EmptyStringIterator} correctly followed
+ * the {@code Iterator} contract, then we might want to guard against inappropriate calls to {@code next}.
+ * Rather than just returning {@code null}, we might want to throw an exception. This is easily done using
+ * the {@code exception} annotation attribute as shown below:
+ * <pre>
+ * import groovy.transform.AutoImplement
+ * import static groovy.test.GroovyAssert.shouldFail
+ *
+ * {@code @AutoImplement}(exception=UnsupportedOperationException)
+ * class EmptyStringIterator implements Iterator<String> {
+ *     boolean hasNext() { false }
+ * }
+ *
+ * shouldFail(UnsupportedOperationException) {
+ *     new EmptyStringIterator().next()
+ * }
+ * </pre>
+ * All implemented methods will throw an instance of this exception constructed using its no-arg constructor.
+ *
+ * You can also supply a single {@code message} annotation attribute in which case the message will be passed
+ * as an argument during exception construction as shown in the following example:
+ * <pre>
+ * {@code @AutoImplement}(exception=UnsupportedOperationException, message='Not supported for this empty iterator')
+ * class EmptyStringIterator implements Iterator<String> {
+ *     boolean hasNext() { false }
+ * }
+ *
+ * def ex = shouldFail(UnsupportedOperationException) {
+ *     new EmptyStringIterator().next()
+ * }
+ * assert ex.message == 'Not supported for this empty iterator'
+ * </pre>
+ * Finally, you can alternatively supply a {@code code} annotation attribute in which case a closure
+ * block can be supplied which should contain the code to execute for all implemented methods. This can be
+ * seen in the following example:
+ * <pre>
+ * {@code @AutoImplement}(code = { throw new UnsupportedOperationException("Not supported for ${getClass().simpleName}") })
+ * class EmptyStringIterator implements Iterator<String> {
+ *     boolean hasNext() { false }
+ * }
+ *
+ * def ex = shouldFail(UnsupportedOperationException) {
+ *     new EmptyStringIterator().next()
+ * }
+ * assert ex.message == 'Not supported for EmptyStringIterator'
+ * </pre>
+ *
+ * @since 2.5.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoImplementASTTransformation")
+public @interface AutoImplement {
+    /**
+     * If defined, all unimplemented methods will throw this exception.
+     * Will be ignored if {@code code} is defined.
+     */
+    Class<? extends RuntimeException> exception() default Undefined.EXCEPTION.class;
+
+    /**
+     * If {@code exception} is defined, {@code message} can be used to specify the exception message.
+     * Will be ignored if {@code code} is defined or {@code exception} isn't defined.
+     */
+    String message() default Undefined.STRING;
+
+    /**
+     * If defined, all unimplemented methods will execute the code found within the supplied closure.
+     */
+    Class code() default Undefined.CLASS.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/BaseScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/BaseScript.java b/src/main/groovy/groovy/transform/BaseScript.java
new file mode 100644
index 0000000..2720b79
--- /dev/null
+++ b/src/main/groovy/groovy/transform/BaseScript.java
@@ -0,0 +1,154 @@
+/*
+ *  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 groovy.transform;
+
+import groovy.lang.Script;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Variable annotation used for changing the base script class of the current script.
+ * <p>
+ * The type of the variable annotated with {@code @BaseScript} must extend {@link groovy.lang.Script}.
+ * It will be used as the base script class.
+ * The annotated variable will become shortcut to <code>this</code> object.
+ * Using this annotation will override base script set by Groovy compiler or
+ * {@link org.codehaus.groovy.control.CompilerConfiguration} of {@link groovy.lang.GroovyShell}
+ * Example usage:
+ * <pre>
+ * abstract class CustomScript extends Script {
+ *     int getTheMeaningOfLife() { 42 }
+ * }
+ *
+ * &#64;BaseScript CustomScript baseScript
+ *
+ * assert baseScript == this
+ * assert theMeaningOfLife == 42
+ * assert theMeaningOfLife == baseScript.theMeaningOfLife
+ * </pre>
+ * In this example, the base script of the current script will be changed to 
+ * <code>CustomScript</code> allowing usage of <code>getTheMeaningOfLife()</code>
+ * method. <code>baseScript</code> variable will become typed shortcut for 
+ * <code>this</code> object which enables better IDE support.
+ * </p><p>
+ * The custom base script may implement the run() method and specify a different
+ * method name to be used for the script body by declaring a single abstract method.
+ * For example:
+ * <pre>
+ * abstract class CustomScriptBodyMethod extends Script {
+ *     abstract def runScript()
+ *     def preRun() { println "preRunning" }
+ *     def postRun() { println "postRunning" }
+ *     def run() {
+ *         preRun()
+ *         try {
+ *             3.times { runScript() }
+ *         } finally {
+ *             postRun()
+ *         }
+ *     }
+ * }
+ *
+ * {@code @BaseScript} CustomScriptBodyMethod baseScript
+ * println "Script body run"
+ * </pre>
+ * That will produce the following output:
+ * <pre>
+ * preRunning
+ * Script body run
+ * Script body run
+ * Script body run
+ * postRunning
+ * </pre>
+ *
+ * Note that while you can declare arguments for the script body's method, as
+ * the AST is currently implemented they are not accessible in the script body code.
+ * </p>
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * // Simple Car class to save state and distance.
+ * class Car {
+ *     String state
+ *     Long distance = 0
+ * }
+ *
+ * // Custom Script with methods that change the Car's state.
+ * // The Car object is passed via the binding.
+ * abstract class CarScript extends Script {
+ *     def start() {
+ *         this.binding.car.state = 'started'
+ *     }
+ *
+ *     def stop() {
+ *         this.binding.car.state = 'stopped'
+ *     }
+ *
+ *     def drive(distance) {
+ *         this.binding.car.distance += distance
+ *     }
+ * }
+ *
+ *
+ * // Define Car object here, so we can use it in assertions later on.
+ * def car = new Car()
+ * // Add to script binding (CarScript references this.binding.car).
+ * def binding = new Binding(car: car)
+ *
+ * // Configure the GroovyShell.
+ * def shell = new GroovyShell(this.class.classLoader, binding)
+ *
+ * // Simple DSL to start, drive and stop the car.
+ * // The methods are defined in the CarScript class.
+ * def carDsl = '''
+ * start()
+ * drive 20
+ * stop()
+ * '''
+ *
+ *
+ * // Run DSL script.
+ * shell.evaluate """
+ * // Use BaseScript annotation to set script
+ * // for evaluating the DSL.
+ * &#64;groovy.transform.BaseScript CarScript carScript
+ *
+ * $carDsl
+ * """
+ *
+ * // Checks to see that Car object has changed.
+ * assert car.distance == 20
+ * assert car.state == 'stopped'
+ * </pre>
+ * 
+ * @author Paul King
+ * @author Vladimir Orany
+ * @author Jim White
+ * @since 2.2.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.TYPE /*, ElementType.IMPORT*/})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.BaseScriptASTTransformation")
+public @interface BaseScript {
+    Class value() default Script.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Canonical.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Canonical.groovy b/src/main/groovy/groovy/transform/Canonical.groovy
new file mode 100644
index 0000000..6f99c80
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Canonical.groovy
@@ -0,0 +1,131 @@
+/*
+ *  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 groovy.transform
+/**
+ * The {@code @Canonical} meta-annotation combines the {@code @EqualsAndHashCode},
+ * {@code @ToString} and {@code @TupleConstructor} annotations. It is used to assist in
+ * the creation of mutable classes. It instructs the compiler to execute AST transformations
+ * which add positional constructors, equals, hashCode and a pretty print toString to your class.
+ * <p>
+ * You can write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.Canonical
+ * {@code @Canonical} class Customer {
+ *     String first, last
+ *     int age
+ *     Date since
+ *     Collection favItems = ['Food']
+ *     def object 
+ * }
+ * def d = new Date()
+ * def anyObject = new Object()
+ * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:d, favItems:['Books', 'Games'], object: anyObject)
+ * def c2 = new Customer('Tom', 'Jones', 21, d, ['Books', 'Games'], anyObject)
+ * assert c1 == c2
+ * </pre>
+ *
+ * You don't need to provide all arguments in constructor calls. If using named parameters, any property names not
+ * referenced will be given their default value (as per Java's default unless an explicit initialization constant is
+ * provided when defining the property). If using a tuple constructor, parameters are supplied in the order in which
+ * the properties are defined. Supplied parameters fill the tuple from the left. Any parameters missing on the right
+ * are given their default value.
+ * <pre>
+ * def c3 = new Customer(last: 'Jones', age: 21)
+ * def c4 = new Customer('Tom', 'Jones')
+ *
+ * assert null == c3.since
+ * assert 0 == c4.age
+ * assert c3.favItems == ['Food'] && c4.favItems == ['Food']
+ * </pre>
+ *
+ * If you don't need all of the functionality of {@code @Canonical}, you can simply directly use one or more of the individual
+ * annotations which {@code @Canonical} aggregates.
+ * In addition, you can use {@code @Canonical} in combination with explicit use one or more of the individual annotations in
+ * cases where you need to further customize the annotation attributes.
+ * Any applicable annotation attributes from {@code @Canonical} missing from the explicit annotation will be merged
+ * but any existing annotation attributes within the explicit annotation take precedence. So, for example in this case here:
+ * <pre>
+ * {@code @Canonical}(includeNames=true, excludes='c')
+ * {@code @}{@link ToString}(excludes='a,b')
+ * class MyClass { ... }
+ * </pre>
+ * The generated {@code toString} will include property names and exclude the {@code a} and {@code b} properties.
+ * <p>
+ * A class created using {@code @Canonical} has the following characteristics:
+ * <ul>
+ * <li>A no-arg constructor is provided which allows you to set properties by name using Groovy's normal bean conventions.
+ * <li>Tuple-style constructors are provided which allow you to set properties in the same order as they are defined.
+ * <li>Default {@code equals}, {@code hashCode} and {@code toString} methods are provided based on the property values.
+ * See the GroovyDoc for the individual annotations for more details.
+ * <p>
+ * If you want similar functionality to what this annotation provides but also require immutability, see the
+ * {@code @}{@link Immutable} annotation.
+ * 
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ *
+ * &#64;Canonical
+ * class Building {
+ *     String name
+ *     int floors
+ *     boolean officeSpace
+ * }
+ *
+ * // Constructors are added.
+ * def officeSpace = new Building('Initech office', 1, true)
+ *
+ * // toString() added.
+ * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
+ *
+ * // Default values are used if constructor
+ * // arguments are not assigned.
+ * def theOffice = new Building('Wernham Hogg Paper Company')
+ * assert theOffice.floors == 0
+ * theOffice.officeSpace = true
+ *
+ * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
+ *
+ * // equals() method is added.
+ * assert anotherOfficeSpace == officeSpace
+ *
+ * // equals() and hashCode() are added, so duplicate is not in Set.
+ * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
+ * assert offices.size() == 2 
+ * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
+ *
+ * &#64;Canonical
+ * &#64;ToString(excludes='age')  // Customize one of the transformations.
+ * class Person {
+ *     String name
+ *     int age
+ * }
+ *
+ * def mrhaki = new Person('mrhaki', 37)
+ * assert mrhaki.toString() == 'Person(mrhaki)'
+ * </pre>
+ *
+ * @see groovy.transform.EqualsAndHashCode
+ * @see groovy.transform.ToString
+ * @see groovy.transform.TupleConstructor
+ * @see groovy.transform.Immutable
+ * @since 1.8.0
+ */
+@AnnotationCollector(value=[ToString, TupleConstructor, EqualsAndHashCode], mode=AnnotationCollectorMode.PREFER_EXPLICIT_MERGED)
+public @interface Canonical { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/CompilationUnitAware.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/CompilationUnitAware.java b/src/main/groovy/groovy/transform/CompilationUnitAware.java
new file mode 100644
index 0000000..b609f43
--- /dev/null
+++ b/src/main/groovy/groovy/transform/CompilationUnitAware.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 groovy.transform;
+
+import org.codehaus.groovy.control.CompilationUnit;
+
+/**
+ * This interface is for AST transformations which must be aware of the compilation unit where they are applied.
+ *
+ * @author Cedric Champeau
+ */
+public interface CompilationUnitAware {
+    void setCompilationUnit(CompilationUnit unit);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/CompileDynamic.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/CompileDynamic.groovy b/src/main/groovy/groovy/transform/CompileDynamic.groovy
new file mode 100644
index 0000000..c5247d4
--- /dev/null
+++ b/src/main/groovy/groovy/transform/CompileDynamic.groovy
@@ -0,0 +1,34 @@
+/*
+ *  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 groovy.transform
+
+import java.lang.annotation.Documented
+
+/**
+ * An annotation which is just a shortcut for @CompileStatic(TypeCheckingMode.SKIP).
+ * This can be used for example if you statically compile a full class but you want to skip
+ * some methods without having to use the full annotation.
+ *
+ * @author Cedric Champeau
+ * @since 2.1.0
+ */
+@Documented
+@AnnotationCollector(processor = "org.codehaus.groovy.transform.CompileDynamicProcessor")
+public @interface CompileDynamic {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/CompileStatic.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/CompileStatic.java b/src/main/groovy/groovy/transform/CompileStatic.java
new file mode 100644
index 0000000..16dbc33
--- /dev/null
+++ b/src/main/groovy/groovy/transform/CompileStatic.java
@@ -0,0 +1,63 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This will let the Groovy compiler use compile time checks in the style of Java
+ * then perform static compilation, thus bypassing the Groovy meta object protocol.
+ * <p>
+ * When a class is annotated, all methods, properties, files, inner classes, etc.
+ * of the annotated class will be type checked. When a method is annotated, static
+ * compilation applies only to items (closures and anonymous inner classes) within
+ * the method.
+ * <p>
+ * By using {@link TypeCheckingMode#SKIP}, static compilation can be skipped on an
+ * element within a class or method otherwise marked with CompileStatic. For example
+ * a class can be annotated with CompileStatic, and a method within can be marked
+ * to skip static checking to use dynamic language features.
+ *
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
+ * @author Cedric Champeau
+ *
+ * @see CompileDynamic
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({   ElementType.METHOD,         ElementType.TYPE,
+            ElementType.CONSTRUCTOR
+})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.sc.StaticCompileTransformation")
+public @interface CompileStatic {
+    TypeCheckingMode value() default TypeCheckingMode.PASS;
+
+    /**
+     * The list of (classpath resources) paths to type checking DSL scripts, also known
+     * as type checking extensions.
+     * @return an array of paths to groovy scripts that must be on compile classpath
+     */
+    String[] extensions() default {};
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ConditionalInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ConditionalInterrupt.groovy b/src/main/groovy/groovy/transform/ConditionalInterrupt.groovy
new file mode 100644
index 0000000..66aa64c
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ConditionalInterrupt.groovy
@@ -0,0 +1,155 @@
+/*
+ *  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 groovy.transform
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.ElementType
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+import java.lang.annotation.Target
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding a custom check for interruption
+ * into loops (for, while, ...) and at the start of closures and methods.
+ * <p>
+ * This is especially useful when executing foreign scripts that you do not have control over. Inject this
+ * transformation into a script that you need to interrupt based on some custom criteria.
+ * <p>
+ * Annotating anything in a script will cause for loops, while loops, methods, and closures to make a
+ * check against the specified closure. If the closure yields true (according to GroovyTruth), then the script
+ * will throw an InterruptedException. The annotation by default applies to any classes defined in the script
+ * as well. Annotated a class will cause (by default) all classes in the entire file ('Compilation Unit') to be
+ * enhanced. You can fine tune what is enhanced using the annotation parameters.
+ * <p>
+ * The following is sample usage of the annotation:
+ * <pre>
+ * <code>@ConditionalInterrupt({ counter++> 10})</code>
+ * import groovy.transform.ConditionalInterrupt
+ *
+ * counter = 0
+ * def scriptMethod() {
+ *      4.times {
+ *          println 'executing script method...'
+ *      }
+ * }
+ *
+ * scriptMethod()
+ * </pre>
+ * Which results in the following code being generated (XXXXXX will be replaced with some runtime generated hashCode). Notice the checks and exceptions:
+ * <pre>
+ * public class script1291741477073 extends groovy.lang.Script {
+ *   Object counter = 0
+ *
+ *   public java.lang.Object run() {
+ *     counter = 0
+ *   }
+ *
+ *   public java.lang.Object scriptMethod() {
+ *     if (this.conditionalTransformXXXXXX$condition()) {
+ *       throw new java.lang.InterruptedException('Execution interrupted. The following condition failed: { counter++> 10}')
+ *     }
+ *     4.times({
+ *       if (this.conditionalTransformXXXXXX$condition()) {
+ *         throw new java.lang.InterruptedException('Execution interrupted. The following condition failed: { counter++> 10}')
+ *       }
+ *       this.println('executing script method...')
+ *     })
+ *   }
+ *
+ *   private java.lang.Object conditionalTransformXXXXXX$condition() {
+ *     counter++ > 10
+ *   }
+ * }
+ * </pre>
+ *
+ * Note that when you're annotating scripts, the variable scoping semantics are unchanged. Therefore, you must be
+ * careful about the variable scope you're using. Make sure that variables you reference in the closure parameter
+ * are in scope during script execution. The following example will throw a MissingPropertyException because
+ * counter is not in scope for a class:
+ * <pre>
+ * import groovy.transform.ConditionalInterrupt
+ *
+ * def counter = 0
+ * <code>@ConditionalInterrupt({ counter++> 10})</code>
+ * class MyClass {
+ *   def myMethod() {
+ *     4.times {
+ *       println 'executing script method...'
+ *     }
+ *   }
+ * }
+ *
+ * new MyClass().myMethod()
+ * </pre>
+ * Additional usage examples can be found in the unit test for this class.
+ *
+ * @see TimedInterrupt
+ * @see ThreadInterrupt
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ * @author Paul King
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target([ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
+@GroovyASTTransformationClass(["org.codehaus.groovy.transform.ConditionalInterruptibleASTTransformation"])
+@interface ConditionalInterrupt {
+  /**
+   * Set this to false if you have multiple classes within one source file and only
+   * want a conditional check on some of the classes. Place annotations on the classes
+   * you want enhanced. Set to true (the default) for blanket coverage of conditional
+   * checks on all methods, loops and closures within all classes/script code.
+   *
+   * For even finer-grained control see {@code applyToAllMembers}.
+   *
+   * @see #applyToAllMembers()
+   */
+  boolean applyToAllClasses() default true
+
+  /**
+   * Set this to false if you have multiple methods/closures within a class or script and only
+   * want conditional checks on some of them. Place annotations on the methods/closures that
+   * you want enhanced. When false, {@code applyToAllClasses} is automatically set to false.
+   *
+   * Set to true (the default) for blanket coverage of conditional checks on all methods, loops
+   * and closures within the class/script.
+   *
+   * @since 2.2.0
+   * @see #applyToAllClasses()
+   */
+  boolean applyToAllMembers() default true
+
+  /**
+   * By default a conditional check is added to the start of all user-defined methods. To turn this off simply
+   * set this parameter to false.
+   */
+  boolean checkOnMethodStart() default true
+
+  /**
+   * Sets the type of exception which is thrown.
+   */
+  Class thrown() default InterruptedException
+
+  /**
+   * Conditional check - set as a closure expression.
+   */
+  Class value()
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/EqualsAndHashCode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/EqualsAndHashCode.java b/src/main/groovy/groovy/transform/EqualsAndHashCode.java
new file mode 100644
index 0000000..592c6ba
--- /dev/null
+++ b/src/main/groovy/groovy/transform/EqualsAndHashCode.java
@@ -0,0 +1,276 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in creating appropriate {@code equals()} and {@code hashCode()} methods.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.EqualsAndHashCode
+ * {@code @EqualsAndHashCode}
+ * class Person {
+ *     String first, last
+ *     int age
+ * }
+ * def p1 = new Person(first:'John', last:'Smith', age:21)
+ * def p2 = new Person(first:'John', last:'Smith', age:21)
+ * assert p1 == p2
+ * def map = [:]
+ * map[p1] = 45
+ * assert map[p2] == 45
+ * </pre>
+ * The {@code @EqualsAndHashCode} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary equals and hashCode methods to the class.
+ * <p>
+ * The {@code hashCode()} method is calculated using Groovy's {@code HashCodeHelper} class
+ * which implements an algorithm similar to the one outlined in the book <em>Effective Java</em>.
+ * <p>
+ * The {@code equals()} method compares the values of the individual properties (and optionally fields)
+ * of the class.  It can also optionally call equals on the super class. Two different equals method
+ * implementations are supported both of which support the equals contract outlined in the javadoc
+ * for <code>java.lang.Object</code>
+ * <p>
+ * To illustrate the 'canEqual' implementation style (see http://www.artima.com/lejava/articles/equality.html
+ * for further details), consider this class:
+ * <pre>
+ * {@code @EqualsAndHashCode}
+ * class IntPair {
+ *     int x, y
+ * }
+ * </pre>
+ * The generated <code>equals</code> and <code>canEqual</code> methods will be something like below:
+ * <pre>
+ * public boolean equals(java.lang.Object other)
+ *     if (other == null) return false
+ *     if (this.is(other)) return true
+ *     if (!(other instanceof IntPair)) return false
+ *     if (!other.canEqual(this)) return false
+ *     if (x != other.x) return false
+ *     if (y != other.y) return false
+ *     return true
+ * }
+ *
+ * public boolean canEqual(java.lang.Object other) {
+ *     return other instanceof IntPair
+ * }
+ * </pre>
+ * If no further options are specified, this is the default style for {@code @Canonical} and
+ * {@code @EqualsAndHashCode} annotated classes. The advantage of this style is that it allows inheritance
+ * to be used in limited cases where its purpose is for overriding implementation details rather than
+ * creating a derived type with different behavior. This is useful when using JPA Proxies for example or
+ * as shown in the following examples:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ * {@code @Canonical} class IntPair { int x, y }
+ * def p1 = new IntPair(1, 2)
+ *
+ * // overridden getter but deemed an IntPair as far as domain is concerned
+ * def p2 = new IntPair(1, 1) { int getY() { 2 } }
+ *
+ * // additional helper method added through inheritance but
+ * // deemed an IntPair as far as our domain is concerned
+ * {@code @InheritConstructors} class IntPairWithSum extends IntPair {
+ *     def sum() { x + y }
+ * }
+ *
+ * def p3 = new IntPairWithSum(1, 2)
+ *
+ * assert p1 == p2 && p2 == p1
+ * assert p1 == p3 && p3 == p1
+ * assert p3 == p2 && p2 == p3
+ * </pre>
+ * Note that if you create any domain classes which don't have exactly the
+ * same contract as <code>IntPair</code> then you should provide an appropriate
+ * <code>equals</code> and <code>canEqual</code> method. The easiest way to
+ * achieve this would be to use the {@code @Canonical} or
+ * {@code @EqualsAndHashCode} annotations as shown below:
+ * <pre>
+ * {@code @EqualsAndHashCode}
+ * {@code @TupleConstructor(includeSuperProperties=true)}
+ * class IntTriple extends IntPair { int z }
+ * def t1 = new IntTriple(1, 2, 3)
+ * assert p1 != t1 && p2 != t1 && t1 != p3
+ * </pre>
+ *
+ * The alternative supported style regards any kind of inheritance as creation of
+ * a new type and is illustrated in the following example:
+ * <pre>
+ * {@code @EqualsAndHashCode(useCanEqual=false)}
+ * class IntPair {
+ *     int x, y
+ * }
+ * </pre>
+ * The generated equals method will be something like below:
+ * <pre>
+ * public boolean equals(java.lang.Object other)
+ *     if (other == null) return false
+ *     if (this.is(other)) return true
+ *     if (IntPair != other.getClass()) return false
+ *     if (x != other.x) return false
+ *     if (y != other.y) return false
+ *     return true
+ * }
+ * </pre>
+ * This style is appropriate for final classes (where inheritance is not
+ * allowed) which have only <code>java.lang.Object</code> as a super class.
+ * Most {@code @Immutable} classes fall in to this category. For such classes,
+ * there is no need to introduce the <code>canEqual()</code> method.
+ * <p>
+ * Note that if you explicitly set <code>useCanEqual=false</code> for child nodes
+ * in a class hierarchy but have it <code>true</code> for parent nodes and you
+ * also have <code>callSuper=true</code> in the child, then your generated
+ * equals methods will not strictly follow the equals contract.
+ * <p>
+ * Note that when used in the recommended fashion, the two implementations supported adhere
+ * to the equals contract. You can provide your own equivalence relationships if you need,
+ * e.g. for comparing instances of the <code>IntPair</code> and <code>IntTriple</code> classes
+ * discussed earlier, you could provide the following method in <code>IntPair</code>:
+ * <pre>
+ * boolean hasEqualXY(other) { other.x == getX() && other.y == getY() }
+ * </pre>
+ * Then for the objects defined earlier, the following would be true:
+ * <pre>
+ * assert p1.hasEqualXY(t1) && t1.hasEqualXY(p1)
+ * assert p2.hasEqualXY(t1) && t1.hasEqualXY(p2)
+ * assert p3.hasEqualXY(t1) && t1.hasEqualXY(p3)
+ * </pre>
+ * There is also support for including or excluding fields/properties by name when constructing
+ * the equals and hashCode methods as shown here:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ * {@code @EqualsAndHashCode}(excludes="z")
+ * {@code @TupleConstructor}
+ * public class Point2D {
+ *     int x, y, z
+ * }
+ *
+ * assert  new Point2D(1, 1, 1).equals(new Point2D(1, 1, 2))
+ * assert !new Point2D(1, 1, 1).equals(new Point2D(2, 1, 1))
+ *
+ * {@code @EqualsAndHashCode}(excludes=["y", "z"])
+ * {@code @TupleConstructor}
+ * public class Point1D {
+ *     int x, y, z
+ * }
+ *
+ * assert  new Point1D(1, 1, 1).equals(new Point1D(1, 1, 2))
+ * assert  new Point1D(1, 1, 1).equals(new Point1D(1, 2, 1))
+ * assert !new Point1D(1, 1, 1).equals(new Point1D(2, 1, 1))
+ * </pre>
+ * <b>Note:</b> {@code @EqualsAndHashCode} is a transform to help reduce boilerplate
+ * in the common cases. It provides a useful implementation of {@code equals()}
+ * and {@code hashCode()} but not necessarily the most appropriate or
+ * efficient one for every use case. You should write custom versions if your
+ * scenario demands it. In particular, if you have
+ * mutually-referential classes, the implementations provided may not be suitable
+ * and may recurse infinitely (leading to a {@code StackOverflowError}). In such cases,
+ * you need to remove the infinite loop from your data structures or write your own custom methods.
+ * If your data structures are self-referencing, the code generated by this transform will try to avoid
+ * infinite recursion but the algorithm used may not suit your scenario, so use with caution if
+ * you have such structures.
+ * A future version of this transform may better handle some additional recursive scenarios.
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.EqualsAndHashCode
+ *
+ * &#64;EqualsAndHashCode(includeFields=true)
+ * class User {
+ *     String name
+ *     boolean active
+ *     List likes
+ *     private int age = 37
+ * }
+ *
+ * def user = new User(name: 'mrhaki', active: false, likes: ['Groovy', 'Java'])
+ * def mrhaki = new User(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ * def hubert = new User(name: 'Hubert Klein Ikkink', likes: ['Groovy', 'Java'])
+ *
+ * assert user == mrhaki
+ * assert mrhaki != hubert
+ *
+ * Set users = new HashSet()
+ * users.add user
+ * users.add mrhaki
+ * users.add hubert
+ * assert users.size() == 2
+ * </pre>
+ *
+ * @see org.codehaus.groovy.util.HashCodeHelper
+ * @author Paul King
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.EqualsAndHashCodeASTTransformation")
+public @interface EqualsAndHashCode {
+    /**
+     * List of field and/or property names to exclude from the equals and hashCode calculations.
+     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the equals and hashCode calculations.
+     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields
+     * and/or properties are included if 'includes' remains undefined and 'excludes' is explicitly or
+     * implicitly an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Whether to cache hashCode calculations. You should only set this to true if
+     * you know the object is immutable (or technically mutable but never changed).
+     */
+    boolean cache() default false;
+
+    /**
+     * Whether to include super in equals and hashCode calculations.
+     */
+    boolean callSuper() default false;
+
+    /**
+     * Include fields as well as properties in equals and hashCode calculations.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Generate a canEqual method to be used by equals.
+     */
+    boolean useCanEqual() default true;
+
+    /**
+     * Whether to include all fields and/or properties in equals and hashCode calculations, including those
+     * with names that are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ExternalizeMethods.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ExternalizeMethods.java b/src/main/groovy/groovy/transform/ExternalizeMethods.java
new file mode 100644
index 0000000..5ef37a0
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ExternalizeMethods.java
@@ -0,0 +1,89 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of {@code Externalizable} classes.
+ * The {@code @ExternalizeMethods} annotation instructs the compiler to execute an
+ * AST transformation which adds {@code writeExternal()} and {@code readExternal()} methods
+ * to a class and adds {@code Externalizable} to the interfaces which the class implements.
+ * The {@code writeExternal()} method writes each property (and optionally field) of the class
+ * while the {@code readExternal()} method will read each one back in the same order.
+ * Properties or fields marked as {@code transient} are ignored.
+ * This annotation is typically used in conjunction with the {@code @ExternalizeVerifier} annotation but
+ * most usually not directly but rather via {@code @AutoExternalizable} which is a shortcut for both annotations.
+ * <p>
+ * Example usage:
+ * <pre>
+ * import groovy.transform.*
+ * {@code @ExternalizeMethods}
+ * class Person {
+ *   String first, last
+ *   List favItems
+ *   Date since
+ * }
+ * </pre>
+ * Which will create a class of the following form:
+ * <pre>
+ * class Person implements Externalizable {
+ *   ...
+ *   public void writeExternal(ObjectOutput out) throws IOException {
+ *     out.writeObject(first)
+ *     out.writeObject(last)
+ *     out.writeObject(favItems)
+ *     out.writeObject(since)
+ *   }
+ *
+ *   public void readExternal(ObjectInput oin) {
+ *     first = (String) oin.readObject()
+ *     last = (String) oin.readObject()
+ *     favItems = (List) oin.readObject()
+ *     since = (Date) oin.readObject()
+ *   }
+ *   ...
+ * }
+ * </pre>
+ *
+ * @author Paul King
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ExternalizeMethodsASTTransformation")
+public @interface ExternalizeMethods {
+    /**
+     * Comma separated list of property names to exclude from externalizing.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * Include fields as well as properties when externalizing.
+     */
+    boolean includeFields() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ExternalizeVerifier.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ExternalizeVerifier.java b/src/main/groovy/groovy/transform/ExternalizeVerifier.java
new file mode 100644
index 0000000..185c935
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ExternalizeVerifier.java
@@ -0,0 +1,62 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of {@code Externalizable} classes.
+ * The {@code @ExternalizeVerifier} annotation instructs the compiler to check
+ * that a class has {@code writeExternal()} and {@code readExternal()} methods,
+ * implements the {@code Externalizable} interface and that each property (and optionally field) is not final
+ * and, optionally for non-primitives, has a type which is either {@code Externalizable} or {@code Serializable}.
+ * Properties or fields marked as {@code transient} are ignored.
+ * This annotation is typically used in conjunction with the {@code @ExternalizeMethods} annotation but
+ * most usually not directly but rather via {@code @AutoExternalizable} which is a shortcut for both annotations.
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ExternalizeVerifierASTTransformation")
+public @interface ExternalizeVerifier {
+    /**
+     * Comma separated list of property names to exclude from externalization verification.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * Include fields as well as properties when verifying externalization properties.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Turns on strict type checking for property (or field) types. In strict mode, such types must also implement Serializable or Externalizable.
+     * If your properties have interface types that don't implement Serializable but all the concrete implementations do, or the
+     * type is of a non-Serializable class but the property will be null at runtime, then your instances will still be serializable
+     * but you can't turn on strict checking.
+     */
+    boolean checkPropertyTypes() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Field.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Field.java b/src/main/groovy/groovy/transform/Field.java
new file mode 100644
index 0000000..bcc64e8
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Field.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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Variable annotation used for changing the scope of a variable within a script from
+ * being within the run method of the script to being at the class level for the script.
+ * <p>
+ * The annotated variable will become a private field of the script class.
+ * The type of the field will be the same as the type of the variable. Example usage:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.Field
+ * {@code @Field} List awe = [1, 2, 3]
+ * def awesum() { awe.sum() }
+ * assert awesum() == 6
+ * </pre>
+ * In this example, without the annotation, variable <code>awe</code> would be
+ * a local script variable (technically speaking it will be a local variable within
+ * the <code>run</code> method of the script class). Such a local variable would
+ * not be visible inside the <code>awesum</code> method. With the annotation,
+ * <code>awe</code> becomes a private List field in the script class and is
+ * visible within the <code>awesum</code> method.
+ *
+ * @author Paul King
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.LOCAL_VARIABLE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.FieldASTTransformation")
+public @interface Field {
+}


[03/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/GroovyCollections.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/GroovyCollections.java b/src/main/groovy/util/GroovyCollections.java
deleted file mode 100644
index dff062d..0000000
--- a/src/main/groovy/util/GroovyCollections.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- *  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 groovy.util;
-
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A Collections utility class
- *
- * @author Paul King
- * @author Jim White
- */
-public class GroovyCollections {
-    /**
-     * Finds all combinations of items from the given collections.
-     *
-     * @param collections the given collections
-     * @return a List of the combinations found
-     * @see #combinations(Collection)
-     */
-    public static List combinations(Object[] collections) {
-        return combinations((Iterable)Arrays.asList(collections));
-    }
-
-    /**
-     * Finds all non-null subsequences of a list.
-     * E.g. <code>subsequences([1, 2, 3])</code> would be:
-     * [[1, 2, 3], [1, 3], [2, 3], [1, 2], [1], [2], [3]]
-     *
-     * @param items the List of items
-     * @return the subsequences from items
-     */
-    public static <T> Set<List<T>> subsequences(List<T> items) {
-        // items.inject([]){ ss, h -> ss.collect { it + [h] }  + ss + [[h]] }
-        Set<List<T>> ans = new HashSet<List<T>>();
-        for (T h : items) {
-            Set<List<T>> next = new HashSet<List<T>>();
-            for (List<T> it : ans) {
-                List<T> sublist = new ArrayList<T>(it);
-                sublist.add(h);
-                next.add(sublist);
-            }
-            next.addAll(ans);
-            List<T> hlist = new ArrayList<T>();
-            hlist.add(h);
-            next.add(hlist);
-            ans = next;
-        }
-        return ans;
-    }
-
-    /**
-     * @param collections the given collections
-     * @deprecated use combinations(Iterable)
-     */
-    @Deprecated
-    public static List combinations(Collection collections) {
-        return combinations((Iterable)collections);
-    }
-
-    /**
-     * Finds all combinations of items from the given Iterable aggregate of collections.
-     * So, <code>combinations([[true, false], [true, false]])</code>
-     * is <code>[[true, true], [false, true], [true, false], [false, false]]</code>
-     * and <code>combinations([['a', 'b'],[1, 2, 3]])</code>
-     * is <code>[['a', 1], ['b', 1], ['a', 2], ['b', 2], ['a', 3], ['b', 3]]</code>.
-     * If a non-collection item is given, it is treated as a singleton collection,
-     * i.e. <code>combinations([[1, 2], 'x'])</code> is <code>[[1, 'x'], [2, 'x']]</code>.
-     *
-     * @param collections the Iterable of given collections
-     * @return a List of the combinations found
-     * @since 2.2.0
-     */
-    public static List combinations(Iterable collections) {
-        List collectedCombos = new ArrayList();
-        for (Object collection : collections) {
-            Iterable items = DefaultTypeTransformation.asCollection(collection);
-            if (collectedCombos.isEmpty()) {
-                for (Object item : items) {
-                    List l = new ArrayList();
-                    l.add(item);
-                    collectedCombos.add(l);
-                }
-            } else {
-                List savedCombos = new ArrayList(collectedCombos);
-                List newCombos = new ArrayList();
-                for (Object value : items) {
-                    for (Object savedCombo : savedCombos) {
-                        List oldList = new ArrayList((List) savedCombo);
-                        oldList.add(value);
-                        newCombos.add(oldList);
-                    }
-                }
-                collectedCombos = newCombos;
-            }
-        }
-        return collectedCombos;
-    }
-
-    public static <T> List<List<T>> inits(Iterable<T> collections) {
-        List<T> copy = DefaultGroovyMethods.toList(collections);
-        List<List<T>> result = new ArrayList<List<T>>();
-        for (int i = copy.size(); i >= 0; i--) {
-            List<T> next = copy.subList(0, i);
-            result.add(next);
-        }
-        return result;
-    }
-
-    public static <T> List<List<T>> tails(Iterable<T> collections) {
-        List<T> copy = DefaultGroovyMethods.toList(collections);
-        List<List<T>> result = new ArrayList<List<T>>();
-        for (int i = 0; i <= copy.size(); i++) {
-            List<T> next = copy.subList(i, copy.size());
-            result.add(next);
-        }
-        return result;
-    }
-
-    /**
-     * Transposes an array of lists.
-     *
-     * @param lists the given lists
-     * @return a List of the transposed lists
-     * @see #transpose(List)
-     */
-    public static List transpose(Object[] lists) {
-        return transpose(Arrays.asList(lists));
-    }
-
-    /**
-     * Transposes the given lists.
-     * So, <code>transpose([['a', 'b'], [1, 2]])</code>
-     * is <code>[['a', 1], ['b', 2]]</code> and
-     * <code>transpose([['a', 'b', 'c']])</code>
-     * is <code>[['a'], ['b'], ['c']]</code>.
-     *
-     * @param lists the given lists
-     * @return a List of the transposed lists
-     */
-    public static List transpose(List lists) {
-        List result = new ArrayList();
-        if (lists.isEmpty()) return result;
-        int minSize = Integer.MAX_VALUE;
-        for (Object listLike : lists) {
-            List list = (List) DefaultTypeTransformation.castToType(listLike, List.class);
-            if (list.size() < minSize) minSize = list.size();
-        }
-        if (minSize == 0) return result;
-        for (int i = 0; i < minSize; i++) {
-            result.add(new ArrayList());
-        }
-        for (Object listLike : lists) {
-            List list = (List) DefaultTypeTransformation.castToType(listLike, List.class);
-            for (int i = 0; i < minSize; i++) {
-                List resultList = (List) result.get(i);
-                resultList.add(list.get(i));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Selects the minimum value found in an array of items, so
-     * min([2, 4, 6] as Object[]) == 2.
-     *
-     * @param items an array of items
-     * @return the minimum value
-     */
-    public static <T> T min(T[] items) {
-        return min((Iterable<T>)Arrays.asList(items));
-    }
-
-    /**
-     * @deprecated use min(Iterable)
-     */
-    @Deprecated
-    public static <T> T min(Collection<T> items) {
-        return min((Iterable<T>)items);
-    }
-
-    /**
-     * Selects the minimum value found in an Iterable of items.
-     *
-     * @param items an Iterable
-     * @return the minimum value
-     * @since 2.2.0
-     */
-    public static <T> T min(Iterable<T> items) {
-        T answer = null;
-        for (T value : items) {
-            if (value != null) {
-                if (answer == null || ScriptBytecodeAdapter.compareLessThan(value, answer)) {
-                    answer = value;
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Selects the maximum value found in an array of items, so
-     * min([2, 4, 6] as Object[]) == 6.
-     *
-     * @param items an array of items
-     * @return the maximum value
-     */
-    public static <T> T max(T[] items) {
-        return max((Iterable<T>)Arrays.asList(items));
-    }
-
-    /**
-     * @deprecated use max(Iterable)
-     */
-    @Deprecated
-    public static <T> T max(Collection<T> items) {
-        return max((Iterable<T>)items);
-    }
-
-    /**
-     * Selects the maximum value found in an Iterable.
-     *
-     * @param items a Collection
-     * @return the maximum value
-     * @since 2.2.0
-     */
-    public static <T> T max(Iterable<T> items) {
-        T answer = null;
-        for (T value : items) {
-            if (value != null) {
-                if (answer == null || ScriptBytecodeAdapter.compareGreaterThan(value, answer)) {
-                    answer = value;
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Sums all the items from an array of items.
-     *
-     * @param items an array of items
-     * @return the sum of the items
-     */
-    public static Object sum(Object[] items) {
-        return sum((Iterable)Arrays.asList(items));
-    }
-
-    /**
-     * @deprecated use sum(Iterable)
-     */
-    @Deprecated
-    public static Object sum(Collection items) {
-        return sum((Iterable)items);
-    }
-
-    /**
-     * Sums all the given items.
-     *
-     * @param items an Iterable of items
-     * @return the sum of the item
-     * @since 2.2.0
-     */
-    public static Object sum(Iterable items) {
-        return DefaultGroovyMethods.sum(items);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/GroovyScriptEngine.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/GroovyScriptEngine.java b/src/main/groovy/util/GroovyScriptEngine.java
deleted file mode 100644
index 92e2486..0000000
--- a/src/main/groovy/util/GroovyScriptEngine.java
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyCodeSource;
-import groovy.lang.GroovyResourceLoader;
-import groovy.lang.Script;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.InnerClassNode;
-import org.codehaus.groovy.classgen.GeneratorContext;
-import org.codehaus.groovy.control.ClassNodeResolver;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.customizers.CompilationCustomizer;
-import org.codehaus.groovy.runtime.IOGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.tools.gse.DependencyTracker;
-import org.codehaus.groovy.tools.gse.StringSetMap;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.PrivilegedAction;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Specific script engine able to reload modified scripts as well as dealing properly
- * with dependent scripts.
- *
- * @author sam
- * @author Marc Palmer
- * @author Guillaume Laforge
- * @author Jochen Theodorou
- * @author Mattias Reichel
- */
-public class GroovyScriptEngine implements ResourceConnector {
-    private static final ClassLoader CL_STUB = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
-        public ClassLoader run() {
-            return new ClassLoader() {};
-        }
-    });
-
-    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
-
-    private static class LocalData {
-        CompilationUnit cu;
-        final StringSetMap dependencyCache = new StringSetMap();
-        final Map<String, String> precompiledEntries = new HashMap<String, String>();
-    }
-
-    private static WeakReference<ThreadLocal<LocalData>> localData = new WeakReference<ThreadLocal<LocalData>>(null);
-
-    private static synchronized ThreadLocal<LocalData> getLocalData() {
-        ThreadLocal<LocalData> local = localData.get();
-        if (local != null) return local;
-        local = new ThreadLocal<LocalData>();
-        localData = new WeakReference<ThreadLocal<LocalData>>(local);
-        return local;
-    }
-
-    private final URL[] roots;
-    private final ResourceConnector rc;
-    private final ClassLoader parentLoader;
-    private GroovyClassLoader groovyLoader;
-    private final Map<String, ScriptCacheEntry> scriptCache = new ConcurrentHashMap<String, ScriptCacheEntry>();
-    private CompilerConfiguration config;
-
-    {
-        config = new CompilerConfiguration(CompilerConfiguration.DEFAULT);
-        config.setSourceEncoding(CompilerConfiguration.DEFAULT_SOURCE_ENCODING);
-    }
-
-
-    //TODO: more finals?
-
-    private static class ScriptCacheEntry {
-        private final Class scriptClass;
-        private final long lastModified, lastCheck;
-        private final Set<String> dependencies;
-        private final boolean sourceNewer;
-
-        public ScriptCacheEntry(Class clazz, long modified, long lastCheck, Set<String> depend, boolean sourceNewer) {
-            this.scriptClass = clazz;
-            this.lastModified = modified;
-            this.lastCheck = lastCheck;
-            this.dependencies = depend;
-            this.sourceNewer = sourceNewer;
-        }
-
-        public ScriptCacheEntry(ScriptCacheEntry old, long lastCheck, boolean sourceNewer) {
-            this(old.scriptClass, old.lastModified, lastCheck, old.dependencies, sourceNewer);
-        }
-    }
-
-    private class ScriptClassLoader extends GroovyClassLoader {
-
-
-        public ScriptClassLoader(GroovyClassLoader loader) {
-            super(loader);
-        }
-
-        public ScriptClassLoader(ClassLoader loader, CompilerConfiguration config) {
-            super(loader, config, false);
-            setResLoader();
-        }
-
-        private void setResLoader() {
-            final GroovyResourceLoader rl = getResourceLoader();
-            setResourceLoader(new GroovyResourceLoader() {
-                public URL loadGroovySource(String className) throws MalformedURLException {
-                    String filename;
-                    for (String extension : getConfig().getScriptExtensions()) {
-                        filename = className.replace('.', File.separatorChar) + "." + extension;
-                        try {
-                            URLConnection dependentScriptConn = rc.getResourceConnection(filename);
-                            return dependentScriptConn.getURL();
-                        } catch (ResourceException e) {
-                            //TODO: maybe do something here?
-                        }
-                    }
-                    return rl.loadGroovySource(className);
-                }
-            });
-        }
-
-        @Override
-        protected CompilationUnit createCompilationUnit(CompilerConfiguration configuration, CodeSource source) {
-            CompilationUnit cu = super.createCompilationUnit(configuration, source);
-            LocalData local = getLocalData().get();
-            local.cu = cu;
-            final StringSetMap cache = local.dependencyCache;
-            final Map<String, String> precompiledEntries = local.precompiledEntries;
-
-            // "." is used to transfer compilation dependencies, which will be
-            // recollected later during compilation
-            for (String depSourcePath : cache.get(".")) {
-                try {
-                    cache.get(depSourcePath);
-                    cu.addSource(getResourceConnection(depSourcePath).getURL());
-                } catch (ResourceException e) {
-                    /* ignore */
-                }
-            }
-
-            // remove all old entries including the "." entry
-            cache.clear();
-
-            cu.addPhaseOperation(new CompilationUnit.PrimaryClassNodeOperation() {
-                @Override
-                public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode)
-                        throws CompilationFailedException {
-                    // GROOVY-4013: If it is an inner class, tracking its dependencies doesn't really
-                    // serve any purpose and also interferes with the caching done to track dependencies
-                    if (classNode instanceof InnerClassNode) return;
-                    DependencyTracker dt = new DependencyTracker(source, cache, precompiledEntries);
-                    dt.visitClass(classNode);
-                }
-            }, Phases.CLASS_GENERATION);
-
-            cu.setClassNodeResolver(new ClassNodeResolver() {
-                @Override
-                public LookupResult findClassNode(String origName, CompilationUnit compilationUnit) {
-                    CompilerConfiguration cc = compilationUnit.getConfiguration();
-                    String name = origName.replace('.', '/');
-                    for (String ext : cc.getScriptExtensions()) {
-                        try {
-                            String finalName = name + "." + ext;
-                            URLConnection conn = rc.getResourceConnection(finalName);
-                            URL url = conn.getURL();
-                            String path = url.toExternalForm();
-                            ScriptCacheEntry entry = scriptCache.get(path);
-                            Class clazz = null;
-                            if (entry != null) clazz = entry.scriptClass;
-                            if (GroovyScriptEngine.this.isSourceNewer(entry)) {
-                                try {
-                                    SourceUnit su = compilationUnit.addSource(url);
-                                    return new LookupResult(su, null);
-                                } finally {
-                                    forceClose(conn);
-                                }
-                            } else {
-                                precompiledEntries.put(origName, path);
-                            }
-                            if (clazz != null) {
-                                ClassNode cn = new ClassNode(clazz);
-                                return new LookupResult(null, cn);
-                            }
-                        } catch (ResourceException re) {
-                            // skip
-                        }
-                    }
-                    return super.findClassNode(origName, compilationUnit);
-                }
-            });
-
-            return cu;
-        }
-
-        @Override
-        public Class parseClass(GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException {
-            synchronized (sourceCache) {
-                return doParseClass(codeSource);
-            }
-        }
-
-        private Class<?> doParseClass(GroovyCodeSource codeSource) {
-            // local is kept as hard reference to avoid garbage collection
-            ThreadLocal<LocalData> localTh = getLocalData();
-            LocalData localData = new LocalData();
-            localTh.set(localData);
-            StringSetMap cache = localData.dependencyCache;
-            Class<?> answer = null;
-            try {
-                updateLocalDependencyCache(codeSource, localData);
-                answer = super.parseClass(codeSource, false);
-                updateScriptCache(localData);
-            } finally {
-                cache.clear();
-                localTh.remove();
-            }
-            return answer;
-        }
-
-        private void updateLocalDependencyCache(GroovyCodeSource codeSource, LocalData localData) {
-            // we put the old dependencies into local cache so createCompilationUnit
-            // can pick it up. We put that entry under the name "."
-            ScriptCacheEntry origEntry = scriptCache.get(codeSource.getName());
-            Set<String> origDep = null;
-            if (origEntry != null) origDep = origEntry.dependencies;
-            if (origDep != null) {
-                Set<String> newDep = new HashSet<String>(origDep.size());
-                for (String depName : origDep) {
-                    ScriptCacheEntry dep = scriptCache.get(depName);
-                    try {
-                        if (origEntry == dep || GroovyScriptEngine.this.isSourceNewer(dep)) {
-                            newDep.add(depName);
-                        }
-                    } catch (ResourceException re) {
-
-                    }
-                }
-                StringSetMap cache = localData.dependencyCache;
-                cache.put(".", newDep);
-            }
-        }
-
-        private void updateScriptCache(LocalData localData) {
-            StringSetMap cache = localData.dependencyCache;
-            cache.makeTransitiveHull();
-            long time = getCurrentTime();
-            Set<String> entryNames = new HashSet<String>();
-            for (Map.Entry<String, Set<String>> entry : cache.entrySet()) {
-                String className = entry.getKey();
-                Class clazz = getClassCacheEntry(className);
-                if (clazz == null) continue;
-
-                String entryName = getPath(clazz, localData.precompiledEntries);
-                if (entryNames.contains(entryName)) continue;
-                entryNames.add(entryName);
-                Set<String> value = convertToPaths(entry.getValue(), localData.precompiledEntries);
-                long lastModified;
-                try {
-                    lastModified = getLastModified(entryName);
-                } catch (ResourceException e) {
-                    lastModified = time;
-                }
-                ScriptCacheEntry cacheEntry = new ScriptCacheEntry(clazz, lastModified, time, value, false);
-                scriptCache.put(entryName, cacheEntry);
-            }
-        }
-
-        private String getPath(Class clazz, Map<String, String> precompiledEntries) {
-            CompilationUnit cu = getLocalData().get().cu;
-            String name = clazz.getName();
-            ClassNode classNode = cu.getClassNode(name);
-            if (classNode == null) {
-                // this is a precompiled class!
-                String path = precompiledEntries.get(name);
-                if (path == null) throw new GroovyBugError("Precompiled class " + name + " should be available in precompiled entries map, but was not.");
-                return path;
-            } else {
-                return classNode.getModule().getContext().getName();
-            }
-        }
-
-        private Set<String> convertToPaths(Set<String> orig, Map<String, String> precompiledEntries) {
-            Set<String> ret = new HashSet<String>();
-            for (String className : orig) {
-                Class clazz = getClassCacheEntry(className);
-                if (clazz == null) continue;
-                ret.add(getPath(clazz, precompiledEntries));
-            }
-            return ret;
-        }
-    }
-
-    /**
-     * Simple testing harness for the GSE. Enter script roots as arguments and
-     * then input script names to run them.
-     *
-     * @param urls an array of URLs
-     * @throws Exception if something goes wrong
-     */
-    public static void main(String[] urls) throws Exception {
-        GroovyScriptEngine gse = new GroovyScriptEngine(urls);
-        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-        String line;
-        while (true) {
-            System.out.print("groovy> ");
-            if ((line = br.readLine()) == null || line.equals("quit")) {
-                break;
-            }
-            try {
-                System.out.println(gse.run(line, new Binding()));
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    /**
-     * Initialize a new GroovyClassLoader with a default or
-     * constructor-supplied parentClassLoader.
-     *
-     * @return the parent classloader used to load scripts
-     */
-    private GroovyClassLoader initGroovyLoader() {
-        GroovyClassLoader groovyClassLoader =
-                AccessController.doPrivileged(new PrivilegedAction<ScriptClassLoader>() {
-                    public ScriptClassLoader run() {
-                        if (parentLoader instanceof GroovyClassLoader) {
-                            return new ScriptClassLoader((GroovyClassLoader) parentLoader);
-                        } else {
-                            return new ScriptClassLoader(parentLoader, config);
-                        }
-                    }
-                });
-        for (URL root : roots) groovyClassLoader.addURL(root);
-        return groovyClassLoader;
-    }
-
-    /**
-     * Get a resource connection as a <code>URLConnection</code> to retrieve a script
-     * from the <code>ResourceConnector</code>.
-     *
-     * @param resourceName name of the resource to be retrieved
-     * @return a URLConnection to the resource
-     * @throws ResourceException
-     */
-    public URLConnection getResourceConnection(String resourceName) throws ResourceException {
-        // Get the URLConnection
-        URLConnection groovyScriptConn = null;
-
-        ResourceException se = null;
-        for (URL root : roots) {
-            URL scriptURL = null;
-            try {
-                scriptURL = new URL(root, resourceName);
-                groovyScriptConn = openConnection(scriptURL);
-
-                break; // Now this is a bit unusual
-            } catch (MalformedURLException e) {
-                String message = "Malformed URL: " + root + ", " + resourceName;
-                if (se == null) {
-                    se = new ResourceException(message);
-                } else {
-                    se = new ResourceException(message, se);
-                }
-            } catch (IOException e1) {
-                String message = "Cannot open URL: " + root + resourceName;
-                groovyScriptConn = null;
-                if (se == null) {
-                    se = new ResourceException(message);
-                } else {
-                    se = new ResourceException(message, se);
-                }
-            }
-        }
-
-        if (se == null) se = new ResourceException("No resource for " + resourceName + " was found");
-
-        // If we didn't find anything, report on all the exceptions that occurred.
-        if (groovyScriptConn == null) throw se;
-        return groovyScriptConn;
-    }
-
-    private static URLConnection openConnection(URL scriptURL) throws IOException {
-        URLConnection urlConnection = scriptURL.openConnection();
-        verifyInputStream(urlConnection);
-
-        return scriptURL.openConnection();
-    }
-
-    /**
-     * This method closes a {@link URLConnection} by getting its {@link InputStream} and calling the
-     * {@link InputStream#close()} method on it. The {@link URLConnection} doesn't have a close() method
-     * and relies on garbage collection to close the underlying connection to the file.
-     * Relying on garbage collection could lead to the application exhausting the number of files the
-     * user is allowed to have open at any one point in time and cause the application to crash
-     * ({@link java.io.FileNotFoundException} (Too many open files)).
-     * Hence the need for this method to explicitly close the underlying connection to the file.
-     *
-     * @param urlConnection the {@link URLConnection} to be "closed" to close the underlying file descriptors.
-     */
-    private static void forceClose(URLConnection urlConnection) {
-        if (urlConnection != null) {
-            // We need to get the input stream and close it to force the open
-            // file descriptor to be released. Otherwise, we will reach the limit
-            // for number of files open at one time.
-
-            try {
-                verifyInputStream(urlConnection);
-            } catch (Exception e) {
-                // Do nothing: We were not going to use it anyway.
-            }
-        }
-    }
-
-    private static void verifyInputStream(URLConnection urlConnection) throws IOException {
-        InputStream in = null;
-        try {
-            in = urlConnection.getInputStream();
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException ignore) {
-                }
-            }
-        }
-    }
-
-    /**
-     * The groovy script engine will run groovy scripts and reload them and
-     * their dependencies when they are modified. This is useful for embedding
-     * groovy in other containers like games and application servers.
-     *
-     * @param roots This an array of URLs where Groovy scripts will be stored. They should
-     *              be laid out using their package structure like Java classes
-     */
-    private GroovyScriptEngine(URL[] roots, ClassLoader parent, ResourceConnector rc) {
-        if (roots == null) roots = EMPTY_URL_ARRAY;
-        this.roots = roots;
-        if (rc == null) rc = this;
-        this.rc = rc;
-        if (parent == CL_STUB) parent = this.getClass().getClassLoader();
-        this.parentLoader = parent;
-        this.groovyLoader = initGroovyLoader();
-    }
-
-    public GroovyScriptEngine(URL[] roots) {
-        this(roots, CL_STUB, null);
-    }
-
-    public GroovyScriptEngine(URL[] roots, ClassLoader parentClassLoader) {
-        this(roots, parentClassLoader, null);
-    }
-
-    public GroovyScriptEngine(String[] urls) throws IOException {
-        this(createRoots(urls), CL_STUB, null);
-    }
-
-    private static URL[] createRoots(String[] urls) throws MalformedURLException {
-        if (urls == null) return null;
-        URL[] roots = new URL[urls.length];
-        for (int i = 0; i < roots.length; i++) {
-            if (urls[i].contains("://")) {
-                roots[i] = new URL(urls[i]);
-            } else {
-                roots[i] = new File(urls[i]).toURI().toURL();
-            }
-        }
-        return roots;
-    }
-
-    public GroovyScriptEngine(String[] urls, ClassLoader parentClassLoader) throws IOException {
-        this(createRoots(urls), parentClassLoader, null);
-    }
-
-    public GroovyScriptEngine(String url) throws IOException {
-        this(new String[]{url});
-    }
-
-    public GroovyScriptEngine(String url, ClassLoader parentClassLoader) throws IOException {
-        this(new String[]{url}, parentClassLoader);
-    }
-
-    public GroovyScriptEngine(ResourceConnector rc) {
-        this(null, CL_STUB, rc);
-    }
-
-    public GroovyScriptEngine(ResourceConnector rc, ClassLoader parentClassLoader) {
-        this(null, parentClassLoader, rc);
-    }
-
-    /**
-     * Get the <code>ClassLoader</code> that will serve as the parent ClassLoader of the
-     * {@link GroovyClassLoader} in which scripts will be executed. By default, this is the
-     * ClassLoader that loaded the <code>GroovyScriptEngine</code> class.
-     *
-     * @return the parent classloader used to load scripts
-     */
-    public ClassLoader getParentClassLoader() {
-        return parentLoader;
-    }
-
-    /**
-     * Get the class of the scriptName in question, so that you can instantiate
-     * Groovy objects with caching and reloading.
-     *
-     * @param scriptName resource name pointing to the script
-     * @return the loaded scriptName as a compiled class
-     * @throws ResourceException if there is a problem accessing the script
-     * @throws ScriptException   if there is a problem parsing the script
-     */
-    public Class loadScriptByName(String scriptName) throws ResourceException, ScriptException {
-        URLConnection conn = rc.getResourceConnection(scriptName);
-        String path = conn.getURL().toExternalForm();
-        ScriptCacheEntry entry = scriptCache.get(path);
-        Class clazz = null;
-        if (entry != null) clazz = entry.scriptClass;
-        try {
-            if (isSourceNewer(entry)) {
-                try {
-                    String encoding = conn.getContentEncoding() != null ? conn.getContentEncoding() : config.getSourceEncoding();
-                    String content = IOGroovyMethods.getText(conn.getInputStream(), encoding);
-                    clazz = groovyLoader.parseClass(content, path);
-                } catch (IOException e) {
-                    throw new ResourceException(e);
-                }
-            }
-        } finally {
-            forceClose(conn);
-        }
-        return clazz;
-    }
-
-    /**
-     * Run a script identified by name with a single argument.
-     *
-     * @param scriptName name of the script to run
-     * @param argument   a single argument passed as a variable named <code>arg</code> in the binding
-     * @return a <code>toString()</code> representation of the result of the execution of the script
-     * @throws ResourceException if there is a problem accessing the script
-     * @throws ScriptException   if there is a problem parsing the script
-     */
-    public String run(String scriptName, String argument) throws ResourceException, ScriptException {
-        Binding binding = new Binding();
-        binding.setVariable("arg", argument);
-        Object result = run(scriptName, binding);
-        return result == null ? "" : result.toString();
-    }
-
-    /**
-     * Run a script identified by name with a given binding.
-     *
-     * @param scriptName name of the script to run
-     * @param binding    the binding to pass to the script
-     * @return an object
-     * @throws ResourceException if there is a problem accessing the script
-     * @throws ScriptException   if there is a problem parsing the script
-     */
-    public Object run(String scriptName, Binding binding) throws ResourceException, ScriptException {
-        return createScript(scriptName, binding).run();
-    }
-
-    /**
-     * Creates a Script with a given scriptName and binding.
-     *
-     * @param scriptName name of the script to run
-     * @param binding    the binding to pass to the script
-     * @return the script object
-     * @throws ResourceException if there is a problem accessing the script
-     * @throws ScriptException   if there is a problem parsing the script
-     */
-    public Script createScript(String scriptName, Binding binding) throws ResourceException, ScriptException {
-        return InvokerHelper.createScript(loadScriptByName(scriptName), binding);
-    }
-
-    private long getLastModified(String scriptName) throws ResourceException {
-        URLConnection conn = rc.getResourceConnection(scriptName);
-        long lastMod = 0;
-        try {
-            lastMod = conn.getLastModified();
-        } finally {
-            // getResourceConnection() opening the inputstream, let's ensure all streams are closed
-            forceClose(conn);
-        }
-        return lastMod;
-    }
-
-    protected boolean isSourceNewer(ScriptCacheEntry entry) throws ResourceException {
-        if (entry == null) return true;
-
-        long mainEntryLastCheck = entry.lastCheck;
-        long now = 0;
-
-        boolean returnValue = false;
-        for (String scriptName : entry.dependencies) {
-            ScriptCacheEntry depEntry = scriptCache.get(scriptName);
-            if (depEntry.sourceNewer) return true;
-
-            // check if maybe dependency was recompiled, but this one here not
-            if (mainEntryLastCheck < depEntry.lastModified) {
-                returnValue = true;
-                continue;
-            }
-
-            if (now == 0) now = getCurrentTime();
-            long nextSourceCheck = depEntry.lastCheck + config.getMinimumRecompilationInterval();
-            if (nextSourceCheck > now) continue;
-
-            long lastMod = getLastModified(scriptName);
-            if (depEntry.lastModified < lastMod) {
-                depEntry = new ScriptCacheEntry(depEntry, lastMod, true);
-                scriptCache.put(scriptName, depEntry);
-                returnValue = true;
-            } else {
-                depEntry = new ScriptCacheEntry(depEntry, now, false);
-                scriptCache.put(scriptName, depEntry);
-            }
-        }
-
-        return returnValue;
-    }
-
-    /**
-     * Returns the GroovyClassLoader associated with this script engine instance.
-     * Useful if you need to pass the class loader to another library.
-     *
-     * @return the GroovyClassLoader
-     */
-    public GroovyClassLoader getGroovyClassLoader() {
-        return groovyLoader;
-    }
-
-    /**
-     * @return a non null compiler configuration
-     */
-    public CompilerConfiguration getConfig() {
-        return config;
-    }
-
-    /**
-     * sets a compiler configuration
-     *
-     * @param config - the compiler configuration
-     * @throws NullPointerException if config is null
-     */
-    public void setConfig(CompilerConfiguration config) {
-        if (config == null) throw new NullPointerException("configuration cannot be null");
-        this.config = config;
-        this.groovyLoader = initGroovyLoader();
-    }
-
-    protected long getCurrentTime() {
-        return System.currentTimeMillis();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/IFileNameFinder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/IFileNameFinder.java b/src/main/groovy/util/IFileNameFinder.java
deleted file mode 100644
index 35e9012..0000000
--- a/src/main/groovy/util/IFileNameFinder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  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 groovy.util;
-
-import java.util.List;
-
-public interface IFileNameFinder {
-    List<String> getFileNames(String basedir, String pattern);
-    List<String> getFileNames(String basedir, String pattern, String excludesPattern);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/IndentPrinter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/IndentPrinter.java b/src/main/groovy/util/IndentPrinter.java
deleted file mode 100644
index df3d8c2..0000000
--- a/src/main/groovy/util/IndentPrinter.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.GroovyRuntimeException;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
-
-/**
- * A helper class for printing indented text. This can be used stand-alone or, more commonly, from Builders.
- * <p>
- * By default, a PrintWriter to System.out is used as the Writer, but it is possible
- * to change the Writer by passing a new one as a constructor argument.
- * <p>
- * Indention by default is 2 characters but can be changed by passing a
- * different value as a constructor argument.
- * <p>
- * The following is an example usage. Note that within a "with" block you need to
- * specify a parameter name so that this.println is not called instead of IndentPrinter.println:
- * <pre>
- * new IndentPrinter(new PrintWriter(out)).with { p ->
- *     p.printIndent()
- *     p.println('parent1')
- *     p.incrementIndent()
- *     p.printIndent()
- *     p.println('child 1')
- *     p.printIndent()
- *     p.println('child 2')
- *     p.decrementIndent()
- *     p.printIndent()
- *     p.println('parent2')
- *     p.flush()
- * }
- * </pre>
- * The above example prints this to standard output:
- * <pre>
- * parent1
- *   child 1
- *   child 2
- * parent2
- * </pre>
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class IndentPrinter {
-
-    private int indentLevel;
-    private final String indent;
-    private final Writer out;
-    private final boolean addNewlines;
-    private boolean autoIndent;
-
-    /**
-     * Creates an IndentPrinter backed by a PrintWriter pointing to System.out, with an indent of two spaces.
-     *
-     * @see #IndentPrinter(Writer, String)
-     */
-    public IndentPrinter() {
-        this(new PrintWriter(System.out), "  ");
-    }
-
-    /**
-     * Creates an IndentPrinter backed by the supplied Writer, with an indent of two spaces.
-     *
-     * @param out Writer to output to
-     * @see #IndentPrinter(Writer, String)
-     */
-    public IndentPrinter(Writer out) {
-        this(out, "  ");
-    }
-
-    /**
-     * Creates an IndentPrinter backed by the supplied Writer,
-     * with a user-supplied String to be used for indenting.
-     *
-     * @param out Writer to output to
-     * @param indent character(s) used to indent each line
-     */
-    public IndentPrinter(Writer out, String indent) {
-        this(out, indent, true);
-    }
-
-    /**
-     * Creates an IndentPrinter backed by the supplied Writer,
-     * with a user-supplied String to be used for indenting
-     * and the ability to override newline handling.
-     *
-     * @param out Writer to output to
-     * @param indent character(s) used to indent each line
-     * @param addNewlines set to false to gobble all new lines (default true)
-     */
-    public IndentPrinter(Writer out, String indent, boolean addNewlines) {
-       this(out, indent, addNewlines, false);
-    }
-
-    /**
-     * Create an IndentPrinter to the given PrintWriter
-     * @param out Writer to output to
-     * @param indent character(s) used to indent each line
-     * @param addNewlines set to false to gobble all new lines (default true)
-     * @param autoIndent set to true to make println() prepend the indent automatically (default false)
-     */
-    public IndentPrinter(Writer out, String indent, boolean addNewlines, boolean autoIndent) {
-        this.addNewlines = addNewlines;
-        if (out == null) {
-            throw new IllegalArgumentException("Must specify a Writer");
-        }
-        this.out = out;
-        this.indent = indent;
-        this.autoIndent = autoIndent;
-    }
-
-    /**
-     * Prints a string followed by an end of line character.
-     *
-     * @param  text String to be written
-     */
-    public void println(String text) {
-        try {
-            if(autoIndent) printIndent();
-            out.write(text);
-            println();
-        } catch(IOException ioe) {
-            throw new GroovyRuntimeException(ioe);
-        }
-    }
-
-    /**
-     * Prints a string.
-     *
-     * @param  text String to be written
-     */
-    public void print(String text) {
-        try {
-            out.write(text);
-        } catch(IOException ioe) {
-            throw new GroovyRuntimeException(ioe);
-        }
-    }
-
-    /**
-     * Prints a character.
-     *
-     * @param  c char to be written
-     */
-    public void print(char c) {
-        try {
-            out.write(c);
-        } catch(IOException ioe) {
-            throw new GroovyRuntimeException(ioe);
-        }
-    }
-
-    /**
-     * Prints the current indent level.
-     */
-    public void printIndent() {
-        for (int i = 0; i < indentLevel; i++) {
-            try {
-                out.write(indent);
-            } catch(IOException ioe) {
-                throw new GroovyRuntimeException(ioe);
-            }
-        }
-    }
-
-    /**
-     * Prints an end-of-line character (if enabled via addNewLines property).
-     * Defaults to outputting a single '\n' character but by using a custom
-     * Writer, e.g. PlatformLineWriter, you can get platform-specific
-     * end-of-line characters.
-     *
-     * @see #IndentPrinter(Writer, String, boolean)
-     */
-    public void println() {
-        if (addNewlines) {
-            try {
-                out.write("\n");
-            } catch(IOException ioe) {
-                throw new GroovyRuntimeException(ioe);
-            }
-        }
-    }
-
-    public void incrementIndent() {
-        ++indentLevel;
-    }
-
-    public void decrementIndent() {
-        --indentLevel;
-    }
-
-    public int getIndentLevel() {
-        return indentLevel;
-    }
-
-    public void setIndentLevel(int indentLevel) {
-        this.indentLevel = indentLevel;
-    }
-
-    public boolean getAutoIndent(){
-        return this.autoIndent;
-    }
-
-    public void setAutoIndent(boolean autoIndent){
-        this.autoIndent = autoIndent;
-    }
-
-    public void flush() {
-        try {
-            out.flush();
-        } catch(IOException ioe) {
-            throw new GroovyRuntimeException(ioe);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/MapEntry.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/MapEntry.java b/src/main/groovy/util/MapEntry.java
deleted file mode 100644
index 9190fcd..0000000
--- a/src/main/groovy/util/MapEntry.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *  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 groovy.util;
-
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.util.Map;
-
-/**
- * A Map.Entry implementation.
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class MapEntry implements Map.Entry {
-
-    private Object key;
-    private Object value;
-
-    public MapEntry(Object key, Object value) {
-        this.key = key;
-        this.value = value;
-    }
-
-    public boolean equals(Object that) {
-        if (that instanceof MapEntry) {
-            return equals((MapEntry) that);
-        }
-        return false;
-    }
-
-    public boolean equals(MapEntry that) {
-        return DefaultTypeTransformation.compareEqual(this.key, that.key) && DefaultTypeTransformation.compareEqual(this.value, that.value);
-    }
-
-    public int hashCode() {
-        return hash(key) ^ hash(value);
-    }
-
-    public String toString() {
-        return "" + key + ":" + value;
-    }
-
-    public Object getKey() {
-        return key;
-    }
-
-    public void setKey(Object key) {
-        this.key = key;
-    }
-
-    public Object getValue() {
-        return value;
-    }
-
-    public Object setValue(Object value) {
-        this.value = value;
-        return value;
-    }
-
-    /**
-     * Helper method to handle object hashes for possibly null values
-     */
-    protected int hash(Object object) {
-        return (object == null) ? 0xbabe : object.hashCode();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Node.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Node.java b/src/main/groovy/util/Node.java
deleted file mode 100644
index e40b14a..0000000
--- a/src/main/groovy/util/Node.java
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.DelegatingMetaClass;
-import groovy.lang.GroovySystem;
-import groovy.lang.MetaClass;
-import groovy.lang.Tuple2;
-import groovy.xml.QName;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.util.ListHashMap;
-
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-
-/**
- * Represents an arbitrary tree node which can be used for structured metadata or any arbitrary XML-like tree.
- * A node can have a name, a value and an optional Map of attributes.
- * Typically the name is a String and a value is either a String or a List of other Nodes,
- * though the types are extensible to provide a flexible structure, e.g. you could use a
- * QName as the name which includes a namespace URI and a local name. Or a JMX ObjectName etc.
- * So this class can represent metadata like <code>{foo a=1 b="abc"}</code> or nested
- * metadata like <code>{foo a=1 b="123" { bar x=12 text="hello" }}</code>
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Paul King
- */
-public class Node implements Serializable, Cloneable {
-
-    static {
-        // wrap the standard MetaClass with the delegate
-        setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(Node.class), Node.class);
-    }
-
-    private static final long serialVersionUID = 4121134753270542643L;
-
-    private Node parent;
-
-    private final Object name;
-
-    private final Map attributes;
-
-    private Object value;
-
-    /**
-     * Creates a new Node with the same name, no parent, shallow cloned attributes
-     * and if the value is a NodeList, a (deep) clone of those nodes.
-     *
-     * @return the clone
-     */
-    @Override
-    public Object clone() {
-        Object newValue = value;
-        if (value != null && value instanceof NodeList) {
-            NodeList nodes = (NodeList) value;
-            newValue = nodes.clone();
-        }
-        return new Node(null, name, new HashMap(attributes), newValue);
-    }
-
-    /**
-     * Creates a new Node named <code>name</code> and if a parent is supplied, adds
-     * the newly created node as a child of the parent.
-     *
-     * @param parent the parent node or null if no parent
-     * @param name   the name of the node
-     */
-    public Node(Node parent, Object name) {
-        this(parent, name, new NodeList());
-    }
-
-    /**
-     * Creates a new Node named <code>name</code> with value <code>value</code> and
-     * if a parent is supplied, adds the newly created node as a child of the parent.
-     *
-     * @param parent the parent node or null if no parent
-     * @param name   the name of the node
-     * @param value  the Node value, e.g. some text but in general any Object
-     */
-    public Node(Node parent, Object name, Object value) {
-        this(parent, name, new HashMap(), value);
-    }
-
-    /**
-     * Creates a new Node named <code>name</code> with
-     * attributes specified in the <code>attributes</code> Map. If a parent is supplied,
-     * the newly created node is added as a child of the parent.
-     *
-     * @param parent     the parent node or null if no parent
-     * @param name       the name of the node
-     * @param attributes a Map of name-value pairs
-     */
-    public Node(Node parent, Object name, Map attributes) {
-        this(parent, name, attributes, new NodeList());
-    }
-
-    /**
-     * Creates a new Node named <code>name</code> with value <code>value</code> and
-     * with attributes specified in the <code>attributes</code> Map. If a parent is supplied,
-     * the newly created node is added as a child of the parent.
-     *
-     * @param parent     the parent node or null if no parent
-     * @param name       the name of the node
-     * @param attributes a Map of name-value pairs
-     * @param value      the Node value, e.g. some text but in general any Object
-     */
-    public Node(Node parent, Object name, Map attributes, Object value) {
-        this.parent = parent;
-        this.name = name;
-        this.attributes = attributes;
-        this.value = value;
-
-        if (parent != null) {
-            getParentList(parent).add(this);
-        }
-    }
-
-    private static List getParentList(Node parent) {
-        Object parentValue = parent.value();
-        List parentList;
-        if (parentValue instanceof List) {
-            parentList = (List) parentValue;
-        } else {
-            parentList = new NodeList();
-            parentList.add(parentValue);
-            parent.setValue(parentList);
-        }
-        return parentList;
-    }
-
-    /**
-     * Appends a child to the current node.
-     *
-     * @param child the child to append
-     * @return <code>true</code>
-     */
-    public boolean append(Node child) {
-        child.setParent(this);
-        return getParentList(this).add(child);
-    }
-
-    /**
-     * Removes a child of the current node.
-     *
-     * @param child the child to remove
-     * @return <code>true</code> if the param was a child of the current node
-     */
-    public boolean remove(Node child) {
-        child.setParent(null);
-        return getParentList(this).remove(child);
-    }
-
-    /**
-     * Creates a new node as a child of the current node.
-     *
-     * @param name the name of the new node
-     * @param attributes the attributes of the new node
-     * @return the newly created <code>Node</code>
-     */
-    public Node appendNode(Object name, Map attributes) {
-        return new Node(this, name, attributes);
-    }
-
-    /**
-     * Creates a new node as a child of the current node.
-     *
-     * @param name the name of the new node
-     * @return the newly created <code>Node</code>
-     */
-    public Node appendNode(Object name) {
-        return new Node(this, name);
-    }
-
-    /**
-     * Creates a new node as a child of the current node.
-     *
-     * @param name the name of the new node
-     * @param value the value of the new node
-     * @return the newly created <code>Node</code>
-     */
-    public Node appendNode(Object name, Object value) {
-        return new Node(this, name, value);
-    }
-
-    /**
-     * Creates a new node as a child of the current node.
-     *
-     * @param name the name of the new node
-     * @param attributes the attributes of the new node
-     * @param value the value of the new node
-     * @return the newly created <code>Node</code>
-     */
-    public Node appendNode(Object name, Map attributes, Object value) {
-        return new Node(this, name, attributes, value);
-    }
-
-    /**
-     * Replaces the current node with nodes defined using builder-style notation via a Closure.
-     *
-     * @param c A Closure defining the new nodes using builder-style notation.
-     * @return the original now replaced node
-     */
-    public Node replaceNode(Closure c) {
-        if (parent() == null) {
-            throw new UnsupportedOperationException("Replacing the root node is not supported");
-        }
-        appendNodes(c);
-        getParentList(parent()).remove(this);
-        this.setParent(null);
-        return this;
-    }
-
-    /**
-     * Replaces the current node with the supplied node.
-     *
-     * @param n the new Node
-     * @return the original now replaced node
-     */
-    public Node replaceNode(Node n) {
-        if (parent() == null) {
-            throw new UnsupportedOperationException("Replacing the root node is not supported");
-        }
-        List tail = getTail();
-        parent().appendNode(n.name(), n.attributes(), n.value());
-        parent().children().addAll(tail);
-        getParentList(parent()).remove(this);
-        this.setParent(null);
-        return this;
-    }
-
-    private List getTail() {
-        List list = parent().children();
-        int afterIndex = list.indexOf(this);
-        List tail = new ArrayList(list.subList(afterIndex + 1, list.size()));
-        list.subList(afterIndex + 1, list.size()).clear();
-        return tail;
-    }
-
-    /**
-     * Adds sibling nodes (defined using builder-style notation via a Closure) after the current node.
-     *
-     * @param c A Closure defining the new sibling nodes to add using builder-style notation.
-     */
-    public void plus(Closure c) {
-        if (parent() == null) {
-            throw new UnsupportedOperationException("Adding sibling nodes to the root node is not supported");
-        }
-        appendNodes(c);
-    }
-
-    private void appendNodes(Closure c) {
-        List tail = getTail();
-        for (Node child : buildChildrenFromClosure(c)) {
-            parent().appendNode(child.name(), child.attributes(), child.value());
-        }
-        parent().children().addAll(tail);
-    }
-
-    private static List<Node> buildChildrenFromClosure(Closure c) {
-        NodeBuilder b = new NodeBuilder();
-        Node newNode = (Node) b.invokeMethod("dummyNode", c);
-        return newNode.children();
-    }
-
-    /**
-     * Extension point for subclasses to override the metaclass. The default
-     * one supports the property and @ attribute notations.
-     *
-     * @param metaClass the original metaclass
-     * @param nodeClass the class whose metaclass we wish to override (this class or a subclass)
-     */
-    protected static void setMetaClass(final MetaClass metaClass, Class nodeClass) {
-        // TODO Is protected static a bit of a smell?
-        // TODO perhaps set nodeClass to be Class<? extends Node>
-        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
-            @Override
-            public Object getAttribute(final Object object, final String attribute) {
-                Node n = (Node) object;
-                return n.get("@" + attribute);
-            }
-
-            @Override
-            public void setAttribute(final Object object, final String attribute, final Object newValue) {
-                Node n = (Node) object;
-                n.attributes().put(attribute, newValue);
-            }
-
-            @Override
-            public Object getProperty(Object object, String property) {
-                if (object instanceof Node) {
-                    Node n = (Node) object;
-                    return n.get(property);
-                }
-                return super.getProperty(object, property);
-            }
-
-            @Override
-            public void setProperty(Object object, String property, Object newValue) {
-                if (property.startsWith("@")) {
-                    setAttribute(object, property.substring(1), newValue);
-                    return;
-                }
-                delegate.setProperty(object, property, newValue);
-            }
-
-        };
-        GroovySystem.getMetaClassRegistry().setMetaClass(nodeClass, newMetaClass);
-    }
-
-    /**
-     * Returns the textual representation of the current node and all its child nodes.
-     *
-     * @return the text value of the node including child text
-     */
-    public String text() {
-        if (value instanceof String) {
-            return (String) value;
-        }
-        if (value instanceof NodeList) {
-            return ((NodeList) value).text();
-        }
-        if (value instanceof Collection) {
-            Collection coll = (Collection) value;
-            String previousText = null;
-            StringBuilder sb = null;
-            for (Object child : coll) {
-                String childText = null;
-                if (child instanceof String) {
-                    childText = (String) child;
-                } else if (child instanceof Node) {
-                    childText = ((Node) child).text();
-                }
-                if (childText != null) {
-                    if (previousText == null) {
-                        previousText = childText;
-                    } else {
-                        if (sb == null) {
-                            sb = new StringBuilder();
-                            sb.append(previousText);
-                        }
-                        sb.append(childText);
-                    }
-                }
-            }
-            if (sb != null) {
-                return sb.toString();
-            } else {
-                if (previousText != null) {
-                    return previousText;
-                }
-                return "";
-            }
-        }
-        return "" + value;
-    }
-
-    /**
-     * Returns an <code>Iterator</code> of the children of the node.
-     *
-     * @return the iterator of the nodes children
-     */
-    public Iterator iterator() {
-        return children().iterator();
-    }
-
-    /**
-     * Returns a <code>List</code> of the nodes children.
-     *
-     * @return the nodes children
-     */
-    public List children() {
-        if (value == null) {
-            return new NodeList();
-        }
-        if (value instanceof List) {
-            return (List) value;
-        }
-        // we're probably just a String
-        List result = new NodeList();
-        result.add(value);
-        return result;
-    }
-
-    /**
-     * Returns a <code>Map</code> of the attributes of the node or an empty <code>Map</code>
-     * if the node does not have any attributes.
-     *
-     * @return the attributes of the node
-     */
-    public Map attributes() {
-        return attributes;
-    }
-
-    /**
-     * Provides lookup of attributes by key.
-     *
-     * @param key the key of interest
-     * @return the attribute matching the key or <code>null</code> if no match exists
-     */
-    public Object attribute(Object key) {
-        return (attributes != null) ? attributes.get(key) : null;
-    }
-
-    /**
-     * Returns an <code>Object</code> representing the name of the node.
-     *
-     * @return the name or <code>null</code> if name is empty
-     */
-    public Object name() {
-        return name;
-    }
-
-    /**
-     * Returns an <code>Object</code> representing the value of the node.
-     *
-     * @return the value or <code>null</code> if value is empty
-     */
-    public Object value() {
-        return value;
-    }
-
-    /**
-     * Adds or replaces the value of the node.
-     *
-     * @param value the new value of the node
-     */
-    public void setValue(Object value) {
-        this.value = value;
-    }
-
-    /**
-     * Returns the parent of the node.
-     *
-     * @return the parent or <code>null</code> for the root node
-     */
-    public Node parent() {
-        return parent;
-    }
-
-    /**
-     * Adds or replaces the parent of the node.
-     *
-     * @param parent the new parent of the node
-     */
-    protected void setParent(Node parent) {
-        this.parent = parent;
-    }
-
-    /**
-     * Provides lookup of elements by non-namespaced name
-     *
-     * @param key the name (or shortcut key) of the node(s) of interest
-     * @return the nodes which match key
-     */
-    public Object get(String key) {
-        if (key != null && key.charAt(0) == '@') {
-            String attributeName = key.substring(1);
-            return attributes().get(attributeName);
-        }
-        if ("..".equals(key)) {
-            return parent();
-        }
-        if ("*".equals(key)) {
-            return children();
-        }
-        if ("**".equals(key)) {
-            return depthFirst();
-        }
-        return getByName(key);
-    }
-
-    /**
-     * Provides lookup of elements by QName.
-     *
-     * @param name the QName of interest
-     * @return the nodes matching name
-     */
-    public NodeList getAt(QName name) {
-        NodeList answer = new NodeList();
-        for (Object child : children()) {
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                Object childNodeName = childNode.name();
-                if (name.matches(childNodeName)) {
-                    answer.add(childNode);
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Provides lookup of elements by name.
-     *
-     * @param name the name of interest
-     * @return the nodes matching name
-     */
-    private NodeList getByName(String name) {
-        NodeList answer = new NodeList();
-        for (Object child : children()) {
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                Object childNodeName = childNode.name();
-                if (childNodeName instanceof QName) {
-                    QName qn = (QName) childNodeName;
-                    if (qn.matches(name)) {
-                        answer.add(childNode);
-                    }
-                } else if (name.equals(childNodeName)) {
-                    answer.add(childNode);
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a depth-first preorder traversal.
-     *
-     * @return the list of (depth-first) ordered nodes
-     */
-    public List depthFirst() {
-        return depthFirst(true);
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a depth-first traversal.
-     *
-     * @param preorder if false, a postorder depth-first traversal will be performed
-     * @return the list of (depth-first) ordered nodes
-     * @since 2.5.0
-     */
-    public List depthFirst(boolean preorder) {
-        List answer = new NodeList();
-        if (preorder) answer.add(this);
-        answer.addAll(depthFirstRest(preorder));
-        if (!preorder) answer.add(this);
-        return answer;
-    }
-
-    private List depthFirstRest(boolean preorder) {
-        List answer = new NodeList();
-        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
-            Object child = iter.next();
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                List children = childNode.depthFirstRest(preorder);
-                if (preorder) answer.add(childNode);
-                if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) answer.addAll(children);
-                if (!preorder) answer.add(childNode);
-            } else if (child instanceof String) {
-                answer.add(child);
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a depth-first preorder traversal.
-     *
-     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
-     *          closure will be passed the node, for a two param closure the second parameter will be the level).
-     * @since 2.5.0
-     */
-    public void depthFirst(Closure c) {
-        Map<String, Object> options = new ListHashMap<String, Object>();
-        options.put("preorder", true);
-        depthFirst(options, c);
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a depth-first traversal.
-     * A boolean 'preorder' options is supported.
-     *
-     * @param options map containing options
-     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
-     *          closure will be passed the node, for a two param closure the second parameter will be the level).
-     * @since 2.5.0
-     */
-    public void depthFirst(Map<String, Object> options, Closure c) {
-        boolean preorder = Boolean.valueOf(options.get("preorder").toString());
-        if (preorder) callClosureForNode(c, this, 1);
-        depthFirstRest(preorder, 2, c);
-        if (!preorder) callClosureForNode(c, this, 1);
-    }
-
-    private static <T> T callClosureForNode(Closure<T> closure, Object node, int level) {
-        if (closure.getMaximumNumberOfParameters() == 2) {
-            return closure.call(new Object[]{node, level});
-        }
-        return closure.call(node);
-    }
-
-    private void depthFirstRest(boolean preorder, int level, Closure c) {
-        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
-            Object child = iter.next();
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                if (preorder) callClosureForNode(c, childNode, level);
-                childNode.depthFirstRest(preorder, level + 1, c);
-                if (!preorder) callClosureForNode(c, childNode, level);
-            }
-        }
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a breadth-first preorder traversal.
-     *
-     * @return the list of (breadth-first) ordered nodes
-     */
-    public List breadthFirst() {
-        return breadthFirst(true);
-    }
-
-    /**
-     * Provides a collection of all the nodes in the tree
-     * using a breadth-first traversal.
-     *
-     * @param preorder if false, a postorder breadth-first traversal will be performed
-     * @return the list of (breadth-first) ordered nodes
-     * @since 2.5.0
-     */
-    public List breadthFirst(boolean preorder) {
-        List answer = new NodeList();
-        if (preorder) answer.add(this);
-        answer.addAll(breadthFirstRest(preorder));
-        if (!preorder) answer.add(this);
-        return answer;
-    }
-
-    private List breadthFirstRest(boolean preorder) {
-        List answer = new NodeList();
-        Stack stack = new Stack();
-        List nextLevelChildren = preorder ? getDirectChildren() : DefaultGroovyMethods.reverse(getDirectChildren());
-        while (!nextLevelChildren.isEmpty()) {
-            List working = new NodeList(nextLevelChildren);
-            nextLevelChildren = new NodeList();
-            for (Object child : working) {
-                if (preorder) {
-                    answer.add(child);
-                } else {
-                    stack.push(child);
-                }
-                if (child instanceof Node) {
-                    Node childNode = (Node) child;
-                    List children = childNode.getDirectChildren();
-                    if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) nextLevelChildren.addAll(preorder ? children : DefaultGroovyMethods.reverse(children));
-                }
-            }
-        }
-        while (!stack.isEmpty()) {
-            answer.add(stack.pop());
-        }
-        return answer;
-    }
-
-    /**
-     * Calls the provided closure for all the nodes in the tree
-     * using a breadth-first preorder traversal.
-     *
-     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
-     *          closure will be passed the node, for a two param closure the second parameter will be the level).
-     * @since 2.5.0
-     */
-    public void breadthFirst(Closure c) {
-        Map<String, Object> options = new ListHashMap<String, Object>();
-        options.put("preorder", true);
-        breadthFirst(options, c);
-    }
-
-    /**
-     * Calls the provided closure for all the nodes in the tree
-     * using a breadth-first traversal.
-     * A boolean 'preorder' options is supported.
-     *
-     * @param options map containing options
-     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
-     *          closure will be passed the node, for a two param closure the second parameter will be the level).
-     * @since 2.5.0
-     */
-    public void breadthFirst(Map<String, Object> options, Closure c) {
-        boolean preorder = Boolean.valueOf(options.get("preorder").toString());
-        if (preorder) callClosureForNode(c, this, 1);
-        breadthFirstRest(preorder, 2, c);
-        if (!preorder) callClosureForNode(c, this, 1);
-    }
-
-    private void breadthFirstRest(boolean preorder, int level, Closure c) {
-        Stack<Tuple2<Object, Integer>> stack = new Stack<Tuple2<Object, Integer>>();
-        List nextLevelChildren = preorder ? getDirectChildren() : DefaultGroovyMethods.reverse(getDirectChildren());
-        while (!nextLevelChildren.isEmpty()) {
-            List working = new NodeList(nextLevelChildren);
-            nextLevelChildren = new NodeList();
-            for (Object child : working) {
-                if (preorder) {
-                    callClosureForNode(c, child, level);
-                } else {
-                    stack.push(new Tuple2<Object, Integer>(child, level));
-                }
-                if (child instanceof Node) {
-                    Node childNode = (Node) child;
-                    List children = childNode.getDirectChildren();
-                    if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) nextLevelChildren.addAll(preorder ? children : DefaultGroovyMethods.reverse(children));
-                }
-            }
-            level++;
-        }
-        while (!stack.isEmpty()) {
-            Tuple2<Object, Integer> next = stack.pop();
-            callClosureForNode(c, next.getFirst(), next.getSecond());
-        }
-    }
-
-    /**
-     * Returns the list of any direct String nodes of this node.
-     *
-     * @return the list of String values from this node
-     * @since 2.3.0
-     */
-    public List<String> localText() {
-        List<String> answer = new ArrayList<String>();
-        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
-            Object child = iter.next();
-            if (!(child instanceof Node)) {
-                answer.add(child.toString());
-            }
-        }
-        return answer;
-    }
-
-    private List getDirectChildren() {
-        List answer = new NodeList();
-        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
-            Object child = iter.next();
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                answer.add(childNode);
-            } else if (child instanceof String) {
-                answer.add(child);
-            }
-        }
-        return answer;
-    }
-
-    public String toString() {
-        return name + "[attributes=" + attributes + "; value=" + value + "]";
-    }
-
-    /**
-     * Writes the node to the specified <code>PrintWriter</code>.
-     *
-     * @param out the writer receiving the output
-     */
-    public void print(PrintWriter out) {
-        new NodePrinter(out).print(this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/NodeBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/NodeBuilder.java b/src/main/groovy/util/NodeBuilder.java
deleted file mode 100644
index babe5c3..0000000
--- a/src/main/groovy/util/NodeBuilder.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  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 groovy.util;
-
-import java.util.Map;
-
-/**
- * A helper class for creating nested trees of Node objects for 
- * handling arbitrary data
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class NodeBuilder extends BuilderSupport {
-
-    public static NodeBuilder newInstance() {
-        return new NodeBuilder();
-    }
-
-    protected void setParent(Object parent, Object child) {
-    }
-
-    protected Object createNode(Object name) {
-        return new Node(getCurrentNode(), name);
-    }
-
-    protected Object createNode(Object name, Object value) {
-        return new Node(getCurrentNode(), name, value);
-    }
-
-    protected Object createNode(Object name, Map attributes) {
-        return new Node(getCurrentNode(), name, attributes);
-    }
-
-    protected Object createNode(Object name, Map attributes, Object value) {
-        return new Node(getCurrentNode(), name, attributes, value);
-    }
-
-    protected Node getCurrentNode() {
-        return (Node) getCurrent();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/NodeList.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/NodeList.java b/src/main/groovy/util/NodeList.java
deleted file mode 100644
index e54009c..0000000
--- a/src/main/groovy/util/NodeList.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.DelegatingMetaClass;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.GroovySystem;
-import groovy.lang.MetaClass;
-import groovy.xml.QName;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A List implementation which is returned by queries on a {@link Node}
- * which provides some XPath like helper methods for GPath.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Paul King
- */
-public class NodeList extends ArrayList {
-    static {
-        // wrap the standard MetaClass with the delegate
-        setMetaClass(NodeList.class, GroovySystem.getMetaClassRegistry().getMetaClass(NodeList.class));
-    }
-
-    public NodeList() {
-    }
-
-    public NodeList(Collection collection) {
-        super(collection);
-    }
-
-    public NodeList(int size) {
-        super(size);
-    }
-
-    /**
-     * Creates a new NodeList containing the same elements as the
-     * original (but cloned in the case of Nodes).
-     *
-     * @return the clone
-     */
-    @Override
-    public Object clone() {
-        NodeList result = new NodeList(size());
-        for (int i = 0; i < size(); i++) {
-            Object next = get(i);
-            if (next instanceof Node) {
-                Node n = (Node) next;
-                result.add(n.clone());
-            } else {
-                result.add(next);
-            }
-        }
-        return result;
-    }
-
-    protected static void setMetaClass(final Class nodelistClass, final MetaClass metaClass) {
-        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
-            @Override
-            public Object getAttribute(final Object object, final String attribute) {
-                NodeList nl = (NodeList) object;
-                Iterator it = nl.iterator();
-                List result = new ArrayList();
-                while (it.hasNext()) {
-                    Node node = (Node) it.next();
-                    result.add(node.attributes().get(attribute));
-                }
-                return result;
-            }
-
-            @Override
-            public void setAttribute(final Object object, final String attribute, final Object newValue) {
-                for (Object o : (NodeList) object) {
-                    Node node = (Node) o;
-                    node.attributes().put(attribute, newValue);
-                }
-            }
-
-            @Override
-            public Object getProperty(Object object, String property) {
-                if (object instanceof NodeList) {
-                    NodeList nl = (NodeList) object;
-                    return nl.getAt(property);
-                }
-                return super.getProperty(object, property);
-            }
-        };
-        GroovySystem.getMetaClassRegistry().setMetaClass(nodelistClass, newMetaClass);
-    }
-
-    /**
-     * Provides lookup of elements by non-namespaced name.
-     *
-     * @param name the name or shortcut key for nodes of interest
-     * @return the nodes of interest which match name
-     */
-    public NodeList getAt(String name) {
-        NodeList answer = new NodeList();
-        for (Object child : this) {
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                Object temp = childNode.get(name);
-                if (temp instanceof Collection) {
-                    answer.addAll((Collection) temp);
-                } else {
-                    answer.add(temp);
-                }
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Provides lookup of elements by QName.
-     *
-     * @param name the name or shortcut key for nodes of interest
-     * @return the nodes of interest which match name
-     */
-    public NodeList getAt(QName name) {
-        NodeList answer = new NodeList();
-        for (Object child : this) {
-            if (child instanceof Node) {
-                Node childNode = (Node) child;
-                NodeList temp = childNode.getAt(name);
-                answer.addAll(temp);
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Returns the text value of all of the elements in the collection.
-     *
-     * @return the text value of all the elements in the collection or null
-     */
-    public String text() {
-        String previousText = null;
-        StringBuilder buffer = null;
-        for (Object child : this) {
-            String text = null;
-            if (child instanceof String) {
-                text = (String) child;
-            } else if (child instanceof Node) {
-                text = ((Node) child).text();
-            }
-            if (text != null) {
-                if (previousText == null) {
-                    previousText = text;
-                } else {
-                    if (buffer == null) {
-                        buffer = new StringBuilder();
-                        buffer.append(previousText);
-                    }
-                    buffer.append(text);
-                }
-            }
-        }
-        if (buffer != null) {
-            return buffer.toString();
-        }
-        if (previousText != null) {
-            return previousText;
-        }
-        return "";
-    }
-
-    public Node replaceNode(Closure c) {
-        if (size() <= 0 || size() > 1) {
-            throw new GroovyRuntimeException(
-                    "replaceNode() can only be used to replace a single node, but was applied to " + size() + " nodes");
-        }
-        return ((Node)get(0)).replaceNode(c);
-    }
-
-    public void plus(Closure c) {
-        for (Object o : this) {
-            ((Node) o).plus(c);
-        }
-    }
-
-}


[13/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/SpreadListEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/SpreadListEvaluatingException.java b/src/main/groovy/lang/SpreadListEvaluatingException.java
deleted file mode 100644
index b6de965..0000000
--- a/src/main/groovy/lang/SpreadListEvaluatingException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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 groovy.lang;
-
-public class SpreadListEvaluatingException extends GroovyRuntimeException {
-    public SpreadListEvaluatingException(String message) {
-        super(message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/SpreadMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/SpreadMap.java b/src/main/groovy/lang/SpreadMap.java
deleted file mode 100644
index 7ba9e4f..0000000
--- a/src/main/groovy/lang/SpreadMap.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Helper to turn a list with an even number of elements into a Map.
- * 
- * @author Pilho Kim
- * @author Tim Tiemens
- */
-public class SpreadMap extends HashMap {
-    private int hashCode;
-
-    public SpreadMap(Object[] values) {
-        int i = 0;
-        while (i < values.length) {
-            super.put(values[i++], values[i++]);
-        }
-    }
-
-    public SpreadMap(Map map) {
-        super(map);
-    }
-
-    /**
-     * @since 1.8.0
-     * @param list the list to make spreadable
-     */
-    public SpreadMap(List list) {
-        this(list.toArray());
-    }
-
-    public Object put(Object key, Object value) {
-        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so ("
-                                   + key + ": " + value + ") cannot be added.");
-    }
-
-    public Object remove(Object key) {
-        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the key ("
-                                   + key + ") cannot be deleted.");
-    }
-
-    public void putAll(Map t) {
-        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the map ("
-                                   + t + ") cannot be put in this spreadMap.");
-    }
-
-    public boolean equals(Object that) {
-        if (that instanceof SpreadMap) {
-            return equals((SpreadMap) that);
-        }
-        return false;
-    }
-
-    public boolean equals(SpreadMap that) {
-        if (that == null) return false;        
-
-        if (size() == that.size()) {
-            for (Object key : keySet()) {
-                if (!DefaultTypeTransformation.compareEqual(get(key), that.get(key))) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public int hashCode() {
-        if (hashCode == 0) {
-            for (Object key : keySet()) {
-                int hash = (key != null) ? key.hashCode() : 0xbabe;
-                hashCode ^= hash;
-            }
-        }
-        return hashCode;
-    }
-
-    /**
-     * @return the string expression of <code>this</code>
-     */
-    public String toString() {
-        if (isEmpty()) {
-            return "*:[:]";
-        }
-        StringBuilder sb = new StringBuilder("*:[");
-        Iterator iter = keySet().iterator();
-        while (iter.hasNext()) {
-            Object key = iter.next();
-            sb.append(key).append(":").append(get(key));
-            if (iter.hasNext())
-                sb.append(", ");
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/SpreadMapEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/SpreadMapEvaluatingException.java b/src/main/groovy/lang/SpreadMapEvaluatingException.java
deleted file mode 100644
index 408a223..0000000
--- a/src/main/groovy/lang/SpreadMapEvaluatingException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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 groovy.lang;
-
-public class SpreadMapEvaluatingException extends GroovyRuntimeException {
-    public SpreadMapEvaluatingException(String message) {
-        super(message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/StringWriterIOException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/StringWriterIOException.java b/src/main/groovy/lang/StringWriterIOException.java
deleted file mode 100644
index 0372399..0000000
--- a/src/main/groovy/lang/StringWriterIOException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.io.IOException;
-
-/**
- * An IO exception occurred trying to append to a StringWriter which should never happen.
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class StringWriterIOException extends RuntimeException {
-
-    public StringWriterIOException(IOException e) {
-        super(e);
-    }
-
-    public IOException getIOException() {
-        return (IOException) getCause();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/TracingInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/TracingInterceptor.java b/src/main/groovy/lang/TracingInterceptor.java
deleted file mode 100644
index f67de11..0000000
--- a/src/main/groovy/lang/TracingInterceptor.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
-
-/*
- * This {@link Interceptor} traces method calls on the proxied object to a log. 
- * By default, the log is simply <pre>System.out</pre>; however, that can be 
- * changed with the <pre>setWriter(Writer)</pre> method.
- * <p>
- * A message will be written to output before a method is invoked and after a method
- * is invoked. If methods are nested, and invoke one another, then indentation 
- * of two spaces is written.
- * <p>
- * Here is an example usage on the ArrayList object: <br>
- * <pre class="groovyTestCase">
- * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
- * proxy.interceptor = new TracingInterceptor()
- * proxy.use {
- *     def list = [1, 2, 3]
- *     assert 3 == list.size()
- *     assert list.contains(1)
- * }
- * </pre>
- * Running this code produces this output: 
- * <pre>
- * before java.util.ArrayList.size()
- * after  java.util.ArrayList.size()
- * before java.util.ArrayList.contains(java.lang.Integer)
- * after  java.util.ArrayList.contains(java.lang.Integer)
- * </pre>
- */
-public class TracingInterceptor implements Interceptor {
-
-    protected Writer writer = new PrintWriter(System.out);
-    private int indent = 0;
-
-    /**
-    * Returns the writer associated with this interceptor. 
-    */ 
-    public Writer getWriter() {
-        return writer;
-    }
-
-    /**
-    * Changes the writer associated with this interceptor. 
-    */ 
-    public void setWriter(Writer writer) {
-        this.writer = writer;
-    }
-
-    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
-        write(object, methodName, arguments, "before");
-        indent++ ;
-        return null;
-    }
-
-    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
-        indent--;
-        write(object, methodName, arguments, "after ");
-        return result;
-    }
-
-    public boolean doInvoke() {
-        return true;
-    }
-    private String indent(){
-        StringBuilder result = new StringBuilder();
-        for (int i=0; i<indent;i++){
-            result.append("  ");
-        }
-        return result.toString();
-    }
-
-    protected void write(Object object, String methodName, Object[] arguments, final String origin) {
-        try {
-            writer.write(indent());
-            writer.write(origin);
-            writer.write(" ");
-            Class theClass = object instanceof Class ? (Class) object: object.getClass();
-            writeInfo(theClass, methodName, arguments);
-            writer.write("\n");
-            writer.flush();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    protected void writeInfo(final Class aClass, String methodName, Object[] arguments) throws IOException {
-        writer.write(aClass.getName());
-        writer.write(".");
-        writer.write(methodName);
-        writer.write("(");
-        for (int i = 0; i < arguments.length; i++) {
-            if (i > 0) writer.write(", ");
-            Object argument = arguments[i];
-            writer.write(argument.getClass().getName());
-        }
-        writer.write(")");
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/TrampolineClosure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/TrampolineClosure.java b/src/main/groovy/lang/TrampolineClosure.java
deleted file mode 100644
index ed68f00..0000000
--- a/src/main/groovy/lang/TrampolineClosure.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * A TrampolineClosure wraps a closure that needs to be executed on a functional trampoline.
- * Upon calling, a TrampolineClosure will call the original closure waiting for its result.
- * If the outcome of the call is another instance of a TrampolineClosure, created perhaps as a result to a call to the TrampolineClosure.trampoline()
- * method, the TrampolineClosure will again be invoked. This repetitive invocation of returned TrampolineClosure instances will continue
- * until a value other than TrampolineClosure is returned.
- * That value will become the final result of the trampoline.
- *
- * @author Vaclav Pech
- */
-final class TrampolineClosure<V> extends Closure<V> {
-
-    private final Closure<V> original;
-
-    TrampolineClosure(final Closure<V> original) {
-        super(original.getOwner(), original.getDelegate());
-        this.original = original;
-    }
-
-    /**
-     * Delegates to the wrapped closure
-     */
-    @Override
-    public int getMaximumNumberOfParameters() {
-        return original.maximumNumberOfParameters;
-    }
-
-    /**
-     * Delegates to the wrapped closure
-     */
-    @Override
-    public Class[] getParameterTypes() {
-        return original.parameterTypes;
-    }
-
-    /**
-     * Starts the trampoline loop and calls the wrapped closure as the first step.
-     * @return The final result of the trampoline
-     */
-    @Override
-    public V call() {
-        return loop(original.call());
-    }
-
-    /**
-     * Starts the trampoline loop and calls the wrapped closure as the first step.
-     * @return The final result of the trampoline
-     */
-    @Override
-    public V call(final Object arguments) {
-        return loop(original.call(arguments));
-    }
-
-    /**
-     * Starts the trampoline loop and calls the wrapped closure as the first step.
-     * @return The final result of the trampoline
-     */
-    @Override
-    public V call(final Object... args) {
-        return loop(original.call(args));
-    }
-
-    private V loop(final Object lastResult) {
-        Object result = lastResult;
-
-        for (;;) {
-            if (result instanceof TrampolineClosure) {
-                result = ((TrampolineClosure)result).original.call();
-            } else return (V) result;
-        }
-    }
-
-    /**
-     * Builds a trampolined variant of the current closure.
-     * @param args Parameters to curry to the underlying closure.
-     * @return An instance of TrampolineClosure wrapping the original closure after currying.
-     */
-    @Override
-   public Closure<V> trampoline(final Object... args) {
-        return new TrampolineClosure<V>(original.curry(args));
-    }
-
-    /**
-     * Returns itself, since it is a good enough trampolined variant of the current closure.
-     * @return An instance of TrampolineClosure wrapping the original closure.
-     */
-    @Override
-    public Closure<V> trampoline() {
-        return this;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple.java b/src/main/groovy/lang/Tuple.java
deleted file mode 100644
index 036d13e..0000000
--- a/src/main/groovy/lang/Tuple.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.io.Serializable;
-import java.util.AbstractList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Represents a list of Objects.
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class Tuple<E> extends AbstractList<E> implements Serializable {
-    private static final long serialVersionUID = -6707770506387821031L;
-    private final E[] contents;
-
-    public Tuple(E... contents) {
-        if (contents == null) throw new NullPointerException();
-        this.contents = contents;
-    }
-
-    @Override
-    public E get(int index) {
-        return contents[index];
-    }
-
-    @Override
-    public int size() {
-        return contents.length;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<E> subList(int fromIndex, int toIndex) {
-        int size = toIndex - fromIndex;
-        E[] newContent = (E[]) new Object[size];
-        System.arraycopy(contents, fromIndex, newContent, 0, size);
-        return new Tuple<>(newContent);
-    }
-
-    public Tuple<E> subTuple(int fromIndex, int toIndex) {
-        return (Tuple<E>) subList(fromIndex, toIndex);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof Tuple)) return false;
-
-        Tuple that = (Tuple) o;
-        int size = size();
-        if (size != that.size()) return false;
-        for (int i = 0; i < size; i++) {
-            if (!DefaultTypeTransformation.compareEqual(get(i), that.get(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(contents);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple1.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple1.java b/src/main/groovy/lang/Tuple1.java
deleted file mode 100644
index 9b8d6bd..0000000
--- a/src/main/groovy/lang/Tuple1.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 1 typed Object.
- *
- * @since 2.5.0
- */
-public class Tuple1<T1> extends Tuple {
-    private static final long serialVersionUID = -4647790147461409603L;
-    private final T1 first;
-
-    public Tuple1(T1 first) {
-        super(first);
-
-        this.first = first;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 1;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple2.java b/src/main/groovy/lang/Tuple2.java
deleted file mode 100644
index b096aee..0000000
--- a/src/main/groovy/lang/Tuple2.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 2 typed Objects.
- */
-public class Tuple2<T1, T2> extends Tuple {
-    private static final long serialVersionUID = 9006144674906325597L;
-    private final T1 first;
-    private final T2 second;
-
-    public Tuple2(T1 first, T2 second) {
-        super(first, second);
-
-        this.first = first;
-        this.second = second;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 2;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple3.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple3.java b/src/main/groovy/lang/Tuple3.java
deleted file mode 100644
index b5fe7d9..0000000
--- a/src/main/groovy/lang/Tuple3.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 3 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple3<T1, T2, T3> extends Tuple {
-    private static final long serialVersionUID = 8469774237154310687L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-
-    public Tuple3(T1 first, T2 second, T3 third) {
-        super(first, second, third);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 3;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple4.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple4.java b/src/main/groovy/lang/Tuple4.java
deleted file mode 100644
index 04f414e..0000000
--- a/src/main/groovy/lang/Tuple4.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 4 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple4<T1, T2, T3, T4> extends Tuple {
-    private static final long serialVersionUID = -7788878731471377207L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-
-    public Tuple4(T1 first, T2 second, T3 third, T4 fourth) {
-        super(first, second, third, fourth);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 4;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple5.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple5.java b/src/main/groovy/lang/Tuple5.java
deleted file mode 100644
index ee9c802..0000000
--- a/src/main/groovy/lang/Tuple5.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 5 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple5<T1, T2, T3, T4, T5> extends Tuple {
-    private static final long serialVersionUID = 6722094358774027115L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-    private final T5 fifth;
-
-    public Tuple5(T1 first, T2 second, T3 third, T4 fourth, T5 fifth) {
-        super(first, second, third, fourth, fifth);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-        this.fifth = fifth;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            case 4:
-                return fifth;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 5;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-
-    public T5 getFifth() {
-        return fifth;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple6.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple6.java b/src/main/groovy/lang/Tuple6.java
deleted file mode 100644
index 76d12ca..0000000
--- a/src/main/groovy/lang/Tuple6.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 6 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple6<T1, T2, T3, T4, T5, T6> extends Tuple {
-    private static final long serialVersionUID = -7848588473093102288L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-    private final T5 fifth;
-    private final T6 sixth;
-
-    public Tuple6(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth) {
-        super(first, second, third, fourth, fifth, sixth);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-        this.fifth = fifth;
-        this.sixth = sixth;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            case 4:
-                return fifth;
-            case 5:
-                return sixth;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 6;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-
-    public T5 getFifth() {
-        return fifth;
-    }
-
-    public T6 getSixth() {
-        return sixth;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple7.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple7.java b/src/main/groovy/lang/Tuple7.java
deleted file mode 100644
index 05046e7..0000000
--- a/src/main/groovy/lang/Tuple7.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 7 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple7<T1, T2, T3, T4, T5, T6, T7> extends Tuple {
-    private static final long serialVersionUID = 4226144828786865766L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-    private final T5 fifth;
-    private final T6 sixth;
-    private final T7 seventh;
-
-    public Tuple7(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh) {
-        super(first, second, third, fourth, fifth, sixth, seventh);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-        this.fifth = fifth;
-        this.sixth = sixth;
-        this.seventh = seventh;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            case 4:
-                return fifth;
-            case 5:
-                return sixth;
-            case 6:
-                return seventh;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 7;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-
-    public T5 getFifth() {
-        return fifth;
-    }
-
-    public T6 getSixth() {
-        return sixth;
-    }
-
-    public T7 getSeventh() {
-        return seventh;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple8.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple8.java b/src/main/groovy/lang/Tuple8.java
deleted file mode 100644
index 1f38ca9..0000000
--- a/src/main/groovy/lang/Tuple8.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 8 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple8<T1, T2, T3, T4, T5, T6, T7, T8> extends Tuple {
-    private static final long serialVersionUID = -8895822084644138566L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-    private final T5 fifth;
-    private final T6 sixth;
-    private final T7 seventh;
-    private final T8 eighth;
-
-    public Tuple8(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth) {
-        super(first, second, third, fourth, fifth, sixth, seventh, eighth);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-        this.fifth = fifth;
-        this.sixth = sixth;
-        this.seventh = seventh;
-        this.eighth = eighth;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            case 4:
-                return fifth;
-            case 5:
-                return sixth;
-            case 6:
-                return seventh;
-            case 7:
-                return eighth;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 8;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-
-    public T5 getFifth() {
-        return fifth;
-    }
-
-    public T6 getSixth() {
-        return sixth;
-    }
-
-    public T7 getSeventh() {
-        return seventh;
-    }
-
-    public T8 getEighth() {
-        return eighth;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Tuple9.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Tuple9.java b/src/main/groovy/lang/Tuple9.java
deleted file mode 100644
index 3189c10..0000000
--- a/src/main/groovy/lang/Tuple9.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Represents a list of 9 typed Objects.
- *
- * @since 2.5.0
- */
-public class Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends Tuple {
-    private static final long serialVersionUID = -5181196675351911769L;
-    private final T1 first;
-    private final T2 second;
-    private final T3 third;
-    private final T4 fourth;
-    private final T5 fifth;
-    private final T6 sixth;
-    private final T7 seventh;
-    private final T8 eighth;
-    private final T9 ninth;
-
-    public Tuple9(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth, T9 ninth) {
-        super(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth);
-
-        this.first = first;
-        this.second = second;
-        this.third = third;
-        this.fourth = fourth;
-        this.fifth = fifth;
-        this.sixth = sixth;
-        this.seventh = seventh;
-        this.eighth = eighth;
-        this.ninth = ninth;
-    }
-
-    @Override
-    public Object get(int index) {
-        switch (index) {
-            case 0:
-                return first;
-            case 1:
-                return second;
-            case 2:
-                return third;
-            case 3:
-                return fourth;
-            case 4:
-                return fifth;
-            case 5:
-                return sixth;
-            case 6:
-                return seventh;
-            case 7:
-                return eighth;
-            case 8:
-                return ninth;
-            default:
-                throw new IndexOutOfBoundsException("index: " + index);
-        }
-    }
-
-    @Override
-    public int size() {
-        return 9;
-    }
-
-    public T1 getFirst() {
-        return first;
-    }
-
-    public T2 getSecond() {
-        return second;
-    }
-
-    public T3 getThird() {
-        return third;
-    }
-
-    public T4 getFourth() {
-        return fourth;
-    }
-
-    public T5 getFifth() {
-        return fifth;
-    }
-
-    public T6 getSixth() {
-        return sixth;
-    }
-
-    public T7 getSeventh() {
-        return seventh;
-    }
-
-    public T8 getEighth() {
-        return eighth;
-    }
-
-    public T9 getNinth() {
-        return ninth;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Writable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Writable.java b/src/main/groovy/lang/Writable.java
deleted file mode 100644
index ec135cd..0000000
--- a/src/main/groovy/lang/Writable.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.io.IOException;
-import java.io.Writer;
-
-
-/**
- * Represents an object which is capable of writing itself to a text stream
- * in a more efficient format than just creating a toString() representation
- * of itself. This mechanism is particularly useful for templates and such like.
- * <p>
- * It is worth noting that writable implementations often override their
- * toString() implementation as well to allow rendering the same result 
- * directly to a String; however this is not required.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public interface Writable {
-
-    /**
-     * Writes this object to the given writer.
-     * <p>
-     * This is used to defer content creation until the point when it is
-     * streamed to the output destination.  Oftentimes, content will be defined 
-     * but not necessarily created (as is may be the case with a Closure 
-     * definition.)  In that case, the output is then 'deferred' to the point 
-     * when it is serialized to the writer. This class may be used whenever an 
-     * object should be responsible for creating its own textual representation, 
-     * but creating the entire output as a single String would be inefficient
-     * (such as outputting a multi-gigabyte XML document.)
-     * 
-     * @param out the Writer to which this Writable should output its data.
-     * @return the Writer that was passed
-     * @throws IOException if an error occurred while outputting data to the writer
-     */
-    Writer writeTo(Writer out) throws IOException;
-        
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/package.html b/src/main/groovy/lang/package.html
deleted file mode 100644
index 1ea84fc..0000000
--- a/src/main/groovy/lang/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-
-     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 groovy.lang.*</title>
-  </head>
-  <body>
-    <p>Core Groovy language classes for implementing data structures, closures, metadata and so forth.</p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/ast/builder/AstBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/ast/builder/AstBuilder.groovy b/src/main/groovy/org/codehaus/groovy/ast/builder/AstBuilder.groovy
new file mode 100644
index 0000000..24dcdd6
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/ast/builder/AstBuilder.groovy
@@ -0,0 +1,145 @@
+/*
+ *  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.ast.builder
+
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.control.CompilePhase
+
+/**
+ * The AstBuilder provides several ways to build an abstract syntax tree (AST) of Groovy code.
+ *
+ * You can convert a String into AST using the buildFromString method.
+ * You can convert code into AST using the buildFromCode method.
+ * You can use the AST DSL with the buildFromSpec method. 
+ * 
+ * For more information, see the resources on the Groovy wiki pages. 
+ *
+ * @author Hamlet D'Arcy
+ */
+
+public class AstBuilder {
+
+    /**
+     * Builds AST based on the code within the  {@link Closure}  parameter.
+     *
+     * This method <strong>must</strong> be invoked at compile time and never at runtime, because
+     * an ASTTransformation must be run to support it. If you receive an IllegalStateException then
+     * you most likely need to add stronger typing. For instance, this will not work:
+     * <code>
+     *      def builder = new AstBuilder()
+     *      builder.buildFromCode {
+     *             // some code
+     *      }
+     * </code>
+     * While this code will:
+     * <code>
+     *      new AstBuilder().buildFromCode {
+     *             // some code
+     *      }
+     * </code>
+     *
+     * The compiler rewrites buildFromCode invocations into  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
+     * invocations. An exception raised during AST generation will show a stack trace from  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
+     * and not from  {@link AstBuilder#buildFromCode(CompilePhase, boolean, Closure)} .
+     *
+     * The compiler saves the source code of the closure as a String within the Java class file. The String source
+     * of the closure will be visible and un-obfuscated within the class file. If your Closure parameter contains
+     * sensitive data such as a hard-coded password then that data is free to be seen by anyone with the class file.
+     * Do not store sensitive data within the closure parameter.
+     *
+     * @param phase
+     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
+     * @param statementsOnly
+     *      when true, only the script statements are returned. WHen false, you will
+     *      receive back a Script class node also. Default is true.
+     * @param block
+     *      the code that will be converted
+     * @returns a List of  {@link ASTNode} .
+     * @throws IllegalStateException
+     *      this method may not be invoked at runtime. It works via a compile-time transformation
+     *      of the closure source code into a String, which is sent to the  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
+     *      method. The buildFromCode() method must be invoked against a strongly typed AstBuilder.
+     */
+    List<ASTNode> buildFromCode(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, Closure block) {
+        throw new IllegalStateException("""AstBuilder.build(CompilePhase, boolean, Closure):List<ASTNode> should never be called at runtime.
+Are you sure you are using it correctly?
+""")
+    }
+
+
+    /**
+     * Builds AST based on the code within the String parameter.
+     *
+     * @param phase
+     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
+     * @param statementsOnly
+     *      when true, only the script statements are returned. WHen false, you will
+     *      receive back a Script class node also. Default is true.
+     * @param source
+     *      The source code String that will be compiled.
+     * @returns a List of  {@link ASTNode} .
+     * @throws IllegalArgumentException
+     *      if source is null or empty
+     */
+    List<ASTNode> buildFromString(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, String source) {
+        if (!source || "" == source.trim()) throw new IllegalArgumentException("A source must be specified")
+        return new AstStringCompiler().compile(source, phase, statementsOnly);
+    }
+
+    /**
+     * Builds AST based on the code within the String parameter. The parameter is assumed to be 
+     * a code block which is not legal Groovy code. A goto label is affixed to the block, compiled, 
+     * and the resulting BlockStatement wrapper is removed before returning a result. 
+     * @param phase
+     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
+     * @param statementsOnly
+     *      when true, only the script statements are returned. WHen false, you will
+     *      receive back a Script class node also. Default is true.
+     * @param source
+     *      The source code String that will be compiled. The string must be a block wrapped in curly braces. 
+     * @returns a List of  {@link ASTNode} .
+     * @throws IllegalArgumentException
+     *      if source is null or empty
+     */
+    private List<ASTNode> buildFromBlock(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, String source) {
+        if (!source || "" == source.trim()) throw new IllegalArgumentException("A source must be specified")
+        def labelledSource = "__synthesized__label__${System.currentTimeMillis()}__:" + source
+        List<ASTNode> result = new AstStringCompiler().compile(labelledSource, phase, statementsOnly)
+        // find the block statement from the result, and unwrap it from one level.
+        result.collect { node ->
+            if (node instanceof BlockStatement) {
+                ((BlockStatement)node).statements[0] //unwrap the artifact of pre-pending the goto label
+            } else {
+                node
+            }
+        }
+    }
+
+    /**
+     * Builds AST based on the DSL data within the Closure parameter.
+     * @param specification
+     *      the contents to create
+     */
+    List<ASTNode> buildFromSpec(@DelegatesTo(AstSpecificationCompiler) Closure specification) {
+        if (specification == null) throw new IllegalArgumentException('Null: specification')
+        def properties = new AstSpecificationCompiler(specification)
+        return properties.expression
+    }
+}
\ No newline at end of file


[07/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/TypeChecked.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TypeChecked.java b/src/main/groovy/transform/TypeChecked.java
deleted file mode 100644
index b902f3f..0000000
--- a/src/main/groovy/transform/TypeChecked.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This will let the Groovy compiler use compile time checks in the style of Java.
- * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({   ElementType.METHOD,         ElementType.TYPE,
-            ElementType.CONSTRUCTOR
-})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.StaticTypesTransformation")
-public @interface TypeChecked {
-    TypeCheckingMode value() default TypeCheckingMode.PASS;
-
-    /**
-     * The list of (classpath resources) paths to type checking DSL scripts, also known
-     * as type checking extensions.
-     * @return an array of paths to groovy scripts that must be on compile classpath
-     */
-    String[] extensions() default {};
-
-    /**
-     * This annotation is added by @TypeChecked on methods which have type checking turned on.
-     * It is used to embed type information into binary, so that the type checker can use this information,
-     * if available, for precompiled classes.
-     */
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    public @interface TypeCheckingInfo {
-        /**
-         * Returns the type checker information protocol number. This is used if the format of the
-         * string used in {@link #inferredType()} changes.
-         * @return the protocol version
-         */
-        int version() default 0;
-
-        /**
-         * An encoded type information.
-         * @return the inferred type
-         */
-        String inferredType();
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/TypeCheckingMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TypeCheckingMode.java b/src/main/groovy/transform/TypeCheckingMode.java
deleted file mode 100644
index 075bd71..0000000
--- a/src/main/groovy/transform/TypeCheckingMode.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  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 groovy.transform;
-
-/**
- * This enumeration can be used whenever it is preferred to annotate a class as
- * {@link TypeChecked} in general, but where only one or more methods are "dynamic". This allows the user
- * to annotate the class itself then annotate only the methods which require exclusion.
- *
- * @author Cedric Champeau
- */
-public enum TypeCheckingMode {
-    PASS,
-    SKIP
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Undefined.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Undefined.java b/src/main/groovy/transform/Undefined.java
deleted file mode 100644
index 35b360d..0000000
--- a/src/main/groovy/transform/Undefined.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.ast.ClassNode;
-
-/**
- * Java doesn't allow you to have null as an attribute value. It wants you to indicate what you really
- * mean by null, so that is what we do here - as ugly as it is.
- */
-public final class Undefined {
-    private Undefined() {}
-    public static final String STRING = "<DummyUndefinedMarkerString-DoNotUse>";
-    public static final class CLASS {}
-    public static final class EXCEPTION extends RuntimeException {
-        private static final long serialVersionUID = -3960500360386581172L;
-    }
-    public static boolean isUndefined(String other) { return STRING.equals(other); }
-    public static boolean isUndefined(ClassNode other) { return CLASS.class.getName().equals(other.getName()); }
-    public static boolean isUndefinedException(ClassNode other) { return EXCEPTION.class.getName().equals(other.getName()); }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/WithReadLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/WithReadLock.java b/src/main/groovy/transform/WithReadLock.java
deleted file mode 100644
index 475786a..0000000
--- a/src/main/groovy/transform/WithReadLock.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used in conjunction with {@link WithWriteLock} to support read and write synchronization on a method.
- * <p>
- * To use this annotation, declare {@code @WithReadLock} on your method. The method may be either an instance method or
- * a static method. The resulting method will allow multiple threads to read the information at the same time.
- * However, if some other method obtains a write lock, then this method will force callers to wait until the write is complete.
- * <p>
- * This annotation is a declarative wrapper around the JDK's <code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
- * Objects containing this annotation will have a ReentrantReadWriteLock field named <code>$reentrantLock</code> added to the class,
- * and method access is protected by the lock. If the method is static then the field is static and named <code>$REENTRANTLOCK</code>.
- * <p>
- * The annotation takes an optional parameter for the name of the field. This field must exist on the class and must be
- * of type ReentrantReadWriteLock.
- * <p>
- * To understand how this annotation works, it is convenient to think in terms of the source code it replaces. The following
- * is a typical usage of this annotation from Groovy:
- * <pre>
- * import groovy.transform.*;
- *
- * public class ResourceProvider {
- *
- *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
- *
- *    {@code @WithReadLock}
- *     public String getResource(String key) throws Exception {
- *             return data.get(key);
- *     }
- *
- *    {@code @WithWriteLock}
- *     public void refresh() throws Exception {
- *             //reload the resources into memory
- *     }
- * }
- * </pre>
- * As part of the Groovy compiler, code resembling this is produced:
- * <pre>
- * import java.util.concurrent.locks.ReentrantReadWriteLock;
- * import java.util.concurrent.locks.ReadWriteLock;
- *
- * public class ResourceProvider {
- *
- *     private final ReadWriteLock $reentrantlock = new ReentrantReadWriteLock();
- *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
- *
- *     public String getResource(String key) throws Exception {
- *         $reentrantlock.readLock().lock();
- *         try {
- *             return data.get(key);
- *         } finally {
- *             $reentrantlock.readLock().unlock();
- *         }
- *     }
- *
- *     public void refresh() throws Exception {
- *         $reentrantlock.writeLock().lock();
- *         try {
- *             //reload the resources into memory
- *         } finally {
- *             $reentrantlock.writeLock().unlock();
- *         }
- *     }
- * }
- * </pre>
- *
- * @author Hamlet D'Arcy
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.METHOD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
-public @interface WithReadLock {
-    /**
-     * @return if a user specified lock object with the given name should be used
-     *      the lock object must exist. If the annotated method is static then the 
-     *      lock object must be static. If the annotated method is not static then 
-     *      the lock object must not be static. 
-     */
-    String value () default "";
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/WithWriteLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/WithWriteLock.java b/src/main/groovy/transform/WithWriteLock.java
deleted file mode 100644
index 1eeb7f0..0000000
--- a/src/main/groovy/transform/WithWriteLock.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used in conjunction with {@link WithReadLock} to support read and write synchronization on a method.
- * <p>
- * To use this annotation, declare {@code @WithWriteLock} on your method. The method may be either an instance method or
- * a static method. The resulting method will allow only one thread access to the method at a time, and will wait to access
- * the method until any other read locks have been released.
- * <p>
- * This annotation is a declarative wrapper around the JDK's <code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
- * Objects containing this annotation will have a ReentrantReadWriteLock field named <code>$reentrantLock</code> added to the class,
- * and method access is protected by the lock. If the method is static then the field is static and named <code>$REENTRANTLOCK</code>.
- * <p>
- * The annotation takes an optional parameter for the name of the field. This field must exist on the class and must be
- * of type ReentrantReadWriteLock.
- * <p>
- * To understand how this annotation works, it is convenient to think in terms of the source code it replaces. The following
- * is a typical usage of this annotation from Groovy:
- * <pre>
- * import groovy.transform.*;
- *
- * public class ResourceProvider {
- *
- *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
- *
- *    {@code @WithReadLock}
- *     public String getResource(String key) throws Exception {
- *             return data.get(key);
- *     }
- *
- *    {@code @WithWriteLock}
- *     public void refresh() throws Exception {
- *             //reload the resources into memory
- *     }
- * }
- * </pre>
- * As part of the Groovy compiler, code resembling this is produced:
- * <pre>
- * import java.util.concurrent.locks.ReentrantReadWriteLock;
- * import java.util.concurrent.locks.ReadWriteLock;
- *
- * public class ResourceProvider {
- *
- *     private final ReadWriteLock $reentrantlock = new ReentrantReadWriteLock();
- *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
- *
- *     public String getResource(String key) throws Exception {
- *         $reentrantlock.readLock().lock();
- *         try {
- *             return data.get(key);
- *         } finally {
- *             $reentrantlock.readLock().unlock();
- *         }
- *     }
- *
- *     public void refresh() throws Exception {
- *         $reentrantlock.writeLock().lock();
- *         try {
- *             //reload the resources into memory
- *         } finally {
- *             $reentrantlock.writeLock().unlock();
- *         }
- *     }
- * }
- * </pre>
- *
- * @author Hamlet D'Arcy
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.METHOD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
-public @interface WithWriteLock {
-    /**
-     * @return if a user specified lock object with the given name should be used
-     *      the lock object must exist. If the annotated method is static then the 
-     *      lock object must be static. If the annotated method is not static then 
-     *      the lock object must not be static. 
-     */
-    String value () default "";
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/builder/Builder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/builder/Builder.java b/src/main/groovy/transform/builder/Builder.java
deleted file mode 100644
index 93b6090..0000000
--- a/src/main/groovy/transform/builder/Builder.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  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 groovy.transform.builder;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import static org.codehaus.groovy.transform.BuilderASTTransformation.BuilderStrategy;
-
-/**
- * The {@code @Builder} AST transformation is used to help write classes that can be created using <em>fluent</em> api calls.<!-- -->
- * The transform supports multiple building strategies to cover a range of cases and there are a number
- * of configuration options to customize the building process.
- *
- * In addition, a number of annotation attributes let you customise the building process. Not all annotation attributes
- * are supported by all strategies. See the individual strategy documentation for more details.
- * If you're an AST hacker, you can also define your own strategy class.
- *
- * The following strategies are bundled with Groovy:
- * <ul>
- *     <li>{@link SimpleStrategy} for creating chained setters</li>
- *     <li>{@link ExternalStrategy} where you annotate an explicit builder class while leaving some buildee class being built untouched</li>
- *     <li>{@link DefaultStrategy} which creates a nested helper class for instance creation</li>
- *     <li>{@link InitializerStrategy} which creates a nested helper class for instance creation which when used with {@code @CompileStatic} allows type-safe object creation</li>
- * </ul>
- *
- * Note that Groovy provides other built-in mechanisms for easy creation of objects, e.g. the named-args constructor:
- * <pre>
- * new Person(firstName: "Robert", lastName: "Lewandowski", age: 21)
- * </pre>
- * or the with statement:
- * <pre>
- * new Person().with {
- *     firstName = "Robert"
- *     lastName = "Lewandowski"
- *     age = 21
- * }
- * </pre>
- * so you might not find value in using the builder transform at all. But if you need Java integration or in some cases improved type safety, the {@code @Builder} transform might prove very useful.
- *
- * @see groovy.transform.builder.SimpleStrategy
- * @see groovy.transform.builder.ExternalStrategy
- * @see groovy.transform.builder.DefaultStrategy
- * @see groovy.transform.builder.InitializerStrategy
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.BuilderASTTransformation")
-public @interface Builder {
-
-    /**
-     * A class for which builder methods should be created. It will be an error to leave
-     * this attribute with its default value for some strategies.
-     */
-    Class forClass() default Undefined.CLASS.class;
-
-    /**
-     * A class capturing the builder strategy
-     */
-    Class<? extends BuilderStrategy> builderStrategy() default DefaultStrategy.class;
-
-    /**
-     * The prefix to use when creating the setter methods.
-     * Default is determined by the strategy which might use "" or "set" but you can choose your own, e.g. "with".
-     * If non-empty the first letter of the property will be capitalized before being appended to the prefix.
-     */
-    String prefix() default Undefined.STRING;
-
-    /**
-     * For strategies which create a builder helper class, the class name to use for the helper class.
-     * Not used if using {@code forClass} since in such cases the builder class is explicitly supplied.
-     * Default is determined by the strategy, e.g. <em>TargetClass</em> + "Builder" or <em>TargetClass</em> + "Initializer".
-     */
-    String builderClassName() default Undefined.STRING;
-
-    /**
-     * For strategies which create a builder helper class that creates the instance, the method name to call to create the instance.
-     * Default is determined by the strategy, e.g. <em>build</em> or <em>create</em>.
-     */
-    String buildMethodName() default Undefined.STRING;
-
-    /**
-     * The method name to use for a builder factory method in the source class for easy access of the
-     * builder helper class for strategies which create such a helper class.
-     * Must not be used if using {@code forClass}.
-     * Default is determined by the strategy, e.g. <em>builder</em> or <em>createInitializer</em>.
-     */
-    String builderMethodName() default Undefined.STRING;
-
-    /**
-     * List of field and/or property names to exclude from generated builder methods.
-     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * List of field and/or property names to include within the generated builder methods.
-     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined; all fields
-     * are included if includes remains undefined and excludes is explicitly or implicitly an empty list.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * By default, properties are set directly using their respective field.
-     * By setting {@code useSetters=true} then a writable property will be set using its setter.
-     * If turning on this flag we recommend that setters that might be called are
-     * made null-safe wrt the parameter.
-     */
-    boolean useSetters() default false;
-
-    /**
-     * Generate builder methods for properties from super classes.
-     */
-    boolean includeSuperProperties() default false;
-
-    /**
-     * Whether the generated builder should support all properties, including those with names that are considered internal.
-     *
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
-
-    /**
-     * Whether to include all properties (as per the JavaBean spec) in the generated builder.
-     * Groovy recognizes any field-like definitions with no explicit visibility as property definitions
-     * and always includes them in the {@code @Builder} generated classes. Groovy also treats any explicitly created getXxx() or isYyy()
-     * methods as property getters as per the JavaBean specification. Old versions of Groovy did not.
-     * So set this flag to false for the old behavior or if you want to explicitly exclude such properties.
-     * Currently only supported by DefaultStrategy and ExternalStrategy.
-     *
-     * @since 2.5.0
-     */
-    boolean allProperties() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/builder/DefaultStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/builder/DefaultStrategy.java b/src/main/groovy/transform/builder/DefaultStrategy.java
deleted file mode 100644
index 65d90e3..0000000
--- a/src/main/groovy/transform/builder/DefaultStrategy.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- *  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 groovy.transform.builder;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.InnerClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.transform.BuilderASTTransformation;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
-import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_STATIC;
-
-/**
- * This strategy is used with the {@link Builder} AST transform to create a builder helper class
- * for the fluent creation of instances of a specified class.&nbsp;It can be used at the class,
- * static method or constructor levels.
- *
- * You use it as follows:
- * <pre class="groovyTestCase">
- * import groovy.transform.builder.*
- *
- * {@code @Builder}
- * class Person {
- *     String firstName
- *     String lastName
- *     int age
- * }
- * def person = Person.builder().firstName("Robert").lastName("Lewandowski").age(21).build()
- * assert person.firstName == "Robert"
- * assert person.lastName == "Lewandowski"
- * assert person.age == 21
- * </pre>
- * The {@code prefix} annotation attribute can be used to create setters with a different naming convention. The default is the
- * empty string but you could change that to "set" as follows:
- * <pre class="groovyTestCase">
- * {@code @groovy.transform.builder.Builder}(prefix='set')
- * class Person {
- *     String firstName
- *     String lastName
- *     int age
- * }
- * def p2 = Person.builder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
- * </pre>
- * or using a prefix of 'with' would result in usage like this:
- * <pre>
- * def p3 = Person.builder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
- * </pre>
- *
- * You can also use the {@code @Builder} annotation in combination with this strategy on one or more constructor or
- * static method instead of or in addition to using it at the class level. An example with a constructor follows:
- * <pre class="groovyTestCase">
- * import groovy.transform.ToString
- * import groovy.transform.builder.Builder
- *
- * {@code @ToString}
- * class Person {
- *     String first, last
- *     int born
- *
- *     {@code @Builder}
- *     Person(String roleName) {
- *         if (roleName == 'Jack Sparrow') {
- *             first = 'Johnny'; last = 'Depp'; born = 1963
- *         }
- *     }
- * }
- * assert Person.builder().roleName("Jack Sparrow").build().toString() == 'Person(Johnny, Depp, 1963)'
- * </pre>
- * In this case, the parameter(s) for the constructor or static method become the properties available
- * in the builder. For the case of a static method, the return type of the static method becomes the
- * class of the instance being created. For static factory methods, this is normally the class containing the
- * static method but in general it can be any class.
- *
- * Note: if using more than one {@code @Builder} annotation, which is only possible when using static method
- * or constructor variants, it is up to you to ensure that any generated helper classes or builder methods
- * have unique names. E.g.&nbsp;we can modify the previous example to have three builders. At least two of the builders
- * in our case will need to set the 'builderClassName' and 'builderMethodName' annotation attributes to ensure
- * we have unique names. This is shown in the following example:
- * <pre class="groovyTestCase">
- * import groovy.transform.builder.*
- * import groovy.transform.*
- *
- * {@code @ToString}
- * {@code @Builder}
- * class Person {
- *     String first, last
- *     int born
- *
- *     Person(){} // required to retain no-arg constructor
- *
- *     {@code @Builder}(builderClassName='MovieBuilder', builderMethodName='byRoleBuilder')
- *     Person(String roleName) {
- *         if (roleName == 'Jack Sparrow') {
- *             this.first = 'Johnny'; this.last = 'Depp'; this.born = 1963
- *         }
- *     }
- *
- *     {@code @Builder}(builderClassName='SplitBuilder', builderMethodName='splitBuilder')
- *     static Person split(String name, int year) {
- *         def parts = name.split(' ')
- *         new Person(first: parts[0], last: parts[1], born: year)
- *     }
- * }
- *
- * assert Person.splitBuilder().name("Johnny Depp").year(1963).build().toString() == 'Person(Johnny, Depp, 1963)'
- * assert Person.byRoleBuilder().roleName("Jack Sparrow").build().toString() == 'Person(Johnny, Depp, 1963)'
- * assert Person.builder().first("Johnny").last('Depp').born(1963).build().toString() == 'Person(Johnny, Depp, 1963)'
- * </pre>
- *
- * The 'forClass' annotation attribute for the {@code @Builder} transform isn't applicable for this strategy.
- * The 'useSetters' annotation attribute for the {@code @Builder} transform is ignored by this strategy which always uses setters.
- */
-public class DefaultStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
-    private static final Expression DEFAULT_INITIAL_VALUE = null;
-    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
-
-    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
-        if (unsupportedAttribute(transform, anno, "forClass")) return;
-        if (annotatedNode instanceof ClassNode) {
-            buildClass(transform, (ClassNode) annotatedNode, anno);
-        } else if (annotatedNode instanceof MethodNode) {
-            buildMethod(transform, (MethodNode) annotatedNode, anno);
-        }
-    }
-
-    public void buildMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
-        if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "excludes") != null) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
-                    " processing: includes/excludes only allowed on classes", anno);
-        }
-        ClassNode buildee = mNode.getDeclaringClass();
-        ClassNode builder = createBuilder(anno, buildee);
-        createBuilderFactoryMethod(anno, buildee, builder);
-        for (Parameter parameter : mNode.getParameters()) {
-            builder.addField(createFieldCopy(buildee, parameter));
-            builder.addMethod(createBuilderMethodForProp(builder, new PropertyInfo(parameter.getName(), parameter.getType()), getPrefix(anno)));
-        }
-        builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, mNode.getParameters()));
-    }
-
-    public void buildClass(BuilderASTTransformation transform, ClassNode buildee, AnnotationNode anno) {
-        List<String> excludes = new ArrayList<String>();
-        List<String> includes = new ArrayList<String>();
-        includes.add(Undefined.STRING);
-        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
-        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
-        ClassNode builder = createBuilder(anno, buildee);
-        createBuilderFactoryMethod(anno, buildee, builder);
-//        List<FieldNode> fields = getFields(transform, anno, buildee);
-        boolean allNames = transform.memberHasValue(anno, "allNames", true);
-        boolean allProperties = !transform.memberHasValue(anno, "allProperties", false);
-        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, excludes, includes, allNames, allProperties);
-        for (PropertyInfo pi : props) {
-            ClassNode correctedType = getCorrectedType(buildee, pi.getType(), builder);
-            String fieldName = pi.getName();
-            builder.addField(createFieldCopy(buildee, fieldName, correctedType));
-            builder.addMethod(createBuilderMethodForProp(builder, new PropertyInfo(fieldName, correctedType), getPrefix(anno)));
-        }
-        builder.addMethod(createBuildMethod(anno, buildee, props));
-    }
-
-    private static ClassNode getCorrectedType(ClassNode buildee, ClassNode fieldType, ClassNode declaringClass) {
-        Map<String,ClassNode> genericsSpec = createGenericsSpec(declaringClass);
-        extractSuperClassGenerics(fieldType, buildee, genericsSpec);
-        return correctToGenericsSpecRecurse(genericsSpec, fieldType);
-    }
-
-    private static void createBuilderFactoryMethod(AnnotationNode anno, ClassNode buildee, ClassNode builder) {
-        buildee.getModule().addClass(builder);
-        buildee.addMethod(createBuilderMethod(anno, builder));
-    }
-
-    private static ClassNode createBuilder(AnnotationNode anno, ClassNode buildee) {
-        return new InnerClassNode(buildee, getFullName(anno, buildee), PUBLIC_STATIC, OBJECT_TYPE);
-    }
-
-    private static String getFullName(AnnotationNode anno, ClassNode buildee) {
-        String builderClassName = getMemberStringValue(anno, "builderClassName", buildee.getNameWithoutPackage() + "Builder");
-        return buildee.getName() + "$" + builderClassName;
-    }
-
-    private static String getPrefix(AnnotationNode anno) {
-        return getMemberStringValue(anno, "prefix", "");
-    }
-
-    private static MethodNode createBuildMethodForMethod(AnnotationNode anno, ClassNode buildee, MethodNode mNode, Parameter[] params) {
-        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
-        final BlockStatement body = new BlockStatement();
-        ClassNode returnType;
-        if (mNode instanceof ConstructorNode) {
-            returnType = newClass(buildee);
-            body.addStatement(returnS(ctorX(newClass(mNode.getDeclaringClass()), args(params))));
-        } else {
-            body.addStatement(returnS(callX(newClass(mNode.getDeclaringClass()), mNode.getName(), args(params))));
-            returnType = newClass(mNode.getReturnType());
-        }
-        return new MethodNode(buildMethodName, ACC_PUBLIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
-    }
-
-    private static MethodNode createBuilderMethod(AnnotationNode anno, ClassNode builder) {
-        String builderMethodName = getMemberStringValue(anno, "builderMethodName", "builder");
-        final BlockStatement body = new BlockStatement();
-        body.addStatement(returnS(ctorX(builder)));
-        return new MethodNode(builderMethodName, PUBLIC_STATIC, builder, NO_PARAMS, NO_EXCEPTIONS, body);
-    }
-
-    private static MethodNode createBuildMethod(AnnotationNode anno, ClassNode buildee, List<PropertyInfo> props) {
-        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
-        final BlockStatement body = new BlockStatement();
-        body.addStatement(returnS(initializeInstance(buildee, props, body)));
-        return new MethodNode(buildMethodName, ACC_PUBLIC, newClass(buildee), NO_PARAMS, NO_EXCEPTIONS, body);
-    }
-
-    private MethodNode createBuilderMethodForProp(ClassNode builder, PropertyInfo pinfo, String prefix) {
-        ClassNode fieldType = pinfo.getType();
-        String fieldName = pinfo.getName();
-        String setterName = getSetterName(prefix, fieldName);
-        return new MethodNode(setterName, ACC_PUBLIC, newClass(builder), params(param(fieldType, fieldName)), NO_EXCEPTIONS, block(
-                stmt(assignX(propX(varX("this"), constX(fieldName)), varX(fieldName, fieldType))),
-                returnS(varX("this", builder))
-        ));
-    }
-
-    private static FieldNode createFieldCopy(ClassNode buildee, Parameter param) {
-        Map<String,ClassNode> genericsSpec = createGenericsSpec(buildee);
-        extractSuperClassGenerics(param.getType(), buildee, genericsSpec);
-        ClassNode correctedParamType = correctToGenericsSpecRecurse(genericsSpec, param.getType());
-        return new FieldNode(param.getName(), ACC_PRIVATE, correctedParamType, buildee, param.getInitialExpression());
-    }
-
-    private static FieldNode createFieldCopy(ClassNode buildee, String fieldName, ClassNode fieldType) {
-        return new FieldNode(fieldName, ACC_PRIVATE, fieldType, buildee, DEFAULT_INITIAL_VALUE);
-    }
-
-    private static Expression initializeInstance(ClassNode buildee, List<PropertyInfo> props, BlockStatement body) {
-        Expression instance = varX("_the" + buildee.getNameWithoutPackage(), buildee);
-        body.addStatement(declS(instance, ctorX(buildee)));
-        for (PropertyInfo pi : props) {
-            body.addStatement(stmt(assignX(propX(instance, pi.getName()), varX(pi.getName(), pi.getType()))));
-        }
-        return instance;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/builder/ExternalStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/builder/ExternalStrategy.java b/src/main/groovy/transform/builder/ExternalStrategy.java
deleted file mode 100644
index c482bef..0000000
--- a/src/main/groovy/transform/builder/ExternalStrategy.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- *  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 groovy.transform.builder;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.transform.BuilderASTTransformation;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.MY_TYPE_NAME;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-
-/**
- * This strategy is used with the {@link Builder} AST transform to populate a builder helper class
- * so that it can be used for the fluent creation of instances of a specified class.&nbsp;The specified class is not modified in any way and may be a Java class.
- *
- * You use it by creating and annotating an explicit builder class which will be filled in by during
- * annotation processing with the appropriate build method and setters. An example is shown here:
- * <pre class="groovyTestCase">
- * import groovy.transform.builder.*
- *
- * class Person {
- *     String firstName
- *     String lastName
- * }
- *
- * {@code @Builder}(builderStrategy=ExternalStrategy, forClass=Person)
- * class PersonBuilder { }
- *
- * def person = new PersonBuilder().firstName("Robert").lastName("Lewandowski").build()
- * assert person.firstName == "Robert"
- * assert person.lastName == "Lewandowski"
- * </pre>
- * The {@code prefix} annotation attribute, which defaults to the empty String for this strategy, can be used to create setters with a different naming convention, e.g. with
- * the {@code prefix} changed to 'set', you would use your setters as follows:
- * <pre>
- * def p1 = new PersonBuilder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
- * </pre>
- * or using a prefix of 'with':
- * <pre>
- * def p2 = new PersonBuilder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
- * </pre>
- *
- * The properties to use can be filtered using either the 'includes' or 'excludes' annotation attributes for {@code @Builder}.
- * The {@code @Builder} 'buildMethodName' annotation attribute can be used for configuring the build method's name, default "build".
- *
- * The {@code @Builder} 'builderMethodName' and 'builderClassName' annotation attributes aren't applicable for this strategy.
- * The {@code @Builder} 'useSetters' annotation attribute is ignored by this strategy which always uses setters.
- */
-public class ExternalStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
-    private static final Expression DEFAULT_INITIAL_VALUE = null;
-
-    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
-        if (!(annotatedNode instanceof ClassNode)) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: building for " +
-                    annotatedNode.getClass().getSimpleName() + " not supported by " + getClass().getSimpleName(), annotatedNode);
-            return;
-        }
-        ClassNode builder = (ClassNode) annotatedNode;
-        String prefix = transform.getMemberStringValue(anno, "prefix", "");
-        ClassNode buildee = transform.getMemberClassValue(anno, "forClass");
-        if (buildee == null) {
-            transform.addError("Error during " + MY_TYPE_NAME + " processing: 'forClass' must be specified for " + getClass().getName(), anno);
-            return;
-        }
-        List<String> excludes = new ArrayList<String>();
-        List<String> includes = new ArrayList<String>();
-        includes.add(Undefined.STRING);
-        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
-        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
-        if (unsupportedAttribute(transform, anno, "builderClassName")) return;
-        if (unsupportedAttribute(transform, anno, "builderMethodName")) return;
-        boolean allNames = transform.memberHasValue(anno, "allNames", true);
-        boolean allProperties = !transform.memberHasValue(anno, "allProperties", false);
-        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, excludes, includes, allNames, allProperties);
-        if (includes != null) {
-            for (String name : includes) {
-                checkKnownProperty(transform, anno, name, props);
-            }
-        }
-        for (PropertyInfo prop : props) {
-            builder.addField(createFieldCopy(builder, prop));
-            builder.addMethod(createBuilderMethodForField(builder, prop, prefix));
-        }
-        builder.addMethod(createBuildMethod(transform, anno, buildee, props));
-    }
-
-    private static MethodNode createBuildMethod(BuilderASTTransformation transform, AnnotationNode anno, ClassNode sourceClass, List<PropertyInfo> fields) {
-        String buildMethodName = transform.getMemberStringValue(anno, "buildMethodName", "build");
-        final BlockStatement body = new BlockStatement();
-        Expression sourceClassInstance = initializeInstance(sourceClass, fields, body);
-        body.addStatement(returnS(sourceClassInstance));
-        return new MethodNode(buildMethodName, ACC_PUBLIC, sourceClass, NO_PARAMS, NO_EXCEPTIONS, body);
-    }
-
-    private MethodNode createBuilderMethodForField(ClassNode builderClass, PropertyInfo prop, String prefix) {
-        String propName = prop.getName().equals("class") ? "clazz" : prop.getName();
-        String setterName = getSetterName(prefix, prop.getName());
-        return new MethodNode(setterName, ACC_PUBLIC, newClass(builderClass), params(param(newClass(prop.getType()), propName)), NO_EXCEPTIONS, block(
-                stmt(assignX(propX(varX("this"), constX(propName)), varX(propName))),
-                returnS(varX("this", newClass(builderClass)))
-        ));
-    }
-
-    private static FieldNode createFieldCopy(ClassNode builderClass, PropertyInfo prop) {
-        String propName = prop.getName();
-        return new FieldNode(propName.equals("class") ? "clazz" : propName, ACC_PRIVATE, newClass(prop.getType()), builderClass, DEFAULT_INITIAL_VALUE);
-    }
-
-    private static Expression initializeInstance(ClassNode sourceClass, List<PropertyInfo> props, BlockStatement body) {
-        Expression instance = varX("_the" + sourceClass.getNameWithoutPackage(), sourceClass);
-        body.addStatement(declS(instance, ctorX(sourceClass)));
-        for (PropertyInfo prop : props) {
-            body.addStatement(stmt(assignX(propX(instance, prop.getName()), varX(prop.getName().equals("class") ? "clazz" : prop.getName(), newClass(prop.getType())))));
-        }
-        return instance;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/builder/InitializerStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/builder/InitializerStrategy.java b/src/main/groovy/transform/builder/InitializerStrategy.java
deleted file mode 100644
index c678c38..0000000
--- a/src/main/groovy/transform/builder/InitializerStrategy.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- *  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 groovy.transform.builder;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.GenericsType;
-import org.codehaus.groovy.ast.InnerClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.classgen.Verifier;
-import org.codehaus.groovy.transform.AbstractASTTransformation;
-import org.codehaus.groovy.transform.BuilderASTTransformation;
-import org.codehaus.groovy.transform.ImmutableASTTransformation;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorThisS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafeWithGenerics;
-import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_STATIC;
-import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
-
-/**
- * This strategy is used with the {@link Builder} AST transform to create a builder helper class
- * for the fluent and type-safe creation of instances of a specified class.
- *
- * It is modelled roughly on the design outlined here:
- * http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/
- *
- * You define classes which use the type-safe initializer pattern as follows:
- * <pre>
- * import groovy.transform.builder.*
- * import groovy.transform.*
- *
- * {@code @ToString}
- * {@code @Builder}(builderStrategy=InitializerStrategy) class Person {
- *     String firstName
- *     String lastName
- *     int age
- * }
- * </pre>
- * While it isn't required to do so, the benefit of this builder strategy comes in conjunction with static type-checking or static compilation. Typical usage is as follows:
- * <pre>
- * {@code @CompileStatic}
- * def main() {
- *     println new Person(Person.createInitializer().firstName("John").lastName("Smith").age(21))
- * }
- * </pre>
- * which prints:
- * <pre>
- * Person(John, Smith, 21)
- * </pre>
- * If you don't initialise some of the properties, your code won't compile, e.g. if the method body above was changed to this:
- * <pre>
- * println new Person(Person.createInitializer().firstName("John").lastName("Smith"))
- * </pre>
- * then the following compile-time error would result:
- * <pre>
- * [Static type checking] - Cannot find matching method Person#<init>(Person$PersonInitializer <groovy.transform.builder.InitializerStrategy$SET, groovy.transform.builder.InitializerStrategy$SET, groovy.transform.builder.InitializerStrategy$UNSET>). Please check if the declared type is right and if the method exists.
- * </pre>
- * The message is a little cryptic, but it is basically the static compiler telling us that the third parameter, {@code age} in our case, is unset.
- *
- * You can also add this annotation to your predefined constructors. These will be made private and an initializer will be set up
- * to call your constructor. Any parameters to your constructor become the properties expected by the initializer.
- * If you use such a builder on a constructor as well as on the class or on more than one constructor, then it is up to you
- * to define unique values for 'builderClassName' and 'builderMethodName' for each annotation.
- */
-public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
-
-    /**
-     * Internal phantom type used by the {@code InitializerStrategy} to indicate that a property has been set. It is used in conjunction with the generated parameterized type helper class.
-     */
-    public abstract static class SET {
-    }
-
-    /**
-     * Internal phantom type used by the {@code InitializerStrategy} to indicate that a property remains unset. It is used in conjunction with the generated parameterized type helper class.
-     */
-    public abstract static class UNSET {
-    }
-
-    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
-    private static final Expression DEFAULT_INITIAL_VALUE = null;
-
-    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
-        if (unsupportedAttribute(transform, anno, "forClass")) return;
-        if (unsupportedAttribute(transform, anno, "allProperties")) return;
-        boolean useSetters = transform.memberHasValue(anno, "useSetters", true);
-        boolean allNames = transform.memberHasValue(anno, "allNames", true);
-        if (annotatedNode instanceof ClassNode) {
-            createBuilderForAnnotatedClass(transform, (ClassNode) annotatedNode, anno, useSetters, allNames);
-        } else if (annotatedNode instanceof MethodNode) {
-            createBuilderForAnnotatedMethod(transform, (MethodNode) annotatedNode, anno, useSetters);
-        }
-    }
-
-    private void createBuilderForAnnotatedClass(BuilderASTTransformation transform, ClassNode buildee, AnnotationNode anno, boolean useSetters, boolean allNames) {
-        List<String> excludes = new ArrayList<String>();
-        List<String> includes = new ArrayList<String>();
-        includes.add(Undefined.STRING);
-        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
-        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
-        List<FieldNode> fields = getFields(transform, anno, buildee);
-        List<FieldNode> filteredFields = filterFields(fields, includes, excludes, allNames);
-        if (filteredFields.isEmpty()) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
-                    " processing: at least one property is required for this strategy", anno);
-        }
-        ClassNode builder = createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), filteredFields.size());
-        addFields(buildee, filteredFields, builder);
-
-        buildCommon(buildee, anno, filteredFields, builder);
-        createBuildeeConstructors(transform, buildee, builder, filteredFields, true, useSetters);
-    }
-
-    private void createBuilderForAnnotatedMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno, boolean useSetters) {
-        if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "excludes") != null) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
-                    " processing: includes/excludes only allowed on classes", anno);
-        }
-        if (mNode instanceof ConstructorNode) {
-            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC);
-        } else {
-            if ((mNode.getModifiers() & ACC_STATIC) == 0) {
-                transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
-                        " processing: method builders only allowed on static methods", anno);
-            }
-            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC);
-        }
-        ClassNode buildee = mNode.getDeclaringClass();
-        Parameter[] parameters = mNode.getParameters();
-        if (parameters.length == 0) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
-                    " processing: at least one parameter is required for this strategy", anno);
-        }
-        ClassNode builder = createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), parameters.length);
-        List<FieldNode> convertedFields = convertParamsToFields(builder, parameters);
-
-        buildCommon(buildee, anno, convertedFields, builder);
-        if (mNode instanceof ConstructorNode) {
-            createBuildeeConstructors(transform, buildee, builder, convertedFields, false, useSetters);
-        } else {
-            createBuildeeMethods(buildee, mNode, builder, convertedFields);
-        }
-    }
-
-    private static String getBuilderClassName(ClassNode buildee, AnnotationNode anno) {
-        return getMemberStringValue(anno, "builderClassName", buildee.getNameWithoutPackage() + "Initializer");
-    }
-
-    private static void addFields(ClassNode buildee, List<FieldNode> filteredFields, ClassNode builder) {
-        for (FieldNode filteredField : filteredFields) {
-            builder.addField(createFieldCopy(buildee, filteredField));
-        }
-    }
-
-    private void buildCommon(ClassNode buildee, AnnotationNode anno, List<FieldNode> fieldNodes, ClassNode builder) {
-        String prefix = getMemberStringValue(anno, "prefix", "");
-        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "create");
-        createBuilderConstructors(builder, buildee, fieldNodes);
-        buildee.getModule().addClass(builder);
-        String builderMethodName = getMemberStringValue(anno, "builderMethodName", "createInitializer");
-        buildee.addMethod(createBuilderMethod(buildMethodName, builder, fieldNodes.size(), builderMethodName));
-        for (int i = 0; i < fieldNodes.size(); i++) {
-            builder.addMethod(createBuilderMethodForField(builder, fieldNodes, prefix, i));
-        }
-        builder.addMethod(createBuildMethod(builder, buildMethodName, fieldNodes));
-    }
-
-    private static List<FieldNode> convertParamsToFields(ClassNode builder, Parameter[] parameters) {
-        List<FieldNode> fieldNodes = new ArrayList<FieldNode>();
-        for(Parameter parameter: parameters) {
-            Map<String,ClassNode> genericsSpec = createGenericsSpec(builder);
-            ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, parameter.getType());
-            FieldNode fieldNode = new FieldNode(parameter.getName(), parameter.getModifiers(), correctedType, builder, DEFAULT_INITIAL_VALUE);
-            fieldNodes.add(fieldNode);
-            builder.addField(fieldNode);
-        }
-        return fieldNodes;
-    }
-
-    private static ClassNode createInnerHelperClass(ClassNode buildee, String builderClassName, int fieldsSize) {
-        final String fullName = buildee.getName() + "$" + builderClassName;
-        ClassNode builder = new InnerClassNode(buildee, fullName, PUBLIC_STATIC, OBJECT_TYPE);
-        GenericsType[] gtypes = new GenericsType[fieldsSize];
-        for (int i = 0; i < gtypes.length; i++) {
-            gtypes[i] = makePlaceholder(i);
-        }
-        builder.setGenericsTypes(gtypes);
-        return builder;
-    }
-
-    private static MethodNode createBuilderMethod(String buildMethodName, ClassNode builder, int numFields, String builderMethodName) {
-        final BlockStatement body = new BlockStatement();
-        body.addStatement(returnS(callX(builder, buildMethodName)));
-        ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(numFields));
-        return new MethodNode(builderMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
-    }
-
-    private static GenericsType[] unsetGenTypes(int numFields) {
-        GenericsType[] gtypes = new GenericsType[numFields];
-        for (int i = 0; i < gtypes.length; i++) {
-            gtypes[i] = new GenericsType(ClassHelper.make(UNSET.class));
-        }
-        return gtypes;
-    }
-
-    private static GenericsType[] setGenTypes(int numFields) {
-        GenericsType[] gtypes = new GenericsType[numFields];
-        for (int i = 0; i < gtypes.length; i++) {
-            gtypes[i] = new GenericsType(ClassHelper.make(SET.class));
-        }
-        return gtypes;
-    }
-
-    private static void createBuilderConstructors(ClassNode builder, ClassNode buildee, List<FieldNode> fields) {
-        builder.addConstructor(ACC_PRIVATE, NO_PARAMS, NO_EXCEPTIONS, block(ctorSuperS()));
-        final BlockStatement body = new BlockStatement();
-        body.addStatement(ctorSuperS());
-        initializeFields(fields, body, false);
-        builder.addConstructor(ACC_PRIVATE, getParams(fields, buildee), NO_EXCEPTIONS, body);
-    }
-
-    private static void createBuildeeConstructors(BuilderASTTransformation transform, ClassNode buildee, ClassNode builder, List<FieldNode> fields, boolean needsConstructor, boolean useSetters) {
-        ConstructorNode initializer = createInitializerConstructor(buildee, builder, fields);
-        if (transform.hasAnnotation(buildee, ImmutableASTTransformation.MY_TYPE)) {
-            initializer.putNodeMetaData(ImmutableASTTransformation.IMMUTABLE_SAFE_FLAG, Boolean.TRUE);
-        } else if (needsConstructor) {
-            final BlockStatement body = new BlockStatement();
-            body.addStatement(ctorSuperS());
-            initializeFields(fields, body, useSetters);
-            buildee.addConstructor(ACC_PRIVATE | ACC_SYNTHETIC, getParams(fields, buildee), NO_EXCEPTIONS, body);
-        }
-    }
-
-    private static void createBuildeeMethods(ClassNode buildee, MethodNode mNode, ClassNode builder, List<FieldNode> fields) {
-        ClassNode paramType = makeClassSafeWithGenerics(builder, setGenTypes(fields.size()));
-        List<Expression> argsList = new ArrayList<Expression>();
-        Parameter initParam = param(paramType, "initializer");
-        for (FieldNode fieldNode : fields) {
-            argsList.add(propX(varX(initParam), fieldNode.getName()));
-        }
-        String newName = "$" + mNode.getName(); // can't have private and public methods of the same name, so rename original
-        buildee.addMethod(mNode.getName(), PUBLIC_STATIC, mNode.getReturnType(), params(param(paramType, "initializer")), NO_EXCEPTIONS,
-                block(stmt(callX(buildee, newName, args(argsList)))));
-        renameMethod(buildee, mNode, newName);
-    }
-
-    // no rename so delete and add
-    private static void renameMethod(ClassNode buildee, MethodNode mNode, String newName) {
-        buildee.addMethod(newName, mNode.getModifiers(), mNode.getReturnType(), mNode.getParameters(), mNode.getExceptions(), mNode.getCode());
-        buildee.removeMethod(mNode);
-    }
-
-    private static Parameter[] getParams(List<FieldNode> fields, ClassNode cNode) {
-        Parameter[] parameters = new Parameter[fields.size()];
-        for (int i = 0; i < parameters.length; i++) {
-            FieldNode fNode = fields.get(i);
-            Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
-            extractSuperClassGenerics(fNode.getType(), cNode, genericsSpec);
-            ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
-            parameters[i] = new Parameter(correctedType, fNode.getName());
-        }
-        return parameters;
-    }
-
-    private static ConstructorNode createInitializerConstructor(ClassNode buildee, ClassNode builder, List<FieldNode> fields) {
-        ClassNode paramType = makeClassSafeWithGenerics(builder, setGenTypes(fields.size()));
-        List<Expression> argsList = new ArrayList<Expression>();
-        Parameter initParam = param(paramType, "initializer");
-        for (FieldNode fieldNode : fields) {
-            argsList.add(propX(varX(initParam), fieldNode.getName()));
-        }
-        return buildee.addConstructor(ACC_PUBLIC, params(param(paramType, "initializer")), NO_EXCEPTIONS, block(ctorThisS(args(argsList))));
-    }
-
-    private static MethodNode createBuildMethod(ClassNode builder, String buildMethodName, List<FieldNode> fields) {
-        ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(fields.size()));
-        return new MethodNode(buildMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, block(returnS(ctorX(returnType))));
-    }
-
-    private MethodNode createBuilderMethodForField(ClassNode builder, List<FieldNode> fields, String prefix, int fieldPos) {
-        String fieldName = fields.get(fieldPos).getName();
-        String setterName = getSetterName(prefix, fieldName);
-        GenericsType[] gtypes = new GenericsType[fields.size()];
-        List<Expression> argList = new ArrayList<Expression>();
-        for (int i = 0; i < fields.size(); i++) {
-            gtypes[i] = i == fieldPos ? new GenericsType(ClassHelper.make(SET.class)) : makePlaceholder(i);
-            argList.add(i == fieldPos ? propX(varX("this"), constX(fieldName)) : varX(fields.get(i).getName()));
-        }
-        ClassNode returnType = makeClassSafeWithGenerics(builder, gtypes);
-        FieldNode fNode = fields.get(fieldPos);
-        Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
-        extractSuperClassGenerics(fNode.getType(), builder, genericsSpec);
-        ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
-        return new MethodNode(setterName, ACC_PUBLIC, returnType, params(param(correctedType, fieldName)), NO_EXCEPTIONS, block(
-                stmt(assignX(propX(varX("this"), constX(fieldName)), varX(fieldName, correctedType))),
-                returnS(ctorX(returnType, args(argList)))
-        ));
-    }
-
-    private static GenericsType makePlaceholder(int i) {
-        ClassNode type = ClassHelper.makeWithoutCaching("T" + i);
-        type.setRedirect(OBJECT_TYPE);
-        type.setGenericsPlaceHolder(true);
-        return new GenericsType(type);
-    }
-
-    private static FieldNode createFieldCopy(ClassNode buildee, FieldNode fNode) {
-        Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
-        extractSuperClassGenerics(fNode.getType(), buildee, genericsSpec);
-        ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
-        return new FieldNode(fNode.getName(), fNode.getModifiers(), correctedType, buildee, DEFAULT_INITIAL_VALUE);
-    }
-
-    private static List<FieldNode> filterFields(List<FieldNode> fieldNodes, List<String> includes, List<String> excludes, boolean allNames) {
-        List<FieldNode> fields = new ArrayList<FieldNode>();
-        for (FieldNode fNode : fieldNodes) {
-            if (AbstractASTTransformation.shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames)) continue;
-            fields.add(fNode);
-        }
-        return fields;
-    }
-
-    private static void initializeFields(List<FieldNode> fields, BlockStatement body, boolean useSetters) {
-        for (FieldNode field : fields) {
-            String name = field.getName();
-            body.addStatement(
-                    stmt(useSetters && !field.isFinal()
-                                    ? callThisX(getSetterName(name), varX(param(field.getType(), name)))
-                                    : assignX(propX(varX("this"), field.getName()), varX(param(field.getType(), name)))
-                    )
-            );
-        }
-    }
-
-    private static String getSetterName(String name) {
-        return "set" + Verifier.capitalize(name);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/builder/SimpleStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/builder/SimpleStrategy.java b/src/main/groovy/transform/builder/SimpleStrategy.java
deleted file mode 100644
index 7956ac6..0000000
--- a/src/main/groovy/transform/builder/SimpleStrategy.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  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 groovy.transform.builder;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.transform.AbstractASTTransformation;
-import org.codehaus.groovy.transform.BuilderASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.getInstancePropertyFields;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
-import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
-import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
-
-/**
- * This strategy is used with the {@link Builder} AST transform to modify your Groovy objects so that the
- * setter methods for properties return the original object, thus allowing chained usage of the setters.
- *
- * You use it as follows:
- * <pre class="groovyTestCase">
- * import groovy.transform.builder.*
- *
- * {@code @Builder}(builderStrategy=SimpleStrategy)
- * class Person {
- *     String firstName
- *     String lastName
- *     int age
- * }
- * def person = new Person().setFirstName("Robert").setLastName("Lewandowski").setAge(21)
- * assert person.firstName == "Robert"
- * assert person.lastName == "Lewandowski"
- * assert person.age == 21
- * </pre>
- * The {@code prefix} annotation attribute can be used to create setters with a different naming convention, e.g. with the prefix set to the empty String, you would use your setters as follows:
- * <pre>
- * def p1 = new Person().firstName("Robert").lastName("Lewandowski").age(21)
- * </pre>
- * or using a prefix of 'with':
- * <pre>
- * def p2 = new Person().withFirstName("Robert").withLastName("Lewandowski").withAge(21)
- * </pre>
- * When using the default prefix of "set", Groovy's normal setters will be replaced by the chained versions. When using
- * a custom prefix, Groovy's unchained setters will still be available for use in the normal unchained fashion.
- *
- * The 'useSetters' annotation attribute can be used for writable properties as per the {@code Builder} transform documentation.
- * The other annotation attributes for the {@code @Builder} transform for configuring the building process aren't applicable for this strategy.
- *
- * @author Paul King
- */
-public class SimpleStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
-    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
-        if (!(annotatedNode instanceof ClassNode)) {
-            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: building for " +
-                    annotatedNode.getClass().getSimpleName() + " not supported by " + getClass().getSimpleName(), annotatedNode);
-            return;
-        }
-        ClassNode buildee = (ClassNode) annotatedNode;
-        if (unsupportedAttribute(transform, anno, "builderClassName")) return;
-        if (unsupportedAttribute(transform, anno, "buildMethodName")) return;
-        if (unsupportedAttribute(transform, anno, "builderMethodName")) return;
-        if (unsupportedAttribute(transform, anno, "forClass")) return;
-        if (unsupportedAttribute(transform, anno, "includeSuperProperties")) return;
-        if (unsupportedAttribute(transform, anno, "allProperties")) return;
-        boolean useSetters = transform.memberHasValue(anno, "useSetters", true);
-        boolean allNames = transform.memberHasValue(anno, "allNames", true);
-
-        List<String> excludes = new ArrayList<String>();
-        List<String> includes = new ArrayList<String>();
-        includes.add(Undefined.STRING);
-        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
-        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
-        String prefix = getMemberStringValue(anno, "prefix", "set");
-        List<FieldNode> fields = getFields(transform, anno, buildee);
-        if (includes != null) {
-            for (String name : includes) {
-                checkKnownField(transform, anno, name, fields);
-            }
-        }
-        for (FieldNode field : fields) {
-            String fieldName = field.getName();
-            if (!AbstractASTTransformation.shouldSkipUndefinedAware(fieldName, excludes, includes, allNames)) {
-                String methodName = getSetterName(prefix, fieldName);
-                Parameter parameter = param(field.getType(), fieldName);
-                buildee.addMethod(methodName, Opcodes.ACC_PUBLIC, newClass(buildee), params(parameter), NO_EXCEPTIONS, block(
-                                stmt(useSetters && !field.isFinal()
-                                                ? callThisX(getSetterName("set", fieldName), varX(parameter))
-                                                : assignX(fieldX(field), varX(parameter))
-                                ),
-                                returnS(varX("this")))
-                );
-            }
-        }
-    }
-
-    @Override
-    protected List<FieldNode> getFields(BuilderASTTransformation transform, AnnotationNode anno, ClassNode buildee) {
-        return getInstancePropertyFields(buildee);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/ClosureParams.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/ClosureParams.java b/src/main/groovy/transform/stc/ClosureParams.java
deleted file mode 100644
index e788d44..0000000
--- a/src/main/groovy/transform/stc/ClosureParams.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Parameter annotation aimed at helping IDEs or the static type checker to infer the
- * parameter types of a closure. Without this annotation, a method signature may look like
- * this:<p>
- * <code>public &lt;T,R&gt; List&lt;R&gt; doSomething(List&lt;T&gt; source, Closure&lt;R&gt; consumer)</code>
- * <p>
- * <p>The problem this annotation tries to solve is to define the expected parameter types of the
- * <i>consumer</i> closure. The generics type defined in <code>Closure&lt;R&gt;</code> correspond to the
- * result type of the closure, but tell nothing about what the closure must accept as arguments.</p>
- * <p></p>
- * <p>There's no way in Java or Groovy to express the type signature of the expected closure call method from
- * outside the closure itself, so we rely on an annotation here. Unfortunately, annotations also have limitations
- * (like not being able to use generics placeholder as annotation values) that prevent us from expressing the
- * type directly.</p>
- * <p>Additionally, closures are polymorphic. This means that a single closure can be used with different, valid,
- * parameter signatures. A typical use case can be found when a closure accepts either a {@link java.util.Map.Entry}
- * or a (key,value) pair, like the {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#each(java.util.Map, groovy.lang.Closure)}
- * method.</p>
- * <p>For those reasons, the {@link ClosureParams} annotation takes these arguments:
- * <ul>
- *     <li>{@link ClosureParams#value()} defines a {@link groovy.transform.stc.ClosureSignatureHint} hint class
- *     that the compiler will use to infer the parameter types</li>
- *     <li>{@link ClosureParams#conflictResolutionStrategy()} defines a {@link groovy.transform.stc.ClosureSignatureConflictResolver} resolver
- *     class that the compiler will use to potentially reduce ambiguities remaining after initial inference calculations</li>
- *     <li>{@link ClosureParams#options()}, a set of options that are passed to the hint when the type is inferred (and also available to the resolver)</li>
- * </ul>
- * </p>
- * <p>As a result, the previous signature can be written like this:</p>
- * <code>public &lt;T,R&gt; List&lt;R&gt; doSomething(List&lt;T&gt; source, @ClosureParams(FirstParam.FirstGenericType.class) Closure&lt;R&gt; consumer)</code>
- * <p>Which uses the {@link FirstParam.FirstGenericType} first generic type of the first argument</p> hint to tell that the only expected
- * argument type corresponds to the type of the first generic argument type of the first method parameter.
- */
-@Target(ElementType.PARAMETER)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ClosureParams {
-    Class<? extends ClosureSignatureHint> value();
-    Class<? extends ClosureSignatureConflictResolver> conflictResolutionStrategy() default ClosureSignatureConflictResolver.class;
-    String[] options() default {};
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/ClosureSignatureConflictResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/ClosureSignatureConflictResolver.java b/src/main/groovy/transform/stc/ClosureSignatureConflictResolver.java
deleted file mode 100644
index d727958..0000000
--- a/src/main/groovy/transform/stc/ClosureSignatureConflictResolver.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.List;
-
-/**
- * If multiple candidate signatures are found after applying type hints,
- * a conflict resolver can attempt to resolve the ambiguity.
- *
- * @since 2.5.0
- */
-public class ClosureSignatureConflictResolver {
-    /**
-     *
-     * @param candidates the list of signatures as determined after applying type hints and performing initial inference calculations
-     * @param receiver the receiver the method is being called on
-     * @param arguments the arguments for the closure
-     * @param closure the closure expression under analysis
-     * @param methodNode the method for which a {@link groovy.lang.Closure} parameter was annotated with {@link ClosureParams}
-     * @param sourceUnit the source unit of the file being compiled
-     * @param compilationUnit the compilation unit of the file being compiled
-     * @param options the options, corresponding to the {@link ClosureParams#options()} found on the annotation
-     * @return a non-null list of signatures, where a signature corresponds to an array of class nodes, each of them matching a parameter. A list with more than one element indicates that all ambiguities haven't yet been resolved.
-     */
-    public List<ClassNode[]> resolve(List<ClassNode[]> candidates, ClassNode receiver, Expression arguments, ClosureExpression closure,
-                                     MethodNode methodNode, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options) {
-        // do nothing by default
-        return candidates;
-    }
-}


[44/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/DefaultPropertyWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/DefaultPropertyWriter.java b/src/main/groovy/beans/DefaultPropertyWriter.java
deleted file mode 100644
index 12ac7db..0000000
--- a/src/main/groovy/beans/DefaultPropertyWriter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * @author Andres Almiray
- */
-public class DefaultPropertyWriter implements PropertyWriter {
-    public static final PropertyWriter INSTANCE = new DefaultPropertyWriter();
-
-    public void write(Object owner, String propertyName, Object value) {
-        InvokerHelper.setProperty(owner, propertyName, value);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/ListenerList.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/ListenerList.groovy b/src/main/groovy/beans/ListenerList.groovy
deleted file mode 100644
index b8119f1..0000000
--- a/src/main/groovy/beans/ListenerList.groovy
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  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 groovy.beans
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.Documented
-import java.lang.annotation.ElementType
-import java.lang.annotation.Retention
-import java.lang.annotation.RetentionPolicy
-import java.lang.annotation.Target
-
-/**
- * This annotation adds Java-style listener support to a class based on an annotated Collection-property.
- * <p>
- * For any given Collection property, several methods will be written into the enclosing class during the compile phase. These
- * changes are visible from Java or other languages. The List is intended to hold listeners of some sort, and the methods
- * addListener, removeListener, and getListeners are all added to the class. The actual methods names depend on the generic
- * type of the collection.
- * <p>
- * Given the following example:<br>
- * <pre>
- * class MyClass {
- *     &#064;groovy.beans.ListenerList
- *     List&lt;java.awt.event.ActionListener&gt; listeners
- * }
- * </pre>
- * The following code is generated:
- * <pre>
- * public class MyClass extends java.lang.Object {
- *     &#064;groovy.beans.ListenerList
- *     private java.util.List&lt;java.awt.event.ActionListener&gt; listeners
- *
- *     public void addActionListener(java.awt.event.ActionListener listener) {
- *         if ( listener == null) {
- *             return null
- *         }
- *         if ( listeners == null) {
- *             listeners = []
- *         }
- *         listeners.add(listener)
- *     }
- *
- *     public void removeActionListener(java.awt.event.ActionListener listener) {
- *         if ( listener == null) {
- *             return null
- *         }
- *         if ( listeners == null) {
- *             listeners = []
- *         }
- *         listeners.remove(listener)
- *     }
- *
- *     public java.awt.event.ActionListener[] getActionListeners() {
- *         java.lang.Object __result = []
- *         if ( listeners != null) {
- *             __result.addAll(listeners)
- *         }
- *         return (( __result ) as java.awt.event.ActionListener[])
- *     }
- *
- *     public void fireActionPerformed(java.awt.event.ActionEvent param0) {
- *         if ( listeners != null) {
- *             def __list = new java.util.ArrayList(listeners)
- *             for (java.lang.Object listener : __list ) {
- *                 listener.actionPerformed(param0)
- *             }
- *         }
- *     }
- * }
- * </pre>
- * A fire method is created for each public method in the target class. In this case, ActionListener only has one
- * method. For a four method interface, four fire methods would be created.
- * <p>
- * The annotation can take the following parameters:
- * <pre>
- * name        = a suffix for creating the add, remove, and get methods.
- *               Default: Name of the listener type
- *               In the above example, if name is set to MyListener, then the class will have an addMyListener,
- *               removeMyListener, and getMyListeners methods. 
- *
- * synchronize = Whether or not the methods created should be synchronized at the method level. 
- *               Default: false
- * </pre>
- * <p>
- * <strong>Compilation Errors</strong> - Using this annotation incorrectly results in compilation errors rather
- * than runtime errors. A list of potential problems includes:
- * <ul>
- * <li>This annotation can only be applied to a field of type Collection</li>
- * <li>The annotated Collection field must have a generic type</li>
- * <li>The annotated Collection field must not have a generic wildcard declared</li>
- * <li>The generated methods must not already exist</li>
- * </ul>
- *
- * @see ListenerListASTTransformation
- * @author Alexander Klein
- * @author Hamlet D'Arcy
- */
-@Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target(ElementType.FIELD)
-@GroovyASTTransformationClass('groovy.beans.ListenerListASTTransformation')
-@interface ListenerList {
-    /**
-     * A suffix for creating the add, remove, and get methods
-     * defaulting to the name of the listener type, e.g. if name is set to MyListener,
-     * then the class will have addMyListener, removeMyListener, and getMyListeners methods.
-     */
-    String name() default ""
-
-    /**
-     * Whether or not the methods created should be synchronized at the method level.
-     */
-    boolean synchronize() default false
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/ListenerListASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/ListenerListASTTransformation.groovy b/src/main/groovy/beans/ListenerListASTTransformation.groovy
deleted file mode 100644
index 1d7fbf7..0000000
--- a/src/main/groovy/beans/ListenerListASTTransformation.groovy
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- *  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 groovy.beans
-
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotatedNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.FieldNode
-import org.codehaus.groovy.ast.GenericsType
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.VariableScope
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
-import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.expr.CastExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.expr.ConstructorCallExpression
-import org.codehaus.groovy.ast.expr.DeclarationExpression
-import org.codehaus.groovy.ast.expr.ListExpression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.EmptyStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
-import org.codehaus.groovy.ast.stmt.ForStatement
-import org.codehaus.groovy.ast.stmt.IfStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage
-import org.codehaus.groovy.syntax.SyntaxException
-import org.codehaus.groovy.syntax.Token
-import org.codehaus.groovy.syntax.Types
-import org.codehaus.groovy.transform.ASTTransformation
-import org.codehaus.groovy.transform.GroovyASTTransformation
-import org.objectweb.asm.Opcodes
-
-/**
- * Handles generation of code for the {@code @ListenerList} annotation.
- * <p>
- * Generally, it adds the needed add&lt;Listener&gt;, remove&lt;Listener&gt; and
- * get&lt;Listener&gt;s methods to support the Java Beans API.
- * <p>
- * Additionally it adds corresponding fire&lt;Event&gt; methods.
- * <p>
- *
- * @author Alexander Klein
- * @author Hamlet D'Arcy
- */
-@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
-class ListenerListASTTransformation implements ASTTransformation, Opcodes {
-    private static final Class MY_CLASS = groovy.beans.ListenerList.class
-    private static final ClassNode COLLECTION_TYPE = ClassHelper.make(Collection)
-
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
-            throw new RuntimeException("Internal error: wrong types: ${node.class} / ${parent.class}")
-        }
-        AnnotationNode node = nodes[0]
-        FieldNode field = nodes[1]
-        ClassNode declaringClass = nodes[1].declaringClass
-        ClassNode parentClass = field.type
-
-        boolean isCollection = parentClass.isDerivedFrom(COLLECTION_TYPE) || parentClass.implementsInterface(COLLECTION_TYPE)
-
-        if (!isCollection) {
-            addError(node, source, '@' + MY_CLASS.name + ' can only annotate collection properties.')
-            return
-        }
-
-        def types = field.type.genericsTypes
-        if (!types) {
-            addError(node, source, '@' + MY_CLASS.name + ' fields must have a generic type.')
-            return
-        }
-
-        if (types[0].wildcard) {
-            addError(node, source, '@' + MY_CLASS.name + ' fields with generic wildcards not yet supported.')
-            return
-        }
-
-        def listener = types[0].type
-
-        if (!field.initialValueExpression) {
-            field.initialValueExpression = new ListExpression()
-        }
-
-        def name = node.getMember('name')?.value ?: listener.nameWithoutPackage
-
-        def fireList = listener.methods.findAll { MethodNode m ->
-            m.isPublic() && !m.isSynthetic() && !m.isStatic()
-        }
-
-        def synchronize = node.getMember('synchronize')?.value ?: false
-        addAddListener(source, node, declaringClass, field, listener, name, synchronize)
-        addRemoveListener(source, node, declaringClass, field, listener, name, synchronize)
-        addGetListeners(source, node, declaringClass, field, listener, name, synchronize)
-
-        fireList.each { MethodNode method ->
-            addFireMethods(source, node, declaringClass, field, types, synchronize, method)
-        }
-    }
-
-    private static def addError(AnnotationNode node, SourceUnit source, String message) {
-        source.errorCollector.addError(
-                new SyntaxErrorMessage(new SyntaxException(
-                        message,
-                        node.lineNumber,
-                        node.columnNumber),
-                        source))
-    }
-
-    /**
-     * Adds the add&lt;Listener&gt; method like:
-     * <pre>
-     * synchronized void add${name.capitalize}(${listener.name} listener) {
-     *     if (listener == null)
-     *         return
-     *     if (${field.name} == null)
-     *        ${field.name} = []
-     *     ${field.name}.add(listener)
-     * }
-     * </pre>
-     */
-    void addAddListener(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
-
-        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
-        def methodReturnType = ClassHelper.make(Void.TYPE)
-        def methodName = "add${name.capitalize()}"
-        def cn = ClassHelper.makeWithoutCaching(listener.name)
-        cn.redirect = listener
-        def methodParameter = [new Parameter(cn,'listener')] as Parameter[]
-
-        if (declaringClass.hasMethod(methodName, methodParameter)) {
-            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
-            return
-        }
-
-        BlockStatement block = new BlockStatement()
-        block.addStatements([
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression('listener'),
-                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new ReturnStatement(ConstantExpression.NULL),
-                        EmptyStatement.INSTANCE
-                ),
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new ExpressionStatement(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.EQUAL, 0, 0),
-                                        new ListExpression()
-                                )
-                        ),
-                        EmptyStatement.INSTANCE
-                ),
-                new ExpressionStatement(
-                        new MethodCallExpression(new VariableExpression(field.name), new ConstantExpression('add'), new ArgumentListExpression(new VariableExpression('listener')))
-                )
-        ])
-        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
-    }
-
-    /**
-     * Adds the remove<Listener> method like:
-     * <pre>
-     * synchronized void remove${name.capitalize}(${listener.name} listener) {
-     *     if (listener == null)
-     *         return
-     *     if (${field.name} == null)
-     *         ${field.name} = []
-     *     ${field.name}.remove(listener)
-     * }
-     * </pre>
-     */
-    void addRemoveListener(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
-        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
-        def methodReturnType = ClassHelper.make(Void.TYPE)
-        def methodName = "remove${name.capitalize()}"
-        def cn = ClassHelper.makeWithoutCaching(listener.name)
-        cn.redirect = listener
-        def methodParameter = [new Parameter(cn,'listener')] as Parameter[]
-
-        if (declaringClass.hasMethod(methodName, methodParameter)) {
-            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
-            return
-        }
-
-        BlockStatement block = new BlockStatement()
-        block.addStatements([
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression('listener'),
-                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new ReturnStatement(ConstantExpression.NULL),
-                        EmptyStatement.INSTANCE
-                ),
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new ExpressionStatement(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.EQUAL, 0, 0),
-                                        new ListExpression()
-                                )
-                        ),
-                        EmptyStatement.INSTANCE
-                ),
-                new ExpressionStatement(
-                        new MethodCallExpression(new VariableExpression(field.name), new ConstantExpression('remove'), new ArgumentListExpression(new VariableExpression("listener")))
-                )
-        ])
-        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
-    }
-
-    /**
-     * Adds the get&lt;Listener&gt;s method like:
-     * <pre>
-     * synchronized ${name.capitalize}[] get${name.capitalize}s() {
-     *     def __result = []
-     *     if (${field.name} != null)
-     *         __result.addAll(${field.name})
-     *     return __result as ${name.capitalize}[]
-     * }
-     * </pre>
-     */
-    void addGetListeners(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
-        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
-        def methodReturnType = listener.makeArray()
-        def methodName = "get${name.capitalize()}s"
-        def methodParameter = [] as Parameter[]
-
-        if (declaringClass.hasMethod(methodName, methodParameter)) {
-            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
-            return
-        }
-
-        BlockStatement block = new BlockStatement()
-        block.addStatements([
-                new ExpressionStatement(
-                        new DeclarationExpression(
-                                new VariableExpression("__result", ClassHelper.DYNAMIC_TYPE),
-                                Token.newSymbol(Types.EQUALS, 0, 0),
-                                new ListExpression()
-                        )),
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.COMPARE_NOT_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new ExpressionStatement(
-                                new MethodCallExpression(new VariableExpression('__result'), new ConstantExpression('addAll'), new ArgumentListExpression(new VariableExpression(field.name)))
-                        ),
-                        EmptyStatement.INSTANCE
-                ),
-                new ReturnStatement(
-                        new CastExpression(
-                                methodReturnType,
-                                new VariableExpression('__result')
-                        )
-                )
-        ])
-        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
-    }
-
-    /**
-     * Adds the fire&lt;Event&gt; methods like:
-     * <pre>
-     * void fire${fireMethod.capitalize()}(${parameterList.join(', ')}) {
-     *     if (${field.name} != null) {
-     *         def __list = new ArrayList(${field.name})
-     *         __list.each { listener ->
-     *             listener.$eventMethod(${evt})
-     *         }
-     *     }
-     * }
-     * </pre>
-     */
-    void addFireMethods(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, GenericsType[] types, boolean synchronize, MethodNode method) {
-
-        def methodReturnType = ClassHelper.make(Void.TYPE)
-        def methodName = "fire${method.name.capitalize()}"
-        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
-
-        if (declaringClass.hasMethod(methodName, method.parameters)) {
-            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
-            return
-        }
-
-        def args = new ArgumentListExpression(method.parameters)
-
-        BlockStatement block = new BlockStatement()
-        def listenerListType = ClassHelper.make(ArrayList).plainNodeReference
-        listenerListType.setGenericsTypes(types)
-        block.addStatements([
-                new IfStatement(
-                        new BooleanExpression(
-                                new BinaryExpression(
-                                        new VariableExpression(field.name),
-                                        Token.newSymbol(Types.COMPARE_NOT_EQUAL, 0, 0),
-                                        ConstantExpression.NULL
-                                )
-                        ),
-                        new BlockStatement([
-                                new ExpressionStatement(
-                                        new DeclarationExpression(
-                                                new VariableExpression('__list', listenerListType),
-                                                Token.newSymbol(Types.EQUALS, 0, 0),
-                                                new ConstructorCallExpression(listenerListType, new ArgumentListExpression(
-                                                        new VariableExpression(field.name)
-                                                ))
-                                        )
-                                ),
-                                new ForStatement(
-                                        new Parameter(ClassHelper.DYNAMIC_TYPE, 'listener'),
-                                        new VariableExpression('__list'),
-                                        new BlockStatement([
-                                                new ExpressionStatement(
-                                                        new MethodCallExpression(
-                                                                new VariableExpression('listener'),
-                                                                method.name,
-                                                                args
-                                                        )
-                                                )
-                                        ], new VariableScope())
-                                )
-                        ], new VariableScope()),
-                        EmptyStatement.INSTANCE
-                )
-        ])
-
-        def params = method.parameters.collect {
-            def paramType = ClassHelper.getWrapper(it.type)
-            def cn = paramType.plainNodeReference
-            cn.setRedirect(paramType)
-            new Parameter(cn, it.name)
-        }
-        declaringClass.addMethod(methodName, methodModifiers, methodReturnType, params as Parameter[], [] as ClassNode[], block)
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/PropertyAccessor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/PropertyAccessor.java b/src/main/groovy/beans/PropertyAccessor.java
deleted file mode 100644
index 822ab10..0000000
--- a/src/main/groovy/beans/PropertyAccessor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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 groovy.beans;
-
-/**
- * @author Andres Almiray
- */
-public interface PropertyAccessor extends PropertyReader, PropertyWriter {
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/PropertyReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/PropertyReader.java b/src/main/groovy/beans/PropertyReader.java
deleted file mode 100644
index 4ef13af..0000000
--- a/src/main/groovy/beans/PropertyReader.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  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 groovy.beans;
-
-/**
- * @author Andres Almiray
- */
-public interface PropertyReader {
-    Object read(Object owner, String propertyName);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/PropertyWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/PropertyWriter.java b/src/main/groovy/beans/PropertyWriter.java
deleted file mode 100644
index 5b9e1ce..0000000
--- a/src/main/groovy/beans/PropertyWriter.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  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 groovy.beans;
-
-/**
- * @author Andres Almiray
- */
-public interface PropertyWriter {
-    void write(Object owner, String propertyName, Object value);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/Vetoable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/Vetoable.java b/src/main/groovy/beans/Vetoable.java
deleted file mode 100644
index 5b40e1a..0000000
--- a/src/main/groovy/beans/Vetoable.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotates a groovy property or a class.
- * <p>
- * When annotating a property it indicates that the property should be a
- * constrained property according to the JavaBeans spec, subject to
- * listeners vetoing the property change.
- * <p>
- * When annotating a class it indicates that all groovy properties in that
- * class should be bound as though each property had the annotation (even
- * if it already has it explicitly).
- * <p>
- * It is a compilation error to place this annotation on a field (that is
- * not a property, i.e. has scope visibility modifiers).
- * <p>
- * If a property with a user defined setter method is annotated the code
- * block is wrapped with the needed code to fire off the event.
- * <p>
- * Here is a simple example of how to annotate a class with Vetoable: 
- * <pre>
- * &#064;groovy.beans.Vetoable
- * class Person {
- *     String firstName
- *     def zipCode
- * }
- * </pre>
- * This code is transformed by the compiler into something resembling the following
- * snippet. Notice the difference between a String and a def/Object property: 
- * <pre>
- * public class Person implements groovy.lang.GroovyObject { 
- *     private java.lang.String firstName
- *     private java.lang.Object zipCode 
- *     final private java.beans.VetoableChangeSupport this$vetoableChangeSupport 
- * 
- *     public Person() {
- *         this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)
- *     }
- * 
- *     public void addVetoableChangeListener(java.beans.VetoableChangeListener listener) {
- *         this$vetoableChangeSupport.addVetoableChangeListener(listener)
- *     }
- * 
- *     public void addVetoableChangeListener(java.lang.String name, java.beans.VetoableChangeListener listener) {
- *         this$vetoableChangeSupport.addVetoableChangeListener(name, listener)
- *     }
- * 
- *     public void removeVetoableChangeListener(java.beans.VetoableChangeListener listener) {
- *         this$vetoableChangeSupport.removeVetoableChangeListener(listener)
- *     }
- * 
- *     public void removeVetoableChangeListener(java.lang.String name, java.beans.VetoableChangeListener listener) {
- *         this$vetoableChangeSupport.removeVetoableChangeListener(name, listener)
- *     }
- * 
- *     public void fireVetoableChange(java.lang.String name, java.lang.Object oldValue, java.lang.Object newValue) throws java.beans.PropertyVetoException {
- *         this$vetoableChangeSupport.fireVetoableChange(name, oldValue, newValue)
- *     }
- * 
- *     public java.beans.VetoableChangeListener[] getVetoableChangeListeners() {
- *         return this$vetoableChangeSupport.getVetoableChangeListeners()
- *     }
- * 
- *     public java.beans.VetoableChangeListener[] getVetoableChangeListeners(java.lang.String name) {
- *         return this$vetoableChangeSupport.getVetoableChangeListeners(name)
- *     }
- * 
- *     public void setFirstName(java.lang.String value) throws java.beans.PropertyVetoException {
- *         this.fireVetoableChange('firstName', firstName, value)
- *         firstName = value 
- *     }
- * 
- *     public void setZipCode(java.lang.Object value) throws java.beans.PropertyVetoException {
- *         this.fireVetoableChange('zipCode', zipCode, value)
- *         zipCode = value 
- *     }
- * }
- * </pre>
- *
- * @see VetoableASTTransformation
- * @author Danno Ferrin (shemnon)
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.FIELD, ElementType.TYPE})
-@GroovyASTTransformationClass("groovy.beans.VetoableASTTransformation")
-public @interface Vetoable {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/VetoableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/VetoableASTTransformation.java b/src/main/groovy/beans/VetoableASTTransformation.java
deleted file mode 100644
index d7353fd..0000000
--- a/src/main/groovy/beans/VetoableASTTransformation.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.PropertyNode;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.tools.PropertyNodeUtils;
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.messages.SimpleMessage;
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.syntax.SyntaxException;
-import org.codehaus.groovy.transform.GroovyASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.beans.PropertyVetoException;
-import java.beans.VetoableChangeListener;
-import java.beans.VetoableChangeSupport;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-
-/**
- * Handles generation of code for the {@code @Vetoable} annotation, and {@code @Bindable}
- * if also present.
- * <p>
- * Generally, it adds (if needed) a VetoableChangeSupport field and
- * the needed add/removeVetoableChangeListener methods to support the
- * listeners.
- * <p>
- * It also generates the setter and wires the setter through the
- * VetoableChangeSupport.
- * <p>
- * If a {@link Bindable} annotation is detected it also adds support similar
- * to what {@link BindableASTTransformation} would do.
- *
- * @author Danno Ferrin (shemnon)
- * @author Chris Reeves
- */
-@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
-public class VetoableASTTransformation extends BindableASTTransformation {
-
-    protected static ClassNode constrainedClassNode = ClassHelper.make(Vetoable.class);
-
-    /**
-     * Convenience method to see if an annotated node is {@code @Vetoable}.
-     *
-     * @param node the node to check
-     * @return true if the node is constrained
-     */
-    public static boolean hasVetoableAnnotation(AnnotatedNode node) {
-        for (AnnotationNode annotation : node.getAnnotations()) {
-            if (constrainedClassNode.equals(annotation.getClassNode())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Handles the bulk of the processing, mostly delegating to other methods.
-     *
-     * @param nodes   the AST nodes
-     * @param source  the source unit for the nodes
-     */
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
-            throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
-        }
-        AnnotationNode node = (AnnotationNode) nodes[0];
-
-        if (nodes[1] instanceof ClassNode) {
-            addListenerToClass(source, (ClassNode) nodes[1]);
-        } else {
-            if ((((FieldNode)nodes[1]).getModifiers() & Opcodes.ACC_FINAL) != 0) {
-                source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                        new SyntaxException("@groovy.beans.Vetoable cannot annotate a final property.",
-                                node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                        source));
-            }
-
-            addListenerToProperty(source, node, (AnnotatedNode) nodes[1]);
-        }
-    }
-
-    private void addListenerToProperty(SourceUnit source, AnnotationNode node, AnnotatedNode parent) {
-        ClassNode declaringClass = parent.getDeclaringClass();
-        FieldNode field = ((FieldNode) parent);
-        String fieldName = field.getName();
-        for (PropertyNode propertyNode : declaringClass.getProperties()) {
-            boolean bindable = BindableASTTransformation.hasBindableAnnotation(parent)
-                    || BindableASTTransformation.hasBindableAnnotation(parent.getDeclaringClass());
-
-            if (propertyNode.getName().equals(fieldName)) {
-                if (field.isStatic()) {
-                    //noinspection ThrowableInstanceNeverThrown
-                    source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                            new SyntaxException("@groovy.beans.Vetoable cannot annotate a static property.",
-                                    node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                            source));
-                } else {
-                    createListenerSetter(source, bindable, declaringClass, propertyNode);
-                }
-                return;
-            }
-        }
-        //noinspection ThrowableInstanceNeverThrown
-        source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                new SyntaxException("@groovy.beans.Vetoable must be on a property, not a field.  Try removing the private, protected, or public modifier.",
-                        node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                source));
-    }
-
-
-    private void addListenerToClass(SourceUnit source, ClassNode classNode) {
-        boolean bindable = BindableASTTransformation.hasBindableAnnotation(classNode);
-        for (PropertyNode propertyNode : classNode.getProperties()) {
-            if (!hasVetoableAnnotation(propertyNode.getField())
-                && !propertyNode.getField().isFinal()
-                && !propertyNode.getField().isStatic())
-            {
-                createListenerSetter(source,
-                        bindable || BindableASTTransformation.hasBindableAnnotation(propertyNode.getField()),
-                    classNode, propertyNode);
-            }
-        }
-    }
-
-    /**
-     * Wrap an existing setter.
-     */
-    private static void wrapSetterMethod(ClassNode classNode, boolean bindable, String propertyName) {
-        String getterName = "get" + MetaClassHelper.capitalize(propertyName);
-        MethodNode setter = classNode.getSetterMethod("set" + MetaClassHelper.capitalize(propertyName));
-
-        if (setter != null) {
-            // Get the existing code block
-            Statement code = setter.getCode();
-
-            Expression oldValue = varX("$oldValue");
-            Expression newValue = varX("$newValue");
-            Expression proposedValue = varX(setter.getParameters()[0].getName());
-            BlockStatement block = new BlockStatement();
-
-            // create a local variable to hold the old value from the getter
-            block.addStatement(declS(oldValue, callThisX(getterName)));
-
-            // add the fireVetoableChange method call
-            block.addStatement(stmt(callThisX("fireVetoableChange", args(
-                    constX(propertyName), oldValue, proposedValue))));
-
-            // call the existing block, which will presumably set the value properly
-            block.addStatement(code);
-
-            if (bindable) {
-                // get the new value to emit in the event
-                block.addStatement(declS(newValue, callThisX(getterName)));
-
-                // add the firePropertyChange method call
-                block.addStatement(stmt(callThisX("firePropertyChange", args(constX(propertyName), oldValue, newValue))));
-            }
-
-            // replace the existing code block with our new one
-            setter.setCode(block);
-        }
-    }
-
-    private void createListenerSetter(SourceUnit source, boolean bindable, ClassNode declaringClass, PropertyNode propertyNode) {
-        if (bindable && needsPropertyChangeSupport(declaringClass, source)) {
-            addPropertyChangeSupport(declaringClass);
-        }
-        if (needsVetoableChangeSupport(declaringClass, source)) {
-            addVetoableChangeSupport(declaringClass);
-        }
-        String setterName = "set" + MetaClassHelper.capitalize(propertyNode.getName());
-        if (declaringClass.getMethods(setterName).isEmpty()) {
-            Expression fieldExpression = fieldX(propertyNode.getField());
-            BlockStatement setterBlock = new BlockStatement();
-            setterBlock.addStatement(createConstrainedStatement(propertyNode, fieldExpression));
-            if (bindable) {
-                setterBlock.addStatement(createBindableStatement(propertyNode, fieldExpression));
-            } else {
-                setterBlock.addStatement(createSetStatement(fieldExpression));
-            }
-
-            // create method void <setter>(<type> fieldName)
-            createSetterMethod(declaringClass, propertyNode, setterName, setterBlock);
-        } else {
-            wrapSetterMethod(declaringClass, bindable, propertyNode.getName());
-        }
-    }
-
-    /**
-     * Creates a statement body similar to:
-     * <code>this.fireVetoableChange("field", field, field = value)</code>
-     *
-     * @param propertyNode           the field node for the property
-     * @param fieldExpression a field expression for setting the property value
-     * @return the created statement
-     */
-    protected Statement createConstrainedStatement(PropertyNode propertyNode, Expression fieldExpression) {
-        return stmt(callThisX("fireVetoableChange", args(constX(propertyNode.getName()), fieldExpression, varX("value"))));
-    }
-
-    /**
-     * Creates a statement body similar to:
-     * <code>field = value</code>.
-     * <p>
-     * Used when the field is not also {@code @Bindable}.
-     *
-     * @param fieldExpression a field expression for setting the property value
-     * @return the created statement
-     */
-    protected Statement createSetStatement(Expression fieldExpression) {
-        return assignS(fieldExpression, varX("value"));
-    }
-
-    /**
-     * Snoops through the declaring class and all parents looking for a field
-     * of type VetoableChangeSupport.  Remembers the field and returns false
-     * if found otherwise returns true to indicate that such support should
-     * be added.
-     *
-     * @param declaringClass the class to search
-     * @return true if vetoable change support should be added
-     */
-    protected boolean needsVetoableChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) {
-        boolean foundAdd = false, foundRemove = false, foundFire = false;
-        ClassNode consideredClass = declaringClass;
-        while (consideredClass!= null) {
-            for (MethodNode method : consideredClass.getMethods()) {
-                // just check length, MOP will match it up
-                foundAdd = foundAdd || method.getName().equals("addVetoableChangeListener") && method.getParameters().length == 1;
-                foundRemove = foundRemove || method.getName().equals("removeVetoableChangeListener") && method.getParameters().length == 1;
-                foundFire = foundFire || method.getName().equals("fireVetoableChange") && method.getParameters().length == 3;
-                if (foundAdd && foundRemove && foundFire) {
-                    return false;
-                }
-            }
-            consideredClass = consideredClass.getSuperClass();
-        }
-        // check if a super class has @Vetoable annotations
-        consideredClass = declaringClass.getSuperClass();
-        while (consideredClass!=null) {
-            if (hasVetoableAnnotation(consideredClass)) return false;
-            for (FieldNode field : consideredClass.getFields()) {
-                if (hasVetoableAnnotation(field)) return false;
-            }
-            consideredClass = consideredClass.getSuperClass();
-        }
-        if (foundAdd || foundRemove || foundFire) {
-            sourceUnit.getErrorCollector().addErrorAndContinue(
-                new SimpleMessage("@Vetoable cannot be processed on "
-                    + declaringClass.getName()
-                    + " because some but not all of addVetoableChangeListener, removeVetoableChange, and fireVetoableChange were declared in the current or super classes.",
-                sourceUnit)
-            );
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Creates a setter method with the given body.
-     * <p>
-     * This differs from normal setters in that we need to add a declared
-     * exception java.beans.PropertyVetoException
-     *
-     * @param declaringClass the class to which we will add the setter
-     * @param propertyNode          the field to back the setter
-     * @param setterName     the name of the setter
-     * @param setterBlock    the statement representing the setter block
-     */
-    protected void createSetterMethod(ClassNode declaringClass, PropertyNode propertyNode, String setterName, Statement setterBlock) {
-        ClassNode[] exceptions = {ClassHelper.make(PropertyVetoException.class)};
-        MethodNode setter = new MethodNode(
-                setterName,
-                PropertyNodeUtils.adjustPropertyModifiersForMethod(propertyNode),
-                ClassHelper.VOID_TYPE,
-                params(param(propertyNode.getType(), "value")),
-                exceptions,
-                setterBlock);
-        setter.setSynthetic(true);
-        // add it to the class
-        declaringClass.addMethod(setter);
-    }
-
-    /**
-     * Adds the necessary field and methods to support vetoable change support.
-     * <p>
-     * Adds a new field:
-     * <code>"protected final java.beans.VetoableChangeSupport this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)"</code>
-     * <p>
-     * Also adds support methods:
-     * <code>public void addVetoableChangeListener(java.beans.VetoableChangeListener)</code>
-     * <code>public void addVetoableChangeListener(String, java.beans.VetoableChangeListener)</code>
-     * <code>public void removeVetoableChangeListener(java.beans.VetoableChangeListener)</code>
-     * <code>public void removeVetoableChangeListener(String, java.beans.VetoableChangeListener)</code>
-     * <code>public java.beans.VetoableChangeListener[] getVetoableChangeListeners()</code>
-     *
-     * @param declaringClass the class to which we add the support field and methods
-     */
-    protected void addVetoableChangeSupport(ClassNode declaringClass) {
-        ClassNode vcsClassNode = ClassHelper.make(VetoableChangeSupport.class);
-        ClassNode vclClassNode = ClassHelper.make(VetoableChangeListener.class);
-
-        // add field:
-        // protected static VetoableChangeSupport this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)
-        FieldNode vcsField = declaringClass.addField(
-                "this$vetoableChangeSupport",
-                ACC_FINAL | ACC_PRIVATE | ACC_SYNTHETIC,
-                vcsClassNode,
-                ctorX(vcsClassNode, args(varX("this"))));
-
-        // add method:
-        // void addVetoableChangeListener(listener) {
-        //     this$vetoableChangeSupport.addVetoableChangeListener(listener)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "addVetoableChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(vclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(vcsField), "addVetoableChangeListener", args(varX("listener", vclClassNode))))));
-
-        // add method:
-        // void addVetoableChangeListener(name, listener) {
-        //     this$vetoableChangeSupport.addVetoableChangeListener(name, listener)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "addVetoableChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(vclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(vcsField), "addVetoableChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", vclClassNode))))));
-
-        // add method:
-        // boolean removeVetoableChangeListener(listener) {
-        //    return this$vetoableChangeSupport.removeVetoableChangeListener(listener);
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "removeVetoableChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(vclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(vcsField), "removeVetoableChangeListener", args(varX("listener", vclClassNode))))));
-
-        // add method: void removeVetoableChangeListener(name, listener)
-        declaringClass.addMethod(
-                new MethodNode(
-                        "removeVetoableChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(vclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(vcsField), "removeVetoableChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", vclClassNode))))));
-
-        // add method:
-        // void fireVetoableChange(String name, Object oldValue, Object newValue)
-        //    throws PropertyVetoException
-        // {
-        //     this$vetoableChangeSupport.fireVetoableChange(name, oldValue, newValue)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "fireVetoableChange",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(ClassHelper.OBJECT_TYPE, "oldValue"), param(ClassHelper.OBJECT_TYPE, "newValue")),
-                        new ClassNode[] {ClassHelper.make(PropertyVetoException.class)},
-                        stmt(callX(fieldX(vcsField), "fireVetoableChange", args(varX("name", ClassHelper.STRING_TYPE), varX("oldValue"), varX("newValue"))))));
-
-        // add method:
-        // VetoableChangeListener[] getVetoableChangeListeners() {
-        //   return this$vetoableChangeSupport.getVetoableChangeListeners
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "getVetoableChangeListeners",
-                        ACC_PUBLIC,
-                        vclClassNode.makeArray(),
-                        Parameter.EMPTY_ARRAY,
-                        ClassNode.EMPTY_ARRAY,
-                        returnS(callX(fieldX(vcsField), "getVetoableChangeListeners"))));
-
-        // add method:
-        // VetoableChangeListener[] getVetoableChangeListeners(String name) {
-        //   return this$vetoableChangeSupport.getVetoableChangeListeners(name)
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "getVetoableChangeListeners",
-                        ACC_PUBLIC,
-                        vclClassNode.makeArray(),
-                        params(param(ClassHelper.STRING_TYPE, "name")),
-                        ClassNode.EMPTY_ARRAY,
-                        returnS(callX(fieldX(vcsField), "getVetoableChangeListeners", args(varX("name", ClassHelper.STRING_TYPE))))));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/CliBuilderException.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/CliBuilderException.groovy b/src/main/groovy/cli/CliBuilderException.groovy
deleted file mode 100644
index 84a9438..0000000
--- a/src/main/groovy/cli/CliBuilderException.groovy
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  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 groovy.cli
-
-import groovy.transform.InheritConstructors
-
-@InheritConstructors
-class CliBuilderException extends RuntimeException { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/Option.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/Option.java b/src/main/groovy/cli/Option.java
deleted file mode 100644
index 9b48861..0000000
--- a/src/main/groovy/cli/Option.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  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 groovy.cli;
-
-import groovy.transform.Undefined;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Indicates that a method or property can be used to set a CLI option.
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.FIELD})
-public @interface Option {
-    /**
-     * The description of this option
-     *
-     * @return the description of this option
-     */
-    String description() default "";
-
-    /**
-     * The short name of this option. Defaults to the name of member being annotated if the longName is empty.
-     *
-     * @return the short name of this option
-     */
-    String shortName() default "";
-
-    /**
-     * The long name of this option. Defaults to the name of member being annotated.
-     *
-     * @return the long name of this option
-     */
-    String longName() default "";
-
-    /**
-     * The value separator for this multi-valued option. Only allowed for array-typed arguments.
-     *
-     * @return the value separator for this multi-valued option
-     */
-    String valueSeparator() default "";
-
-    /**
-     * Whether this option can have an optional argument.
-     * Only supported for array-typed arguments to indicate that the array may be empty.
-     *
-     * @return true if this array-typed option can have an optional argument (i.e. could be empty)
-     */
-    boolean optionalArg() default false;
-
-    /**
-     * How many arguments this option has.
-     * A value greater than 1 is only allowed for array-typed arguments.
-     * Ignored for boolean options which are assumed to have a default of 0
-     * or if {@code numberOfArgumentsString} is set.
-     *
-     * @return the number of arguments
-     */
-    int numberOfArguments() default 1;
-
-    /**
-     * How many arguments this option has represented as a String.
-     * Only allowed for array-typed arguments.
-     * Overrides {@code numberOfArguments} if set.
-     * The special values of '+' means one or more and '*' as 0 or more.
-     *
-     * @return the number of arguments (as a String)
-     */
-    String numberOfArgumentsString() default "";
-
-    /**
-     * The default value for this option as a String; subject to type conversion and 'convert'.
-     * Ignored for Boolean options.
-     *
-     * @return the default value for this option
-     */
-    String defaultValue() default "";
-
-    /**
-     * A conversion closure to convert the incoming String into the desired object
-     *
-     * @return the closure to convert this option's argument(s)
-     */
-    Class convert() default Undefined.CLASS.class;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/OptionField.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/OptionField.groovy b/src/main/groovy/cli/OptionField.groovy
deleted file mode 100644
index 69cc1f5..0000000
--- a/src/main/groovy/cli/OptionField.groovy
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  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 groovy.cli
-
-import groovy.transform.AnnotationCollector
-import groovy.transform.Field
-
-@Option
-@Field
-@AnnotationCollector
-@interface OptionField { }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/TypedOption.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/TypedOption.java b/src/main/groovy/cli/TypedOption.java
deleted file mode 100644
index e669324..0000000
--- a/src/main/groovy/cli/TypedOption.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  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 groovy.cli;
-
-import java.util.HashMap;
-
-public class TypedOption<T> extends HashMap<String, T> {
-    public T defaultValue() {
-        return (T) super.get("defaultValue");
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/Unparsed.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/Unparsed.java b/src/main/groovy/cli/Unparsed.java
deleted file mode 100644
index a741413..0000000
--- a/src/main/groovy/cli/Unparsed.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  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 groovy.cli;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Indicates that a method or property will contain the remaining arguments.
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.FIELD})
-public @interface Unparsed {
-    /**
-     * The description for the remaining non-option arguments
-     *
-     * @return the description for the remaining non-option arguments
-     */
-    String description() default "ARGUMENTS";
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/cli/UnparsedField.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/cli/UnparsedField.groovy b/src/main/groovy/cli/UnparsedField.groovy
deleted file mode 100644
index b185431..0000000
--- a/src/main/groovy/cli/UnparsedField.groovy
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  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 groovy.cli
-
-import groovy.transform.AnnotationCollector
-import groovy.transform.Field
-
-@Unparsed
-@Field
-@AnnotationCollector
-@interface UnparsedField { }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/genArrayAccess.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/genArrayAccess.groovy b/src/main/groovy/genArrayAccess.groovy
deleted file mode 100644
index 08cb68a..0000000
--- a/src/main/groovy/genArrayAccess.groovy
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *  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.classgen
-
-println """
-package org.codehaus.groovy.runtime.dgmimpl;
-
-import groovy.lang.MetaClassImpl;
-import groovy.lang.MetaMethod;
-import org.codehaus.groovy.runtime.callsite.CallSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.reflection.ReflectionCache;
-
-public class ArrayOperations {
-  ${genInners()}
-}
-"""
-
-def genInners () {
-    def res = ""
-
-    final Map primitives = [
-            "boolean": "Boolean",
-            "byte": "Byte",
-            "char": "Character",
-            "short": "Short",
-            "int": "Integer",
-            "long": "Long",
-            "float": "Float",
-            "double": "Double"
-    ]
-
-    primitives.each {primName, clsName ->
-        res += """
-         public static class ${clsName}ArrayGetAtMetaMethod extends ArrayGetAtMetaMethod {
-            private static final CachedClass ARR_CLASS = ReflectionCache.getCachedClass(${primName}[].class);
-
-            public Class getReturnType() {
-                return ${clsName}.class;
-            }
-
-            public final CachedClass getDeclaringClass() {
-                return ARR_CLASS;
-            }
-
-            public Object invoke(Object object, Object[] args) {
-                final ${primName}[] objects = (${primName}[]) object;
-                return objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)];
-            }
-
-            public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
-                if (!(args [0] instanceof Integer))
-                  return PojoMetaMethodSite.createNonAwareCallSite(site, metaClass, metaMethod, params, args);
-                else
-                    return new PojoMetaMethodSite(site, metaClass, metaMethod, params) {
-                        public Object invoke(Object receiver, Object[] args) {
-                            final ${primName}[] objects = (${primName}[]) receiver;
-                            return objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)];
-                        }
-
-                        public Object callBinop(Object receiver, Object arg) {
-                            if ((receiver instanceof ${primName}[] && arg instanceof Integer)
-                                    && checkMetaClass()) {
-                                final ${primName}[] objects = (${primName}[]) receiver;
-                                return objects[normaliseIndex(((Integer) arg).intValue(), objects.length)];
-                            }
-                            else
-                              return super.callBinop(receiver,arg);
-                        }
-
-                        public Object invokeBinop(Object receiver, Object arg) {
-                            final ${primName}[] objects = (${primName}[]) receiver;
-                            return objects[normaliseIndex(((Integer) arg).intValue(), objects.length)];
-                        }
-                    };
-            }
-         }
-
-
-        public static class ${clsName}ArrayPutAtMetaMethod extends ArrayPutAtMetaMethod {
-            private static final CachedClass OBJECT_CLASS = ReflectionCache.OBJECT_CLASS;
-            private static final CachedClass ARR_CLASS = ReflectionCache.getCachedClass(${primName}[].class);
-            private static final CachedClass [] PARAM_CLASS_ARR = new CachedClass[] {INTEGER_CLASS, OBJECT_CLASS};
-
-            public ${clsName}ArrayPutAtMetaMethod() {
-                parameterTypes = PARAM_CLASS_ARR;
-            }
-
-            public final CachedClass getDeclaringClass() {
-                return ARR_CLASS;
-            }
-
-            public Object invoke(Object object, Object[] args) {
-                final ${primName}[] objects = (${primName}[]) object;
-                final int index = normaliseIndex(((Integer) args[0]).intValue(), objects.length);
-                Object newValue = args[1];
-                if (!(newValue instanceof ${clsName})) {
-                    Number n = (Number) newValue;
-                    objects[index] = ((Number)newValue).${primName}Value();
-                }
-                else
-                  objects[index] = ((${clsName})args[1]).${primName}Value();
-                return null;
-            }
-
-            public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
-                if (!(args [0] instanceof Integer) || !(args [1] instanceof ${clsName}))
-                  return PojoMetaMethodSite.createNonAwareCallSite(site, metaClass, metaMethod, params, args);
-                else
-                    return new PojoMetaMethodSite(site, metaClass, metaMethod, params) {
-                        public Object call(Object receiver, Object[] args) {
-                            if ((receiver instanceof ${primName}[] && args[0] instanceof Integer && args[1] instanceof ${clsName} )
-                                    && checkMetaClass()) {
-                                final ${primName}[] objects = (${primName}[]) receiver;
-                                objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)] = ((${clsName})args[1]).${primName}Value();
-                                return null;
-                            }
-                            else
-                              return super.call(receiver,args);
-                        }
-                    };
-            }
-        }
-
-       """
-    }
-
-    res
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/genArrays.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/genArrays.groovy b/src/main/groovy/genArrays.groovy
deleted file mode 100644
index 9bbe3cf..0000000
--- a/src/main/groovy/genArrays.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  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.classgen
-
-print """
-
-public class ArrayUtil {
-   ${genMethods()}
-}
-
-"""
-
-def genMethods () {
-    def res = ""
-    for (i in 1..250)
-      res += "\n\n" + genMethod (i)
-    res
-}
-
-def genMethod (int paramNum) {
-    def res = "public static Object [] createArray ("
-    for (k in 0..<paramNum) {
-        res += "Object arg" + k
-        if (k != paramNum-1)
-          res += ", "
-    }
-    res += ") {\n"
-    res += "return new Object [] {\n"
-        for (k in 0..<paramNum) {
-            res += "arg" + k
-            if (k != paramNum-1)
-              res += ", "
-        }
-        res += "};\n"
-    res += "}"
-    res
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/genDgmMath.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/genDgmMath.groovy b/src/main/groovy/genDgmMath.groovy
deleted file mode 100644
index 71bdd5f..0000000
--- a/src/main/groovy/genDgmMath.groovy
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *  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.classgen
-
-def types = ["Integer", "Long", "Float", "Double"]
-
-def getMath (a,b) {
-    if (a == "Double" || b == "Double" || a == "Float" || b == "Float")
-      return "FloatingPointMath"
-
-    if (a == "Long" || b == "Long")
-      return "LongMath"
-
-    "IntegerMath"
-}
-
-println """
-public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
-    NumberMath m = NumberMath.getMath((Number)receiver, (Number)args[0]);
-"""
-
-types.each {
-    a ->
-    print """
-    if (receiver instanceof $a) {"""
-    types.each {
-        b ->
-        print """
-        if (args[0] instanceof $b)
-            return new NumberNumberCallSite (site, metaClass, metaMethod, params, (Number)receiver, (Number)args[0]){
-                public final Object invoke(Object receiver, Object[] args) {
-                    return ${getMath(a,b)}.INSTANCE.addImpl(($a)receiver,($b)args[0]);
-                }
-
-                public final Object invokeBinop(Object receiver, Object arg) {
-                    return ${getMath(a,b)}.INSTANCE.addImpl(($a)receiver,($b)arg);
-                }
-            };
-        """
-    }
-    println "}"
-}
-
-println """
-    return new NumberNumberCallSite (site, metaClass, metaMethod, params, (Number)receiver, (Number)args[0]){
-        public final Object invoke(Object receiver, Object[] args) {
-            return math.addImpl((Number)receiver,(Number)args[0]);
-        }
-
-        public final Object invokeBinop(Object receiver, Object arg) {
-            return math.addImpl((Number)receiver,(Number)arg);
-        }
-}
-"""
-
-for (i in 2..256) {
-    print "public Object invoke$i (Object receiver, "
-    for (j in 1..(i-1)) {
-        print "Object a$j, "
-    }
-    println "Object a$i) {"
-
-    print "  return invoke (receiver, new Object[] {"
-
-    for (j in 1..(i-1)) {
-        print "a$j, "
-    }
-    println "a$i} );"
-
-    println "}"
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/genMathModification.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/genMathModification.groovy b/src/main/groovy/genMathModification.groovy
deleted file mode 100644
index 10cc7eb..0000000
--- a/src/main/groovy/genMathModification.groovy
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  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.classgen
-
-def ops = [
-        "plus",
-        "minus",
-        "multiply",
-        "div",
-        "or",
-        "and",
-        "xor",
-        "intdiv",
-        "mod",
-        "leftShift",
-        "rightShift",
-        "rightShiftUnsigned"
-]
-
-def numbers = ["Byte":"byte", "Short":"short", "Integer":"int", "Long":"long", "Float":"float", "Double":"double"]
-
-ops.each { op ->
-    numbers.each { wrappedType, type ->
-        println "public boolean ${type}_${op};";    
-    }
-}
-
-ops.each { op ->
-    println "if (\"${op}\".equals(name)) {"
-    numbers.each { wrappedType, type ->
-        println """if (klazz==${wrappedType}.class) {
-                ${type}_${op} = true;
-            }"""
-    }
-    println "if (klazz==Object.class) {"
-    numbers.each { wrappedType, type ->
-        println "${type}_${op} = true;"
-            }
-    println "}"
-    println "}"
-}
-
-ops.each { op ->
-    numbers.each { wrappedType1, type1 ->
-        numbers.each { wrappedType2, type2 ->
-            def math = getMath(wrappedType1, wrappedType2)
-            if (math [op]) {
-                println """public static ${math.resType} ${op}(${type1} op1, ${type2} op2) {
-                   if (instance.${type1}_${op}) {
-                      return ${op}Slow(op1, op2);
-                   }
-                   else {
-                      return ${math.resType != type1 ? "((" + math.resType+ ")op1)" : "op1"} ${math[op]} ${math.resType != type2 ? "((" + math.resType+ ")op2)" : "op2"};
-                   }
-                }"""
-                println """private static ${math.resType} ${op}Slow(${type1} op1,${type2} op2) {
-                      return ((Number)InvokerHelper.invokeMethod(op1, "${op}", op2)).${math.resType}Value();
-                }"""
-            }
-        }
-    }
-}
-
-def isFloatingPoint(number) {
-    return number == "Double" || number == "Float";
-}
-
-def isLong(number) {
-    return number == "Long";
-}
-
-def getMath (left, right) {
-    if (isFloatingPoint(left) || isFloatingPoint(right)) {
-        return [
-                resType : "double",
-
-                plus : "+",
-                minus : "-",
-                multiply : "*",
-                div : "/",
-        ];
-    }
-    if (isLong(left) || isLong(right)){
-        return [
-                resType : "long",
-
-                plus : "+",
-                minus : "-",
-                multiply : "*",
-                div : "/",
-                or : "|",
-                and : "&",
-                xor : "^",
-                intdiv : "/",
-                mod : "%",
-                leftShift : "<<",
-                rightShift : ">>",
-                rightShiftUnsigned : ">>>"
-        ]
-    }
-    return [
-            resType : "int",
-
-            plus : "+",
-            minus : "-",
-            multiply : "*",
-            div : "/",
-            or : "|",
-            and : "&",
-            xor : "^",
-            intdiv : "/",
-            mod : "%",
-            leftShift : "<<",
-            rightShift : ">>",
-            rightShiftUnsigned : ">>>"
-    ]
-}


[26/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ConfigObject.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ConfigObject.java b/src/main/groovy/groovy/util/ConfigObject.java
new file mode 100644
index 0000000..c76bc97
--- /dev/null
+++ b/src/main/groovy/groovy/util/ConfigObject.java
@@ -0,0 +1,425 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.Writable;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+import org.codehaus.groovy.syntax.Types;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A ConfigObject at a simple level is a Map that creates configuration entries (other ConfigObjects) when referencing them.
+ * This means that navigating to foo.bar.stuff will not return null but nested ConfigObjects which are of course empty maps
+ * The Groovy truth can be used to check for the existence of "real" entries.
+ *
+ * @author Graeme Rocher
+ * @author Guillaume Laforge (rewrite in Java related to security constraints on Google App Engine)
+ * @since 1.5
+ */
+public class ConfigObject extends GroovyObjectSupport implements Writable, Map, Cloneable {
+
+    static final Collection<String> KEYWORDS = Types.getKeywords();
+
+    static final String TAB_CHARACTER = "\t";
+
+    /**
+     * The config file that was used when parsing this ConfigObject
+     */
+    private URL configFile;
+
+    private HashMap delegateMap = new LinkedHashMap();
+
+    public ConfigObject(URL file) {
+        this.configFile = file;
+    }
+
+    public ConfigObject() {
+        this(null);
+    }
+
+    public URL getConfigFile() {
+        return configFile;
+    }
+
+    public void setConfigFile(URL configFile) {
+        this.configFile = configFile;
+    }
+
+    /**
+     * Writes this config object into a String serialized representation which can later be parsed back using the parse()
+     * method
+     *
+     * @see groovy.lang.Writable#writeTo(java.io.Writer)
+     */
+    public Writer writeTo(Writer outArg) throws IOException {
+        BufferedWriter out = new BufferedWriter(outArg);
+        try {
+            writeConfig("", this, out, 0, false);
+        } finally {
+            out.flush();
+        }
+
+        return outArg;
+    }
+
+
+    /**
+     * Overrides the default getProperty implementation to create nested ConfigObject instances on demand
+     * for non-existent keys
+     */
+    public Object getProperty(String name) {
+        if ("configFile".equals(name))
+            return this.configFile;
+
+        if (!containsKey(name)) {
+            ConfigObject prop = new ConfigObject(this.configFile);
+            put(name, prop);
+
+            return prop;
+        }
+
+        return get(name);
+    }
+
+    /**
+     * A ConfigObject is a tree structure consisting of nested maps. This flattens the maps into
+     * a single level structure like a properties file
+     */
+    public Map flatten() {
+        return flatten(null);
+    }
+
+    /**
+     * Flattens this ConfigObject populating the results into the target Map
+     *
+     * @see ConfigObject#flatten()
+     */
+    public Map flatten(Map target) {
+        if (target == null)
+            target = new ConfigObject();
+        populate("", target, this);
+
+        return target;
+    }
+
+    /**
+     * Merges the given map with this ConfigObject overriding any matching configuration entries in this ConfigObject
+     *
+     * @param other The ConfigObject to merge with
+     * @return The result of the merge
+     */
+    public Map merge(ConfigObject other) {
+        return doMerge(this, other);
+    }
+
+
+    /**
+     * Converts this ConfigObject into a the java.util.Properties format, flattening the tree structure beforehand
+     *
+     * @return A java.util.Properties instance
+     */
+    public Properties toProperties() {
+        Properties props = new Properties();
+        flatten(props);
+
+        props = convertValuesToString(props);
+
+        return props;
+    }
+
+    /**
+     * Converts this ConfigObject ino the java.util.Properties format, flatten the tree and prefixing all entries with the given prefix
+     *
+     * @param prefix The prefix to append before property entries
+     * @return A java.util.Properties instance
+     */
+    public Properties toProperties(String prefix) {
+        Properties props = new Properties();
+        populate(prefix + ".", props, this);
+
+        props = convertValuesToString(props);
+
+        return props;
+    }
+
+    private Map doMerge(Map config, Map other) {
+        for (Object o : other.entrySet()) {
+            Map.Entry next = (Map.Entry) o;
+            Object key = next.getKey();
+            Object value = next.getValue();
+
+            Object configEntry = config.get(key);
+
+            if (configEntry == null) {
+                config.put(key, value);
+
+                continue;
+            } else {
+                if (configEntry instanceof Map && !((Map) configEntry).isEmpty() && value instanceof Map) {
+                    // recur
+                    doMerge((Map) configEntry, (Map) value);
+                } else {
+                    config.put(key, value);
+                }
+            }
+        }
+
+        return config;
+    }
+
+    private void writeConfig(String prefix, ConfigObject map, BufferedWriter out, int tab, boolean apply) throws IOException {
+        String space = apply ? StringGroovyMethods.multiply(TAB_CHARACTER, tab) : "";
+
+        for (Object o1 : map.keySet()) {
+            String key = (String) o1;
+            Object v = map.get(key);
+
+            if (v instanceof ConfigObject) {
+                ConfigObject value = (ConfigObject) v;
+
+                if (!value.isEmpty()) {
+
+                    Object dotsInKeys = null;
+                    for (Object o : value.entrySet()) {
+                        Entry e = (Entry) o;
+                        String k = (String) e.getKey();
+                        if (k.indexOf('.') > -1) {
+                            dotsInKeys = e;
+                            break;
+                        }
+                    }
+
+                    int configSize = value.size();
+                    Object firstKey = value.keySet().iterator().next();
+                    Object firstValue = value.values().iterator().next();
+
+                    int firstSize;
+                    if (firstValue instanceof ConfigObject) {
+                        firstSize = ((ConfigObject) firstValue).size();
+                    } else {
+                        firstSize = 1;
+                    }
+
+                    if (configSize == 1 || DefaultGroovyMethods.asBoolean(dotsInKeys)) {
+                        if (firstSize == 1 && firstValue instanceof ConfigObject) {
+                            key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
+                            String writePrefix = prefix + key + "." + firstKey + ".";
+                            writeConfig(writePrefix, (ConfigObject) firstValue, out, tab, true);
+                        } else if (!DefaultGroovyMethods.asBoolean(dotsInKeys) && firstValue instanceof ConfigObject) {
+                            writeNode(key, space, tab, value, out);
+                        } else {
+                            for (Object j : value.keySet()) {
+                                Object v2 = value.get(j);
+                                Object k2 = ((String) j).indexOf('.') > -1 ? InvokerHelper.inspect(j) : j;
+                                if (v2 instanceof ConfigObject) {
+                                    key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
+                                    writeConfig(prefix + key, (ConfigObject) v2, out, tab, false);
+                                } else {
+                                    writeValue(key + "." + k2, space, prefix, v2, out);
+                                }
+                            }
+                        }
+                    } else {
+                        writeNode(key, space, tab, value, out);
+                    }
+                }
+            } else {
+                writeValue(key, space, prefix, v, out);
+            }
+        }
+    }
+
+    private static void writeValue(String key, String space, String prefix, Object value, BufferedWriter out) throws IOException {
+//        key = key.indexOf('.') > -1 ? InvokerHelper.inspect(key) : key;
+        boolean isKeyword = KEYWORDS.contains(key);
+        key = isKeyword ? InvokerHelper.inspect(key) : key;
+
+        if (!StringGroovyMethods.asBoolean(prefix) && isKeyword) prefix = "this.";
+        out.append(space).append(prefix).append(key).append('=').append(InvokerHelper.inspect(value));
+        out.newLine();
+    }
+
+    private void writeNode(String key, String space, int tab, ConfigObject value, BufferedWriter out) throws IOException {
+        key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
+        out.append(space).append(key).append(" {");
+        out.newLine();
+        writeConfig("", value, out, tab + 1, true);
+        out.append(space).append('}');
+        out.newLine();
+    }
+
+    private static Properties convertValuesToString(Map props) {
+        Properties newProps = new Properties();
+
+        for (Object o : props.entrySet()) {
+            Map.Entry next = (Map.Entry) o;
+            Object key = next.getKey();
+            Object value = next.getValue();
+
+            newProps.put(key, value != null ? value.toString() : null);
+        }
+
+        return newProps;
+    }
+
+    private void populate(String suffix, Map config, Map map) {
+        for (Object o : map.entrySet()) {
+            Map.Entry next = (Map.Entry) o;
+            Object key = next.getKey();
+            Object value = next.getValue();
+
+            if (value instanceof Map) {
+                populate(suffix + key + ".", config, (Map) value);
+            } else {
+                try {
+                    config.put(suffix + key, value);
+                } catch (NullPointerException e) {
+                    // it is idiotic story but if config map doesn't allow null values (like Hashtable)
+                    // we can't do too much
+                }
+            }
+        }
+    }
+
+    public int size() {
+        return delegateMap.size();
+    }
+
+    public boolean isEmpty() {
+        return delegateMap.isEmpty();
+    }
+
+    public boolean containsKey(Object key) {
+        return delegateMap.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return delegateMap.containsValue(value);
+    }
+
+    public Object get(Object key) {
+        return delegateMap.get(key);
+    }
+
+    public Object put(Object key, Object value) {
+        return delegateMap.put(key, value);
+    }
+
+    public Object remove(Object key) {
+        return delegateMap.remove(key);
+    }
+
+    public void putAll(Map m) {
+        delegateMap.putAll(m);
+    }
+
+    public void clear() {
+        delegateMap.clear();
+    }
+
+    public Set keySet() {
+        return delegateMap.keySet();
+    }
+
+    public Collection values() {
+        return delegateMap.values();
+    }
+
+    public Set entrySet() {
+        return delegateMap.entrySet();
+    }
+
+    /**
+     * Returns a shallow copy of this ConfigObject, keys and configuration entries are not cloned.
+     * @return a shallow copy of this ConfigObject
+     */
+    public ConfigObject clone() {
+        try {
+            ConfigObject clone = (ConfigObject) super.clone();
+            clone.configFile = configFile;
+            clone.delegateMap = (LinkedHashMap) delegateMap.clone();
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Checks if a config option is set. Example usage:
+     * <pre class="groovyTestCase">
+     * def config = new ConfigSlurper().parse("foo { password='' }")
+     * assert config.foo.isSet('password')
+     * assert config.foo.isSet('username') == false
+     * </pre>
+     *
+     * The check works <b>only</v> for options <b>one</b> block below the current block.
+     * E.g. <code>config.isSet('foo.password')</code> will always return false.
+     *
+     * @param option The name of the option
+     * @return <code>true</code> if the option is set <code>false</code> otherwise
+     * @since 2.3.0
+     */
+    public Boolean isSet(String option) {
+        if (delegateMap.containsKey(option)) {
+            Object entry = delegateMap.get(option);
+            if (!(entry instanceof ConfigObject) || !((ConfigObject) entry).isEmpty()) {
+                return Boolean.TRUE;
+            }
+        }
+        return Boolean.FALSE;
+    }
+
+    public String prettyPrint() {
+        StringWriter sw = new StringWriter();
+        try {
+            writeTo(sw);
+        } catch (IOException e) {
+            throw new GroovyRuntimeException(e);
+        }
+
+        return sw.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        try {
+            InvokerHelper.write(sw, this);
+        } catch (IOException e) {
+            throw new GroovyRuntimeException(e);
+        }
+
+        return sw.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ConfigSlurper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ConfigSlurper.groovy b/src/main/groovy/groovy/util/ConfigSlurper.groovy
new file mode 100644
index 0000000..20d0723
--- /dev/null
+++ b/src/main/groovy/groovy/util/ConfigSlurper.groovy
@@ -0,0 +1,309 @@
+/*
+ *  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 groovy.util
+
+import org.codehaus.groovy.runtime.InvokerHelper
+
+/**
+ * ConfigSlurper is a utility class for reading configuration files defined in the form of Groovy
+ * scripts. Configuration settings can be defined using dot notation or scoped using closures:
+ *
+ * <pre><code>
+ * grails.webflow.stateless = true
+ * smtp {
+ *     mail.host = 'smtp.myisp.com'
+ *     mail.auth.user = 'server'
+ * }
+ * resources.URL = "http://localhost:80/resources"
+ * </code></pre>
+ *
+ * Settings can either be bound into nested maps or onto a specified JavaBean instance.
+ * In the latter case, an error will be thrown if a property cannot be bound.
+ *
+ * @author Graeme Rocher
+ * @author Andres Almiray
+ * @since 1.5
+ */
+class ConfigSlurper {
+    private static final ENVIRONMENTS_METHOD = 'environments'
+    GroovyClassLoader classLoader = new GroovyClassLoader()
+    private Map bindingVars = [:]
+
+    private final Map<String, String> conditionValues = [:]
+    private final Stack<Map<String, ConfigObject>> conditionalBlocks = new Stack<Map<String,ConfigObject>>()
+
+    ConfigSlurper() {
+        this('')
+    }
+
+    /**
+     * Constructs a new ConfigSlurper instance using the given environment
+     *
+     * @param env The Environment to use
+     */
+    ConfigSlurper(String env) {
+        conditionValues[ENVIRONMENTS_METHOD] = env
+    }
+
+    void registerConditionalBlock(String blockName, String blockValue) {
+        if (blockName) {
+            if (!blockValue) {
+                conditionValues.remove(blockName)
+            } else {
+                conditionValues[blockName] = blockValue
+            }
+        }
+    }
+
+    Map<String, String> getConditionalBlockValues() {
+        Collections.unmodifiableMap(conditionValues)
+    }
+
+    String getEnvironment() {
+        return conditionValues[ENVIRONMENTS_METHOD]
+    }
+
+    void setEnvironment(String environment) {
+        conditionValues[ENVIRONMENTS_METHOD] = environment
+    }
+
+    /**
+     * Sets any additional variables that should be placed into the binding when evaluating Config scripts
+     */
+    void setBinding(Map vars) {
+        this.bindingVars = vars
+    }
+
+    /**
+     * Parses a ConfigObject instances from an instance of java.util.Properties
+     *
+     * @param The java.util.Properties instance
+     */
+    ConfigObject parse(Properties properties) {
+        ConfigObject config = new ConfigObject()
+        for (key in properties.keySet()) {
+            def tokens = key.split(/\./)
+
+            def current = config
+            def last
+            def lastToken
+            def foundBase = false
+            for (token in tokens) {
+                if (foundBase) {
+                    // handle not properly nested tokens by ignoring
+                    // hierarchy below this point
+                    lastToken += "." + token
+                    current = last
+                } else {
+                    last = current
+                    lastToken = token
+                    current = current."${token}"
+                    if (!(current instanceof ConfigObject)) foundBase = true
+                }
+            }
+
+            if (current instanceof ConfigObject) {
+                if (last[lastToken]) {
+                    def flattened = last.flatten()
+                    last.clear()
+                    flattened.each { k2, v2 -> last[k2] = v2 }
+                    last[lastToken] = properties.get(key)
+                }
+                else {
+                    last[lastToken] = properties.get(key)
+                }
+            }
+            current = config
+        }
+        return config
+    }
+    /**
+     * Parse the given script as a string and return the configuration object
+     *
+     * @see ConfigSlurper#parse(groovy.lang.Script)
+     */
+    ConfigObject parse(String script) {
+        return parse(classLoader.parseClass(script))
+    }
+
+    /**
+     * Create a new instance of the given script class and parse a configuration object from it
+     *
+     * @see ConfigSlurper#parse(groovy.lang.Script)
+     */
+    ConfigObject parse(Class scriptClass) {
+        return parse(scriptClass.newInstance())
+    }
+
+    /**
+     * Parse the given script into a configuration object (a Map)
+     * (This method creates a new class to parse the script each time it is called.)
+     *
+     * @param script The script to parse
+     * @return A Map of maps that can be navigating with dot de-referencing syntax to obtain configuration entries
+     */
+    ConfigObject parse(Script script) {
+        return parse(script, null)
+    }
+
+    /**
+     * Parses a Script represented by the given URL into a ConfigObject
+     *
+     * @param scriptLocation The location of the script to parse
+     * @return The ConfigObject instance
+     */
+    ConfigObject parse(URL scriptLocation) {
+        return parse(classLoader.parseClass(scriptLocation.text).newInstance(), scriptLocation)
+    }
+
+    /**
+     * Parses the passed groovy.lang.Script instance using the second argument to allow the ConfigObject
+     * to retain an reference to the original location other Groovy script
+     *
+     * @param script The groovy.lang.Script instance
+     * @param location The original location of the Script as a URL
+     * @return The ConfigObject instance
+     */
+    ConfigObject parse(Script script, URL location) {
+        Stack<String> currentConditionalBlock = new Stack<String>()
+        def config = location ? new ConfigObject(location) : new ConfigObject()
+        GroovySystem.metaClassRegistry.removeMetaClass(script.class)
+        def mc = script.class.metaClass
+        def prefix = ""
+        LinkedList stack = new LinkedList()
+        stack << [config: config, scope: [:]]
+        def pushStack = { co ->
+            stack << [config: co, scope: stack.last.scope.clone()]
+        }
+        def assignName = { name, co ->
+            def current = stack.last
+            current.config[name] = co
+            current.scope[name] = co
+        }
+        mc.getProperty = { String name ->
+            def current = stack.last
+            def result
+            if (current.config.get(name)) {
+                result = current.config.get(name)
+            } else if (current.scope[name]) {
+                result = current.scope[name]
+            } else {
+                try {
+                    result = InvokerHelper.getProperty(this, name)
+                } catch (GroovyRuntimeException e) {
+                    result = new ConfigObject()
+                    assignName.call(name, result)
+                }
+            }
+            result
+        }
+
+        ConfigObject overrides = new ConfigObject()
+        mc.invokeMethod = { String name, args ->
+            def result
+            if (args.length == 1 && args[0] instanceof Closure) {
+                if (name in conditionValues.keySet()) {
+                    try {
+                        currentConditionalBlock.push(name)
+                        conditionalBlocks.push([:])
+                        args[0].call()
+                    } finally {
+                        currentConditionalBlock.pop()
+                        for (entry in conditionalBlocks.pop().entrySet()) {
+                            def c = stack.last.config
+                            (c != config? c : overrides).merge(entry.value)
+                        }
+                    }
+                } else if (currentConditionalBlock.size() > 0) {
+                    String conditionalBlockKey = currentConditionalBlock.peek()
+                    if (name == conditionValues[conditionalBlockKey]) {
+                        def co = new ConfigObject()
+                        conditionalBlocks.peek()[conditionalBlockKey] = co
+
+                        pushStack.call(co)
+                        try {
+                            currentConditionalBlock.pop()
+                            args[0].call()
+                        } finally {
+                            currentConditionalBlock.push(conditionalBlockKey)
+                        }
+                        stack.removeLast()
+                    }
+                } else {
+                    def co
+                    if (stack.last.config.get(name) instanceof ConfigObject) {
+                        co = stack.last.config.get(name)
+                    } else {
+                        co = new ConfigObject()
+                    }
+
+                    assignName.call(name, co)
+                    pushStack.call(co)
+                    args[0].call()
+                    stack.removeLast()
+                }
+            } else if (args.length == 2 && args[1] instanceof Closure) {
+                try {
+                    prefix = name + '.'
+                    assignName.call(name, args[0])
+                    args[1].call()
+                } finally { prefix = "" }
+            } else {
+                MetaMethod mm = mc.getMetaMethod(name, args)
+                if (mm) {
+                    result = mm.invoke(delegate, args)
+                } else {
+                    throw new MissingMethodException(name, getClass(), args)
+                }
+            }
+            result
+        }
+        script.metaClass = mc
+
+        def setProperty = { String name, value ->
+            assignName.call(prefix + name, value)
+        }
+        def binding = new ConfigBinding(setProperty)
+        if (this.bindingVars) {
+            binding.getVariables().putAll(this.bindingVars)
+        }
+        script.binding = binding
+
+        script.run()
+
+        config.merge(overrides)
+
+        return config
+    }
+}
+
+/**
+ * Since Groovy Script doesn't support overriding setProperty, we use a trick with the Binding to provide this
+ * functionality
+ */
+class ConfigBinding extends Binding {
+    def callable
+    ConfigBinding(Closure c) {
+        this.callable = c
+    }
+
+    void setVariable(String name, Object value) {
+        callable(name, value)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/DelegatingScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/DelegatingScript.java b/src/main/groovy/groovy/util/DelegatingScript.java
new file mode 100644
index 0000000..959c8e8
--- /dev/null
+++ b/src/main/groovy/groovy/util/DelegatingScript.java
@@ -0,0 +1,141 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+import groovy.lang.MissingMethodException;
+import groovy.lang.MissingPropertyException;
+import groovy.lang.Script;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * {@link Script} that performs method invocations and property access like {@link groovy.lang.Closure} does.
+ *
+ * <p>
+ * {@link DelegatingScript} is a convenient basis for loading a custom-defined DSL as a {@link Script}, then execute it.
+ * The following sample code illustrates how to do it:
+ *
+ * <pre>
+ * class MyDSL {
+ *     public void foo(int x, int y, Closure z) { ... }
+ *     public void setBar(String a) { ... }
+ * }
+ *
+ * CompilerConfiguration cc = new CompilerConfiguration();
+ * cc.setScriptBaseClass(DelegatingScript.class.getName());
+ * GroovyShell sh = new GroovyShell(cl,new Binding(),cc);
+ * DelegatingScript script = (DelegatingScript)sh.parse(new File("my.dsl"))
+ * script.setDelegate(new MyDSL());
+ * script.run();
+ * </pre>
+ *
+ * <p>
+ * <tt>my.dsl</tt> can look like this:
+ *
+ * <pre>
+ * foo(1,2) {
+ *     ....
+ * }
+ * bar = ...;
+ * </pre>
+ *
+ * <p>
+ * {@link DelegatingScript} does this by delegating property access and method invocation to the <tt>delegate</tt> object.
+ *
+ * <p>
+ * More formally speaking, given the following script:
+ *
+ * <pre>
+ * a = 1;
+ * b(2);
+ * </pre>
+ *
+ * <p>
+ * Using {@link DelegatingScript} as the base class, the code will run as:
+ *
+ * <pre>
+ * delegate.a = 1;
+ * delegate.b(2);
+ * </pre>
+ *
+ * ... whereas in plain {@link Script}, this will be run as:
+ *
+ * <pre>
+ * binding.setProperty("a",1);
+ * ((Closure)binding.getProperty("b")).call(2);
+ * </pre>
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public abstract class DelegatingScript extends Script {
+    private Object delegate;
+    private MetaClass metaClass;
+
+    protected DelegatingScript() {
+        super();
+    }
+
+    protected DelegatingScript(Binding binding) {
+        super(binding);
+    }
+
+    /**
+     * Sets the delegation target.
+     */
+    public void setDelegate(Object delegate) {
+        this.delegate = delegate;
+        this.metaClass = InvokerHelper.getMetaClass(delegate.getClass());
+    }
+
+    @Override
+    public Object invokeMethod(String name, Object args) {
+        try {
+            if (delegate instanceof GroovyObject) {
+                return ((GroovyObject) delegate).invokeMethod(name, args);
+            }
+            return metaClass.invokeMethod(delegate, name, args);
+        } catch (MissingMethodException mme) {
+            return super.invokeMethod(name, args);
+        }
+    }
+
+    @Override
+    public Object getProperty(String property) {
+        try {
+            return metaClass.getProperty(delegate,property);
+        } catch (MissingPropertyException e) {
+            return super.getProperty(property);
+        }
+    }
+
+    @Override
+    public void setProperty(String property, Object newValue) {
+        try {
+            metaClass.setProperty(delegate,property,newValue);
+        } catch (MissingPropertyException e) {
+            super.setProperty(property,newValue);
+        }
+    }
+
+    public Object getDelegate() {
+        return delegate;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/Eval.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/Eval.java b/src/main/groovy/groovy/util/Eval.java
new file mode 100644
index 0000000..87f9295
--- /dev/null
+++ b/src/main/groovy/groovy/util/Eval.java
@@ -0,0 +1,124 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+import org.codehaus.groovy.control.CompilationFailedException;
+
+/**
+ * Allow easy integration from Groovy into Java through convenience methods.
+ * <p>
+ * This class is a simple helper on top of GroovyShell. You can use it to evaluate small
+ * Groovy scripts that don't need large Binding objects. For example, this script 
+ * executes with no errors: 
+ * <pre class="groovyTestCase">
+ * assert Eval.me(' 2 * 4 + 2') == 10
+ * assert Eval.x(2, ' x * 4 + 2') == 10
+ * </pre>
+ * 
+ * @see GroovyShell
+ * @author Dierk Koenig
+ */
+
+public class Eval {
+    /**
+     * Evaluates the specified String expression and returns the result. For example: 
+     * <pre class="groovyTestCase">
+     * assert Eval.me(' 2 * 4 + 2') == 10
+     * </pre>
+     * @param expression the Groovy expression to evaluate
+     * @return the result of the expression
+     * @throws CompilationFailedException if expression is not valid Groovy
+     */
+    public static Object me(final String expression) throws CompilationFailedException {
+        return me(null, null, expression);
+    }
+
+    /**
+     * Evaluates the specified String expression and makes the parameter available inside
+     * the script, returning the result. For example, this code binds the 'x' variable: 
+     * <pre class="groovyTestCase">
+     * assert Eval.me('x', 2, ' x * 4 + 2') == 10
+     * </pre>
+     * @param expression the Groovy expression to evaluate
+     * @return the result of the expression
+     * @throws CompilationFailedException if expression is not valid Groovy
+     */
+    public static Object me(final String symbol, final Object object, final String expression) throws CompilationFailedException {
+        Binding b = new Binding();
+        b.setVariable(symbol, object);
+        GroovyShell sh = new GroovyShell(b);
+        return sh.evaluate(expression);
+    }
+
+    /**
+     * Evaluates the specified String expression and makes the parameter available inside
+     * the script bound to a variable named 'x', returning the result. For example, this 
+     * code executes without failure: 
+     * <pre class="groovyTestCase">
+     * assert Eval.x(2, ' x * 4 + 2') == 10
+     * </pre>
+     * @param expression the Groovy expression to evaluate
+     * @return the result of the expression
+     * @throws CompilationFailedException if expression is not valid Groovy
+     */
+    public static Object x(final Object x, final String expression) throws CompilationFailedException {
+        return me("x", x, expression);
+    }
+
+    /**
+     * Evaluates the specified String expression and makes the first two parameters available inside
+     * the script bound to variables named 'x' and 'y' respectively, returning the result. For example, 
+     * this code executes without failure: 
+     * <pre class="groovyTestCase">
+     * assert Eval.xy(2, 4, ' x * y + 2') == 10
+     * </pre>
+     * @param expression the Groovy expression to evaluate
+     * @return the result of the expression
+     * @throws CompilationFailedException if expression is not valid Groovy
+     */
+    public static Object xy(final Object x, final Object y, final String expression) throws CompilationFailedException {
+        Binding b = new Binding();
+        b.setVariable("x", x);
+        b.setVariable("y", y);
+        GroovyShell sh = new GroovyShell(b);
+        return sh.evaluate(expression);
+    }
+
+    /**
+     * Evaluates the specified String expression and makes the first three parameters available inside
+     * the script bound to variables named 'x', 'y', and 'z' respectively, returning the result. For 
+     * example, this code executes without failure: 
+     * <pre class="groovyTestCase">
+     * assert Eval.xyz(2, 4, 2, ' x * y + z') == 10
+     * </pre>
+     * @param expression the Groovy expression to evaluate
+     * @return the result of the expression
+     * @throws CompilationFailedException if expression is not valid Groovy
+     */
+    public static Object xyz(final Object x, final Object y, final Object z, final String expression) throws CompilationFailedException {
+        Binding b = new Binding();
+        b.setVariable("x", x);
+        b.setVariable("y", y);
+        b.setVariable("z", z);
+        GroovyShell sh = new GroovyShell(b);
+        return sh.evaluate(expression);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/Expando.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/Expando.java b/src/main/groovy/groovy/util/Expando.java
new file mode 100644
index 0000000..f009551
--- /dev/null
+++ b/src/main/groovy/groovy/util/Expando.java
@@ -0,0 +1,175 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.MetaExpandoProperty;
+import groovy.lang.MissingPropertyException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+
+/**
+ * Represents a dynamically expandable bean.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Hein Meling
+ * @author Pilho Kim
+ */
+public class Expando extends GroovyObjectSupport {
+
+    private Map expandoProperties;
+
+    public Expando() {
+    }
+
+    public Expando(Map expandoProperties) {
+        this.expandoProperties = expandoProperties;
+    }
+
+    /**
+     * @return the dynamically expanded properties
+     */
+    public Map getProperties() {
+        if (expandoProperties == null) {
+            expandoProperties = createMap();
+        }
+        return expandoProperties;
+    }
+
+    public List getMetaPropertyValues() {
+        // run through all our current properties and create MetaProperty objects
+        List ret = new ArrayList();
+        for (Object o : getProperties().entrySet()) {
+            Entry entry = (Entry) o;
+            ret.add(new MetaExpandoProperty(entry));
+        }
+
+        return ret;
+    }
+
+    public Object getProperty(String property) {
+        // always use the expando properties first
+        Object result = getProperties().get(property);
+        if (result != null) return result;
+        try {
+            return super.getProperty(property);
+        }
+        catch (MissingPropertyException e) {
+            // IGNORE
+        }
+        return null;
+    }
+
+    public void setProperty(String property, Object newValue) {
+        // always use the expando properties
+        getProperties().put(property, newValue);
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return super.invokeMethod(name, args);
+        }
+        catch (GroovyRuntimeException e) {
+            // br should get a "native" property match first. getProperty includes such fall-back logic
+            Object value = this.getProperty(name);
+            if (value instanceof Closure) {
+                Closure closure = (Closure) value;
+                closure = (Closure) closure.clone();
+                closure.setDelegate(this);
+                return closure.call((Object[]) args);
+            } else {
+                throw e;
+            }
+        }
+
+    }
+
+    /**
+     * This allows toString to be overridden by a closure <i>field</i> method attached
+     * to the expando object.
+     *
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        Object method = getProperties().get("toString");
+        if (method != null && method instanceof Closure) {
+            // invoke overridden toString closure method
+            Closure closure = (Closure) method;
+            closure.setDelegate(this);
+            return closure.call().toString();
+        } else {
+            return expandoProperties.toString();
+        }
+    }
+
+    /**
+     * This allows equals to be overridden by a closure <i>field</i> method attached
+     * to the expando object.
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        Object method = getProperties().get("equals");
+        if (method != null && method instanceof Closure) {
+            // invoke overridden equals closure method
+            Closure closure = (Closure) method;
+            closure.setDelegate(this);
+            Boolean ret = (Boolean) closure.call(obj);
+            return ret.booleanValue();
+        } else {
+            return super.equals(obj);
+        }
+    }
+
+    /**
+     * This allows hashCode to be overridden by a closure <i>field</i> method attached
+     * to the expando object.
+     *
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        Object method = getProperties().get("hashCode");
+        if (method != null && method instanceof Closure) {
+            // invoke overridden hashCode closure method
+            Closure closure = (Closure) method;
+            closure.setDelegate(this);
+            Integer ret = (Integer) closure.call();
+            return ret.intValue();
+        } else {
+            return super.hashCode();
+        }
+    }
+
+    /**
+     * Factory method to create a new Map used to store the expando properties map
+     *
+     * @return a newly created Map implementation
+     */
+    protected Map createMap() {
+        return new HashMap();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/Factory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/Factory.java b/src/main/groovy/groovy/util/Factory.java
new file mode 100644
index 0000000..c8e8fc7
--- /dev/null
+++ b/src/main/groovy/groovy/util/Factory.java
@@ -0,0 +1,90 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
+ * @author Danno Ferrin
+ */
+public interface Factory {
+    /**
+     *
+     * @return true if no child closures should be processed
+     */
+    boolean isLeaf();
+
+    /**
+     * Does this factory "Own" it's child closure.
+     *
+     * @return true  if the factory should have onContentClosure() called,
+     *         false if the builder should handle it
+     */
+    boolean isHandlesNodeChildren();
+
+    /**
+     * Called when a factory is registered to a builder
+     * @param builder the build the factory has been registered to
+     * @param registeredName the name the factory has been registered under
+     */
+    void onFactoryRegistration(FactoryBuilderSupport builder, String registeredName, String registeredGroupName);
+
+    /**
+     * @param builder the FactoryBuilder
+     * @param name the name of the node being built
+     * @param value the 'value' argument in the build node
+     * @param attributes the attributes of the build arg
+     * @return the object created for the builder
+     * @throws InstantiationException if attempting to instantiate an interface or abstract class
+     * @throws IllegalAccessException if the instance can't be created due to a security violation
+     */
+    Object newInstance( FactoryBuilderSupport builder, Object name, Object value, Map attributes )
+            throws InstantiationException, IllegalAccessException;
+
+    /**
+     * @param builder the FactoryBuilder
+     * @param node the node (returned from newINstance) to consider the attributes for
+     * @param attributes the attributes, a mutable set
+     * @return true if the factory builder should use standard bean property matching for the remaining attributes
+     */
+    boolean onHandleNodeAttributes( FactoryBuilderSupport builder, Object node, Map attributes );
+
+    /**
+     * Only called if it isLeaf is false and isHandlesNodeChildren is true
+     * @param builder the FactoryBuilder
+     * @param node the node (returned from newINstance) to consider the attributes for
+     * @param childContent the child content closure of the builder
+     * @return true if the factory builder should apply default node processing to the content child
+     */
+    boolean onNodeChildren( FactoryBuilderSupport builder, Object node, Closure childContent);
+
+    /**
+     * @param builder the FactoryBuilder
+     * @param parent the parent node (null if 'root')
+     * @param node the node just completed
+     */
+    void onNodeCompleted( FactoryBuilderSupport builder, Object parent, Object node );
+
+    void setParent( FactoryBuilderSupport builder, Object parent, Object child );
+
+    void setChild( FactoryBuilderSupport builder, Object parent, Object child );
+}


[12/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy b/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
new file mode 100644
index 0000000..e033af8
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
@@ -0,0 +1,1080 @@
+/*
+ *  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.ast.builder
+
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.ConstructorNode
+import org.codehaus.groovy.ast.DynamicVariable
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.GenericsType
+import org.codehaus.groovy.ast.ImportNode
+import org.codehaus.groovy.ast.InnerClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.MixinNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.PropertyNode
+import org.codehaus.groovy.ast.VariableScope
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.ArrayExpression
+import org.codehaus.groovy.ast.expr.AttributeExpression
+import org.codehaus.groovy.ast.expr.BinaryExpression
+import org.codehaus.groovy.ast.expr.BitwiseNegationExpression
+import org.codehaus.groovy.ast.expr.BooleanExpression
+import org.codehaus.groovy.ast.expr.CastExpression
+import org.codehaus.groovy.ast.expr.ClassExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.ClosureListExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression
+import org.codehaus.groovy.ast.expr.DeclarationExpression
+import org.codehaus.groovy.ast.expr.ElvisOperatorExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.FieldExpression
+import org.codehaus.groovy.ast.expr.GStringExpression
+import org.codehaus.groovy.ast.expr.ListExpression
+import org.codehaus.groovy.ast.expr.MapEntryExpression
+import org.codehaus.groovy.ast.expr.MapExpression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.MethodPointerExpression
+import org.codehaus.groovy.ast.expr.NamedArgumentListExpression
+import org.codehaus.groovy.ast.expr.NotExpression
+import org.codehaus.groovy.ast.expr.PostfixExpression
+import org.codehaus.groovy.ast.expr.PrefixExpression
+import org.codehaus.groovy.ast.expr.PropertyExpression
+import org.codehaus.groovy.ast.expr.RangeExpression
+import org.codehaus.groovy.ast.expr.SpreadExpression
+import org.codehaus.groovy.ast.expr.SpreadMapExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.TernaryExpression
+import org.codehaus.groovy.ast.expr.TupleExpression
+import org.codehaus.groovy.ast.expr.UnaryMinusExpression
+import org.codehaus.groovy.ast.expr.UnaryPlusExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.AssertStatement
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.BreakStatement
+import org.codehaus.groovy.ast.stmt.CaseStatement
+import org.codehaus.groovy.ast.stmt.CatchStatement
+import org.codehaus.groovy.ast.stmt.ContinueStatement
+import org.codehaus.groovy.ast.stmt.EmptyStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.ast.stmt.SwitchStatement
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement
+import org.codehaus.groovy.ast.stmt.ThrowStatement
+import org.codehaus.groovy.ast.stmt.TryCatchStatement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+import org.codehaus.groovy.runtime.MethodClosure
+import org.codehaus.groovy.syntax.Token
+import org.codehaus.groovy.syntax.Types
+
+/**
+ * Handles parsing the properties from the closure into values that can be referenced.
+ * 
+ * This object is very stateful and not threadsafe. It accumulates expressions in the 
+ * 'expression' field as they are found and executed within the DSL. 
+ * 
+ * Note: this class consists of many one-line method calls. A better implementation
+ * might be to take a declarative approach and replace the one-liners with map entries. 
+ * 
+ * @author Hamlet D'Arcy
+ */
+class AstSpecificationCompiler implements GroovyInterceptable {
+
+    private final List<ASTNode> expression = []
+
+    /**
+     * Creates the DSL compiler.
+     */
+    AstSpecificationCompiler(@DelegatesTo(AstSpecificationCompiler) Closure spec) {
+        spec.delegate = this
+        spec()
+    }
+
+    /**
+     * Gets the current generated expression.
+     */
+    List<ASTNode> getExpression() {
+        return expression
+    }
+
+    /**
+    * This method takes a List of Classes (a "spec"), and makes sure that the expression field 
+    * contains those classes. It is a safety mechanism to enforce that the DSL is being called
+    * properly. 
+    * 
+    * @param methodName
+    *   the name of the method within the DSL that is being invoked. Used in creating error messages. 
+    * @param spec
+    *   the list of Class objects that the method expects to have in the expression field when invoked.
+    * @return 
+    *   the portions of the expression field that adhere to the spec. 
+    */ 
+    private List<ASTNode> enforceConstraints(String methodName, List<Class> spec) {
+
+        // enforce that the correct # arguments was passed
+        if (spec.size() != expression.size()) {
+            throw new IllegalArgumentException("$methodName could not be invoked. Expected to receive parameters $spec but found ${expression?.collect { it.class }}")
+        }
+
+        // enforce types and collect result
+        (0..(spec.size() - 1)).collect { int it ->
+            def actualClass = expression[it].class
+            def expectedClass = spec[it]
+            if (!expectedClass.isAssignableFrom(actualClass)) {
+                throw new IllegalArgumentException("$methodName could not be invoked. Expected to receive parameters $spec but found ${expression?.collect { it.class }}")
+            }
+            expression[it]
+        }
+    }
+
+    /**
+    * This method helps you take Closure parameters to a method and bundle them into 
+    * constructor calls to a specific ASTNode subtype. 
+    * @param name 
+    *       name of object being constructed, used to create helpful error message. 
+    * @param argBlock
+    *       the actual parameters being specified for the node
+    * @param constructorStatement
+    *       the type specific construction code that will be run
+    */ 
+    private void captureAndCreateNode(String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, Closure constructorStatement) {
+        if (!argBlock) throw new IllegalArgumentException("nodes of type $name require arguments to be specified")
+
+        def oldProps = new ArrayList(expression)
+        expression.clear()
+        new AstSpecificationCompiler(argBlock)
+        def result = constructorStatement(expression) // invoke custom constructor for node
+        expression.clear()
+        expression.addAll(oldProps)
+        expression.add(result)
+    }
+
+    /**
+    * Helper method to convert a DSL invocation into an ASTNode instance. 
+    * 
+    * @param target     
+    *       the class you are going to create
+    * @param typeAlias  
+    *       the DSL keyword that was used to invoke this type
+    * @param ctorArgs   
+    *       a specification of what arguments the constructor expects
+    * @param argBlock   
+    *       the single closure argument used during invocation
+    */ 
+    private void makeNode(Class target, String typeAlias, List<Class<? super ASTNode>> ctorArgs, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode(target.class.simpleName, argBlock) {
+            target.newInstance(*enforceConstraints(typeAlias, ctorArgs))
+        }
+    }
+
+    /**
+    * Helper method to convert a DSL invocation with a list of parameters specified 
+    * in a Closure into an ASTNode instance. 
+    * 
+    * @param target     
+    *       the class you are going to create
+    * @param argBlock   
+    *       the single closure argument used during invocation
+    */ 
+    private void makeNodeFromList(Class target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        //todo: add better error handling?
+        captureAndCreateNode(target.simpleName, argBlock) {
+            target.newInstance(new ArrayList(expression))
+        }
+    }
+
+    /**
+    * Helper method to convert a DSL invocation with a String parameter into a List of ASTNode instances. 
+    * 
+    * @param argBlock   
+    *       the single closure argument used during invocation
+    * @param input   
+    *       the single String argument used during invocation
+    */ 
+    private void makeListOfNodes(@DelegatesTo(AstSpecificationCompiler) Closure argBlock, String input) {
+        captureAndCreateNode(input, argBlock) {
+            new ArrayList(expression)
+        }
+    }
+
+    /**
+    * Helper method to convert a DSL invocation with a String parameter into an Array of ASTNode instances. 
+    * 
+    * @param argBlock   
+    *       the single closure argument used during invocation
+    * @param target   
+    *       the target type
+    */ 
+    private void makeArrayOfNodes(Object target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode(target.class.simpleName, argBlock) {
+            expression.toArray(target)
+        }
+    }
+    
+    /**
+    * Helper method to convert a DSL invocation into an ASTNode instance when a Class parameter is specified. 
+    * 
+    * @param target     
+    *       the class you are going to create
+    * @param alias  
+    *       the DSL keyword that was used to invoke this type
+    * @param spec
+    *       the list of Classes that you expect to be present as parameters
+    * @param argBlock   
+    *       the single closure argument used during invocation
+    * @param type 
+    *       a type parameter
+    */ 
+    private void makeNodeWithClassParameter(Class target, String alias, List<Class> spec, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, Class type) {
+        captureAndCreateNode(target.class.simpleName, argBlock) {
+            expression.add(0, ClassHelper.make(type))
+            target.newInstance(*enforceConstraints(alias, spec))
+        }
+    }
+
+    private void makeNodeWithStringParameter(Class target, String alias, List<Class> spec, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, String text) {
+        captureAndCreateNode(target.class.simpleName, argBlock) {
+            expression.add(0, text)
+            target.newInstance(*enforceConstraints(alias, spec))
+        }
+    }
+
+    /**
+     * Creates a CastExpression.
+     */
+    void cast(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeWithClassParameter(CastExpression, 'cast', [ClassNode, Expression], argBlock, type)
+    }
+
+    /**
+     * Creates an ConstructorCallExpression.
+     */
+    void constructorCall(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeWithClassParameter(ConstructorCallExpression, 'constructorCall', [ClassNode, Expression], argBlock, type)
+    }
+
+    /**
+     * Creates a MethodCallExpression.
+     */
+    void methodCall(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(MethodCallExpression, 'methodCall', [Expression, Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates an AnnotationConstantExpression.
+     */
+    void annotationConstant(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(AnnotationConstantExpression, 'annotationConstant', [AnnotationNode], argBlock)
+    }
+
+    /**
+     * Creates a PostfixExpression.
+     */
+    void postfix(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(PostfixExpression, 'postfix', [Expression, Token], argBlock)
+    }
+
+    /**
+     * Creates a FieldExpression.
+     */
+    void field(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(FieldExpression, 'field', [FieldNode], argBlock)
+    }
+
+    /**
+     * Creates a MapExpression.
+     */
+    void map(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeFromList(MapExpression, argBlock)
+    }
+
+    /**
+     * Creates a TupleExpression.
+     */
+    void tuple(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeFromList(TupleExpression, argBlock)
+    }
+
+    /**
+     * Creates a MapEntryExpression.
+     */
+    void mapEntry(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(MapEntryExpression, 'mapEntry', [Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates a gString.
+     */
+    void gString(String verbatimText, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeWithStringParameter(GStringExpression, 'gString', [String, List, List], argBlock, verbatimText)
+    }
+
+
+    /**
+     * Creates a methodPointer.
+     */
+
+    void methodPointer(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(MethodPointerExpression, 'methodPointer', [Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates a property.
+     */
+    void property(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(PropertyExpression, 'property', [Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates a RangeExpression.
+     */
+    void range(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(RangeExpression, 'range', [Expression, Expression, Boolean], argBlock)
+    }
+
+    /**
+     * Creates EmptyStatement.
+     */
+    void empty() {
+        expression << EmptyStatement.INSTANCE
+    }
+
+    /**
+     * Creates a label.
+     */
+    void label(String label) {
+        expression << label
+    }
+
+    /**
+     * Creates an ImportNode.
+     */
+    void importNode(Class target, String alias = null) {
+        expression << new ImportNode(ClassHelper.make(target), alias)
+    }
+
+    /**
+     * Creates a CatchStatement.
+     */
+    void catchStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(CatchStatement, 'catchStatement', [Parameter, Statement], argBlock)
+    }
+
+    /**
+     * Creates a ThrowStatement.
+     */
+    void throwStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ThrowStatement, 'throwStatement', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a SynchronizedStatement.
+     */
+    void synchronizedStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(SynchronizedStatement, 'synchronizedStatement', [Expression, Statement], argBlock)
+    }
+
+    /**
+     * Creates a ReturnStatement.
+     */
+    void returnStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ReturnStatement, 'returnStatement', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a TernaryExpression.
+     */
+
+    private void ternary(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(TernaryExpression, 'ternary', [BooleanExpression, Expression, Expression], argBlock)
+    }
+
+
+    /**
+     * Creates an ElvisOperatorExpression.
+     */
+    void elvisOperator(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ElvisOperatorExpression, 'elvisOperator', [Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates a BreakStatement.
+     */
+    void breakStatement(String label = null) {
+        if (label) {
+            expression << new BreakStatement(label)
+        } else {
+            expression << new BreakStatement()
+        }
+    }
+
+    /**
+     * Creates a ContinueStatement.
+     */
+    void continueStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
+        if (!argBlock) {
+            expression << new ContinueStatement()
+        } else {
+            makeNode(ContinueStatement, 'continueStatement', [String], argBlock)
+        }
+    }
+
+    /**
+     * Create a CaseStatement.
+     */
+    void caseStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(CaseStatement, 'caseStatement', [Expression, Statement], argBlock)
+    }
+
+    /**
+     * Creates a BlockStatement.
+     */
+    void defaultCase(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        block(argBlock) // same as arg block
+    }
+
+    /**
+     * Creates a PrefixExpression.
+     */
+    void prefix(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(PrefixExpression, 'prefix', [Token, Expression], argBlock)
+    }
+
+    /**
+     * Creates a NotExpression.
+     */
+    void not(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(NotExpression, 'not', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a DynamicVariable.
+     */
+    void dynamicVariable(String variable, boolean isStatic = false) {
+        expression << new DynamicVariable(variable, isStatic)
+    }
+
+    /**
+     * Creates a ClassNode[].
+     */
+    void exceptions(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeArrayOfNodes([] as ClassNode[], argBlock)
+    }
+
+    /**
+     * Designates a list of AnnotationNodes.
+     */
+    void annotations(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<AnnotationNode>")
+    }
+
+
+    /**
+     * Designates a list of MethodNodes.
+     */
+    void methods(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<MethodNode>")
+    }
+
+    /**
+     * Designates a list of ConstructorNodes.
+     */
+    void constructors(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<ConstructorNode>")
+    }
+
+    /**
+     * Designates a list of {@code PropertyNode}s.
+     */
+    void properties(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<PropertyNode>")
+    }
+
+    /**
+     * Designates a list of {@code FieldNode}s.
+     */
+    void fields(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<FieldNode>")
+    }
+
+    /**
+     * Designates a list of ConstantExpressions.
+     */
+
+    void strings(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<ConstantExpression>")
+    }
+
+    /**
+     * Designates a list of Expressions.
+     */
+
+    void values(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<Expression>")
+    }
+
+    /**
+     * Creates a boolean value.
+     */
+    void inclusive(boolean value) {
+        expression << value
+    }
+
+    /**
+     * Creates a ConstantExpression.
+     */
+    void constant(Object value) {
+        expression << new ConstantExpression(value)
+    }
+
+    /**
+     * Creates an IfStatement.
+     */
+    void ifStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(IfStatement, 'ifStatement', [BooleanExpression, Statement, Statement], argBlock)
+    }
+
+    /**
+     * Creates a SpreadExpression.
+     */
+    void spread(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(SpreadExpression, 'spread', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a SpreadMapExpression.
+     */
+    void spreadMap(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(SpreadMapExpression, 'spreadMap', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a WhileStatement.
+     */
+    void whileStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(WhileStatement, 'whileStatement', [BooleanExpression, Statement], argBlock)
+    }
+
+    /**
+     * Create a ForStatement.
+     */
+    void forStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ForStatement, 'forStatement', [Parameter, Expression, Statement], argBlock)
+    }
+
+    /**
+     * Creates a ClosureListExpression.
+     */
+    void closureList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeFromList(ClosureListExpression, argBlock)
+    }
+
+    /**
+     * Creates a DeclarationExpression.
+     */
+    void declaration(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(DeclarationExpression, 'declaration', [Expression, Token, Expression], argBlock)
+    }
+
+    /**
+     * Creates a ListExpression.
+     */
+    void list(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeFromList(ListExpression, argBlock)
+    }
+
+    /**
+     * Creates a BitwiseNegationExpression.
+     */
+    void bitwiseNegation(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(BitwiseNegationExpression, 'bitwiseNegation', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a ClosureExpression.
+     */
+    void closure(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ClosureExpression, 'closure', [Parameter[], Statement], argBlock)
+    }
+
+    /**
+     * Creates a BooleanExpression.
+     */
+    void booleanExpression(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(BooleanExpression, 'booleanExpression', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a BinaryExpression.
+     */
+    void binary(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(BinaryExpression, 'binary', [Expression, Token, Expression], argBlock)
+    }
+
+    /**
+     * Creates a UnaryPlusExpression.
+     */
+    void unaryPlus(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(UnaryPlusExpression, 'unaryPlus', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a ClassExpression.
+     */
+    void classExpression(Class type) {
+        expression << new ClassExpression(ClassHelper.make(type))
+    }
+
+    /**
+     * Creates a UnaryMinusExpression
+     */
+    void unaryMinus(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(UnaryMinusExpression, 'unaryMinus', [Expression], argBlock)
+    }
+
+    /**
+     * Creates an AttributeExpression.
+     */
+    void attribute(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(AttributeExpression, 'attribute', [Expression, Expression], argBlock)
+    }
+
+    /**
+     * Creates an ExpressionStatement.
+     */
+    void expression(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNode(ExpressionStatement, 'expression', [Expression], argBlock)
+    }
+
+    /**
+     * Creates a NamedArgumentListExpression.
+     */
+    void namedArgumentList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeNodeFromList(NamedArgumentListExpression, argBlock)
+    }
+
+    /**
+     * Creates a ClassNode[].
+     */
+    void interfaces(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<ClassNode>")
+    }
+
+    /**
+     * Creates a MixinNode[].
+     */
+    void mixins(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<MixinNode>")
+    }
+
+    /**
+     * Creates a GenericsTypes[].
+     */
+    void genericsTypes(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, "List<GenericsTypes>")
+    }
+
+    /**
+     * Creates a ClassNode.
+     */
+    void classNode(Class target) {
+        expression << ClassHelper.make(target, false)
+    }
+
+    /**
+     * Creates a Parameter[].
+     */
+    void parameters(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeArrayOfNodes([] as Parameter[], argBlock)
+    }
+
+    /**
+     * Creates a BlockStatement.
+     */
+    void block(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("BlockStatement", argBlock) {
+            return new BlockStatement(new ArrayList(expression), new VariableScope())
+        }
+    }
+
+    /**
+     * Creates a Parameter.
+     */
+    void parameter(Map<String, Class> args, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
+        if (!args) throw new IllegalArgumentException()
+        if (args.size() > 1) throw new IllegalArgumentException()
+
+        //todo: add better error handling?
+        if (argBlock) {
+            args.each {name, type ->
+                captureAndCreateNode("Parameter", argBlock) {
+                    new Parameter(ClassHelper.make(type), name, expression[0])
+                }
+            }
+        } else {
+            args.each {name, type ->
+                expression << (new Parameter(ClassHelper.make(type), name))
+            }
+        }
+    }
+
+    /**
+     * Creates an ArrayExpression.
+     */
+    void array(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("ArrayExpression", argBlock) {
+            new ArrayExpression(ClassHelper.make(type), new ArrayList(expression))
+        }
+    }
+
+    /**
+     * Creates a GenericsType.
+     */
+    void genericsType(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
+        if (argBlock) {
+            captureAndCreateNode("GenericsType", argBlock) {
+                new GenericsType(ClassHelper.make(type), expression[0] as ClassNode[], expression[1])
+            }
+        } else {
+            expression << new GenericsType(ClassHelper.make(type))
+        }
+    }
+
+    /**
+     * Creates a list of upperBound ClassNodes.
+     */
+    void upperBound(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        makeListOfNodes(argBlock, 'List<ClassNode>')
+    }
+
+    /**
+     * Create lowerBound ClassNode.
+     */
+    void lowerBound(Class target) {
+        expression << ClassHelper.make(target)
+    }
+
+    /**
+     * Creates a 2 element list of name and Annotation. Used with Annotation Members.
+     */
+    void member(String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("Annotation Member", argBlock) {
+            [name, expression[0]]
+        }
+    }
+
+    /**
+     * Creates an ArgumentListExpression.
+     */
+    void argumentList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        if (!argBlock) {
+            expression << new ArgumentListExpression()
+        } else {
+            makeNodeFromList(ArgumentListExpression, argBlock)
+        }
+    }
+
+    /**
+     * Creates an AnnotationNode.
+     */
+    void annotation(Class target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
+        if (argBlock) {
+            //todo: add better error handling
+            captureAndCreateNode("ArgumentListExpression", argBlock) {
+                def node = new AnnotationNode(ClassHelper.make(target))
+                expression?.each {
+                    node.addMember(it[0], it[1])
+                }
+                node
+            }
+        } else {
+            expression << new AnnotationNode(ClassHelper.make(target))
+        }
+    }
+
+    /**
+     * Creates a MixinNode.
+     */
+    void mixin(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("AttributeExpression", argBlock) {
+            if (expression.size() > 1) {
+                new MixinNode(name, modifiers, expression[0], new ArrayList(expression[1]) as ClassNode[])
+            } else {
+                new MixinNode(name, modifiers, expression[0])
+            }
+        }
+    }
+
+    /**
+     * Creates a ClassNode
+     */
+    void classNode(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("ClassNode", argBlock) {
+            def result = new ClassNode(name, modifiers,
+                    expression[0],
+                    new ArrayList(expression[1]) as ClassNode[],
+                    new ArrayList(expression[2]) as MixinNode[]
+            )
+            while (expression.size() > 3) {
+                if (!List.isAssignableFrom(expression[3].getClass())) {
+                    throw new IllegalArgumentException("Expecting to find list of additional items instead found: " + expression[3].getClass())
+                }
+                if (expression[3].size() > 0) {
+                    def clazz = expression[3][0].getClass()
+                    switch(clazz) {
+                        case GenericsType:
+                            result.setGenericsTypes(new ArrayList(expression[3]) as GenericsType[])
+                            break
+                        case MethodNode:
+                            expression[3].each{ result.addMethod(it) }
+                            break
+                        case ConstructorNode:
+                            expression[3].each{ result.addConstructor(it) }
+                            break
+                        case PropertyNode:
+                            expression[3].each{
+                                it.field.owner = result
+                                result.addProperty(it)
+                            }
+                            break
+                        case FieldNode:
+                            expression[3].each{
+                                it.owner = result
+                                result.addField(it)
+                            }
+                            break
+                        case AnnotationNode:
+                            result.addAnnotations(new ArrayList(expression[3]))
+                            break
+                        default:
+                            throw new IllegalArgumentException("Unexpected item found in ClassNode spec. Expecting [Field|Method|Property|Constructor|Annotation|GenericsType] but found: $clazz.name")
+                    }
+                }
+                expression.remove(3)
+            }
+            result
+        }
+    }
+
+    /**
+     * Creates an AssertStatement.
+     */
+    void assertStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("AssertStatement", argBlock) {
+            if (expression.size() < 2) {
+                new AssertStatement(*enforceConstraints('assertStatement', [BooleanExpression]))
+            } else {
+                new AssertStatement(*enforceConstraints('assertStatement', [BooleanExpression, Expression]))
+            }
+        }
+    }
+
+    /**
+     * Creates a TryCatchStatement.
+     */
+    void tryCatch(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("TryCatchStatement", argBlock) {
+            def result = new TryCatchStatement(expression[0], expression[1])
+            def catchStatements = expression.tail().tail()
+            catchStatements.each {statement -> result.addCatch(statement) }
+            return result
+        }
+    }
+
+    /**
+     * Creates a VariableExpression.
+     */
+    void variable(String variable) {
+        expression << new VariableExpression(variable)
+    }
+
+    /**
+     * Creates a MethodNode.
+     */
+    void method(String name, int modifiers, Class returnType, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("MethodNode", argBlock) {
+            //todo: enforce contract
+            def result = new MethodNode(name, modifiers, ClassHelper.make(returnType), expression[0], expression[1], expression[2])
+            if (expression[3]) {
+                result.addAnnotations(new ArrayList(expression[3]))
+            }
+            result
+        }
+    }
+
+    /**
+     * Creates a token.
+     */
+    void token(String value) {
+        if (value == null) throw new IllegalArgumentException("Null: value")
+
+        def tokenID = Types.lookupKeyword(value)
+        if (tokenID == Types.UNKNOWN) {
+            tokenID = Types.lookupSymbol(value)
+        }
+        if (tokenID == Types.UNKNOWN) throw new IllegalArgumentException("could not find token for $value")
+
+        expression << new Token(tokenID, value, -1, -1)
+    }
+
+    /**
+     * Creates a RangeExpression.
+     */
+    void range(Range range) {
+        if (range == null) throw new IllegalArgumentException('Null: range')
+        expression << new RangeExpression(new ConstantExpression(range.getFrom()), new ConstantExpression(range.getTo()), true) //default is inclusive
+    }
+
+    /**
+     * Creates a SwitchStatement.
+     */
+    void switchStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("SwitchStatement", argBlock) {
+            def switchExpression = expression.head()
+            def caseStatements = expression.tail().tail()
+            def defaultExpression = expression.tail().head()
+            new SwitchStatement(switchExpression, caseStatements, defaultExpression)
+        }
+    }
+
+    /**
+     * Creates a mapEntry.
+     */
+    void mapEntry(Map map) {
+        map.entrySet().each {
+            expression << new MapEntryExpression(
+                    new ConstantExpression(it.key),
+                    new ConstantExpression(it.value))
+        }
+    }
+
+    //
+    // todo: these methods can still be reduced smaller
+    //
+
+    /**
+     * Creates a FieldNode.
+     */
+    void fieldNode(String name, int modifiers, Class type, Class owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("FieldNode", argBlock) {
+            def annotations = null
+            if (expression.size() > 1) {
+                annotations = expression[1]
+                expression.remove(1)
+            }
+            expression.add(0, ClassHelper.make(owner))
+            expression.add(0, ClassHelper.make(type))
+            expression.add(0, modifiers)
+            expression.add(0, name)
+            def result = new FieldNode(*enforceConstraints('fieldNode', [String, Integer, ClassNode, ClassNode, Expression]))
+            if (annotations) {
+                result.addAnnotations(new ArrayList(annotations))
+            }
+            result
+        }
+    }
+
+    /**
+     * Creates an inner class.
+     */
+    void innerClass(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("InnerClassNode", argBlock) {
+            //todo: enforce contract
+            new InnerClassNode(
+                    expression[0],
+                    name,
+                    modifiers,
+                    expression[1],
+                    new ArrayList(expression[2]) as ClassNode[],
+                    new ArrayList(expression[3]) as MixinNode[])
+        }
+    }
+
+    /**
+     * Creates a PropertyNode.
+     */
+    void propertyNode(String name, int modifiers, Class type, Class owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        //todo: improve error handling?
+        captureAndCreateNode("PropertyNode", argBlock) {
+            def annotations = null
+            // check if the last expression looks like annotations
+            if (List.isAssignableFrom(expression[-1].getClass())) {
+                annotations = expression[-1]
+                expression.remove(expression.size() - 1)
+            }
+            def result = new PropertyNode(name, modifiers, ClassHelper.make(type), ClassHelper.make(owner),
+                    expression[0],  // initial value (possibly null)
+                    expression[1],  // getter block (possibly null)
+                    expression[2])  // setter block (possibly null)
+            if (annotations) {
+                result.addAnnotations(new ArrayList(annotations))
+            }
+            result
+        }
+    }
+
+    /**
+     * Creates a StaticMethodCallExpression.
+     */
+    void staticMethodCall(Class target, String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("StaticMethodCallExpression", argBlock) {
+            expression.add(0, name)
+            expression.add(0, ClassHelper.make(target))
+            new StaticMethodCallExpression(*enforceConstraints('staticMethodCall', [ClassNode, String, Expression]))
+        }
+    }
+
+    /**
+     * Creates a StaticMethodCallExpression.
+     */
+    void staticMethodCall(MethodClosure target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("StaticMethodCallExpression", argBlock) {
+            expression.add(0, target.method)
+            expression.add(0, ClassHelper.makeWithoutCaching(target.owner.class, false))
+            new StaticMethodCallExpression(*enforceConstraints('staticMethodCall', [ClassNode, String, Expression]))
+        }
+    }
+
+    /**
+     * Creates a ConstructorNode.
+     */
+    void constructor(int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
+        captureAndCreateNode("ConstructorNode", argBlock) {
+            def annotations = null
+            if (expression.size() > 3) {
+                annotations = expression[3]
+                expression.remove(3)
+            }
+            expression.add(0, modifiers)
+            def result = new ConstructorNode(*enforceConstraints('constructor', [Integer, Parameter[], ClassNode[], Statement]))
+            if (annotations) {
+                result.addAnnotations(new ArrayList(annotations))
+            }
+            result
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/ast/builder/AstStringCompiler.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/ast/builder/AstStringCompiler.groovy b/src/main/groovy/org/codehaus/groovy/ast/builder/AstStringCompiler.groovy
new file mode 100644
index 0000000..1ea3970
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/ast/builder/AstStringCompiler.groovy
@@ -0,0 +1,63 @@
+/*
+ *  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.ast.builder
+
+import groovy.transform.PackageScope
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.ModuleNode
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.CompilerConfiguration
+
+/**
+ * This class handles converting Strings to ASTNode lists.
+ *
+ * @author Hamlet D'Arcy
+ */
+@PackageScope class AstStringCompiler {
+    
+    /**
+     * Performs the String source to {@link List} of {@link ASTNode}.
+     *
+     * @param script
+     *      a Groovy script in String form
+     * @param compilePhase
+     *      the int based CompilePhase to compile it to.
+     * @param statementsOnly
+     */
+    List<ASTNode> compile(String script, CompilePhase compilePhase, boolean statementsOnly) {
+        def scriptClassName = "script" + System.currentTimeMillis()
+        GroovyClassLoader classLoader = new GroovyClassLoader()
+        GroovyCodeSource codeSource = new GroovyCodeSource(script, scriptClassName + ".groovy", "/groovy/script")
+        CompilationUnit cu = new CompilationUnit(CompilerConfiguration.DEFAULT, codeSource.codeSource, classLoader)
+        cu.addSource(codeSource.getName(), script);
+        cu.compile(compilePhase.getPhaseNumber())
+        // collect all the ASTNodes into the result, possibly ignoring the script body if desired
+        return cu.ast.modules.inject([]) {List acc, ModuleNode node ->
+            if (node.statementBlock) acc.add(node.statementBlock)
+            node.classes?.each {
+                if (!(it.name == scriptClassName && statementsOnly)) {
+                    acc << it
+                }
+            }
+            acc
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/classgen/genArrayAccess.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/classgen/genArrayAccess.groovy b/src/main/groovy/org/codehaus/groovy/classgen/genArrayAccess.groovy
new file mode 100644
index 0000000..08cb68a
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/classgen/genArrayAccess.groovy
@@ -0,0 +1,146 @@
+/*
+ *  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.classgen
+
+println """
+package org.codehaus.groovy.runtime.dgmimpl;
+
+import groovy.lang.MetaClassImpl;
+import groovy.lang.MetaMethod;
+import org.codehaus.groovy.runtime.callsite.CallSite;
+import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.ReflectionCache;
+
+public class ArrayOperations {
+  ${genInners()}
+}
+"""
+
+def genInners () {
+    def res = ""
+
+    final Map primitives = [
+            "boolean": "Boolean",
+            "byte": "Byte",
+            "char": "Character",
+            "short": "Short",
+            "int": "Integer",
+            "long": "Long",
+            "float": "Float",
+            "double": "Double"
+    ]
+
+    primitives.each {primName, clsName ->
+        res += """
+         public static class ${clsName}ArrayGetAtMetaMethod extends ArrayGetAtMetaMethod {
+            private static final CachedClass ARR_CLASS = ReflectionCache.getCachedClass(${primName}[].class);
+
+            public Class getReturnType() {
+                return ${clsName}.class;
+            }
+
+            public final CachedClass getDeclaringClass() {
+                return ARR_CLASS;
+            }
+
+            public Object invoke(Object object, Object[] args) {
+                final ${primName}[] objects = (${primName}[]) object;
+                return objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)];
+            }
+
+            public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
+                if (!(args [0] instanceof Integer))
+                  return PojoMetaMethodSite.createNonAwareCallSite(site, metaClass, metaMethod, params, args);
+                else
+                    return new PojoMetaMethodSite(site, metaClass, metaMethod, params) {
+                        public Object invoke(Object receiver, Object[] args) {
+                            final ${primName}[] objects = (${primName}[]) receiver;
+                            return objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)];
+                        }
+
+                        public Object callBinop(Object receiver, Object arg) {
+                            if ((receiver instanceof ${primName}[] && arg instanceof Integer)
+                                    && checkMetaClass()) {
+                                final ${primName}[] objects = (${primName}[]) receiver;
+                                return objects[normaliseIndex(((Integer) arg).intValue(), objects.length)];
+                            }
+                            else
+                              return super.callBinop(receiver,arg);
+                        }
+
+                        public Object invokeBinop(Object receiver, Object arg) {
+                            final ${primName}[] objects = (${primName}[]) receiver;
+                            return objects[normaliseIndex(((Integer) arg).intValue(), objects.length)];
+                        }
+                    };
+            }
+         }
+
+
+        public static class ${clsName}ArrayPutAtMetaMethod extends ArrayPutAtMetaMethod {
+            private static final CachedClass OBJECT_CLASS = ReflectionCache.OBJECT_CLASS;
+            private static final CachedClass ARR_CLASS = ReflectionCache.getCachedClass(${primName}[].class);
+            private static final CachedClass [] PARAM_CLASS_ARR = new CachedClass[] {INTEGER_CLASS, OBJECT_CLASS};
+
+            public ${clsName}ArrayPutAtMetaMethod() {
+                parameterTypes = PARAM_CLASS_ARR;
+            }
+
+            public final CachedClass getDeclaringClass() {
+                return ARR_CLASS;
+            }
+
+            public Object invoke(Object object, Object[] args) {
+                final ${primName}[] objects = (${primName}[]) object;
+                final int index = normaliseIndex(((Integer) args[0]).intValue(), objects.length);
+                Object newValue = args[1];
+                if (!(newValue instanceof ${clsName})) {
+                    Number n = (Number) newValue;
+                    objects[index] = ((Number)newValue).${primName}Value();
+                }
+                else
+                  objects[index] = ((${clsName})args[1]).${primName}Value();
+                return null;
+            }
+
+            public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
+                if (!(args [0] instanceof Integer) || !(args [1] instanceof ${clsName}))
+                  return PojoMetaMethodSite.createNonAwareCallSite(site, metaClass, metaMethod, params, args);
+                else
+                    return new PojoMetaMethodSite(site, metaClass, metaMethod, params) {
+                        public Object call(Object receiver, Object[] args) {
+                            if ((receiver instanceof ${primName}[] && args[0] instanceof Integer && args[1] instanceof ${clsName} )
+                                    && checkMetaClass()) {
+                                final ${primName}[] objects = (${primName}[]) receiver;
+                                objects[normaliseIndex(((Integer) args[0]).intValue(), objects.length)] = ((${clsName})args[1]).${primName}Value();
+                                return null;
+                            }
+                            else
+                              return super.call(receiver,args);
+                        }
+                    };
+            }
+        }
+
+       """
+    }
+
+    res
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/classgen/genArrays.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/classgen/genArrays.groovy b/src/main/groovy/org/codehaus/groovy/classgen/genArrays.groovy
new file mode 100644
index 0000000..9bbe3cf
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/classgen/genArrays.groovy
@@ -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.classgen
+
+print """
+
+public class ArrayUtil {
+   ${genMethods()}
+}
+
+"""
+
+def genMethods () {
+    def res = ""
+    for (i in 1..250)
+      res += "\n\n" + genMethod (i)
+    res
+}
+
+def genMethod (int paramNum) {
+    def res = "public static Object [] createArray ("
+    for (k in 0..<paramNum) {
+        res += "Object arg" + k
+        if (k != paramNum-1)
+          res += ", "
+    }
+    res += ") {\n"
+    res += "return new Object [] {\n"
+        for (k in 0..<paramNum) {
+            res += "arg" + k
+            if (k != paramNum-1)
+              res += ", "
+        }
+        res += "};\n"
+    res += "}"
+    res
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/classgen/genDgmMath.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/classgen/genDgmMath.groovy b/src/main/groovy/org/codehaus/groovy/classgen/genDgmMath.groovy
new file mode 100644
index 0000000..71bdd5f
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/classgen/genDgmMath.groovy
@@ -0,0 +1,87 @@
+/*
+ *  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.classgen
+
+def types = ["Integer", "Long", "Float", "Double"]
+
+def getMath (a,b) {
+    if (a == "Double" || b == "Double" || a == "Float" || b == "Float")
+      return "FloatingPointMath"
+
+    if (a == "Long" || b == "Long")
+      return "LongMath"
+
+    "IntegerMath"
+}
+
+println """
+public CallSite createPojoCallSite(CallSite site, MetaClassImpl metaClass, MetaMethod metaMethod, Class[] params, Object receiver, Object[] args) {
+    NumberMath m = NumberMath.getMath((Number)receiver, (Number)args[0]);
+"""
+
+types.each {
+    a ->
+    print """
+    if (receiver instanceof $a) {"""
+    types.each {
+        b ->
+        print """
+        if (args[0] instanceof $b)
+            return new NumberNumberCallSite (site, metaClass, metaMethod, params, (Number)receiver, (Number)args[0]){
+                public final Object invoke(Object receiver, Object[] args) {
+                    return ${getMath(a,b)}.INSTANCE.addImpl(($a)receiver,($b)args[0]);
+                }
+
+                public final Object invokeBinop(Object receiver, Object arg) {
+                    return ${getMath(a,b)}.INSTANCE.addImpl(($a)receiver,($b)arg);
+                }
+            };
+        """
+    }
+    println "}"
+}
+
+println """
+    return new NumberNumberCallSite (site, metaClass, metaMethod, params, (Number)receiver, (Number)args[0]){
+        public final Object invoke(Object receiver, Object[] args) {
+            return math.addImpl((Number)receiver,(Number)args[0]);
+        }
+
+        public final Object invokeBinop(Object receiver, Object arg) {
+            return math.addImpl((Number)receiver,(Number)arg);
+        }
+}
+"""
+
+for (i in 2..256) {
+    print "public Object invoke$i (Object receiver, "
+    for (j in 1..(i-1)) {
+        print "Object a$j, "
+    }
+    println "Object a$i) {"
+
+    print "  return invoke (receiver, new Object[] {"
+
+    for (j in 1..(i-1)) {
+        print "a$j, "
+    }
+    println "a$i} );"
+
+    println "}"
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/classgen/genMathModification.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/classgen/genMathModification.groovy b/src/main/groovy/org/codehaus/groovy/classgen/genMathModification.groovy
new file mode 100644
index 0000000..10cc7eb
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/classgen/genMathModification.groovy
@@ -0,0 +1,133 @@
+/*
+ *  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.classgen
+
+def ops = [
+        "plus",
+        "minus",
+        "multiply",
+        "div",
+        "or",
+        "and",
+        "xor",
+        "intdiv",
+        "mod",
+        "leftShift",
+        "rightShift",
+        "rightShiftUnsigned"
+]
+
+def numbers = ["Byte":"byte", "Short":"short", "Integer":"int", "Long":"long", "Float":"float", "Double":"double"]
+
+ops.each { op ->
+    numbers.each { wrappedType, type ->
+        println "public boolean ${type}_${op};";    
+    }
+}
+
+ops.each { op ->
+    println "if (\"${op}\".equals(name)) {"
+    numbers.each { wrappedType, type ->
+        println """if (klazz==${wrappedType}.class) {
+                ${type}_${op} = true;
+            }"""
+    }
+    println "if (klazz==Object.class) {"
+    numbers.each { wrappedType, type ->
+        println "${type}_${op} = true;"
+            }
+    println "}"
+    println "}"
+}
+
+ops.each { op ->
+    numbers.each { wrappedType1, type1 ->
+        numbers.each { wrappedType2, type2 ->
+            def math = getMath(wrappedType1, wrappedType2)
+            if (math [op]) {
+                println """public static ${math.resType} ${op}(${type1} op1, ${type2} op2) {
+                   if (instance.${type1}_${op}) {
+                      return ${op}Slow(op1, op2);
+                   }
+                   else {
+                      return ${math.resType != type1 ? "((" + math.resType+ ")op1)" : "op1"} ${math[op]} ${math.resType != type2 ? "((" + math.resType+ ")op2)" : "op2"};
+                   }
+                }"""
+                println """private static ${math.resType} ${op}Slow(${type1} op1,${type2} op2) {
+                      return ((Number)InvokerHelper.invokeMethod(op1, "${op}", op2)).${math.resType}Value();
+                }"""
+            }
+        }
+    }
+}
+
+def isFloatingPoint(number) {
+    return number == "Double" || number == "Float";
+}
+
+def isLong(number) {
+    return number == "Long";
+}
+
+def getMath (left, right) {
+    if (isFloatingPoint(left) || isFloatingPoint(right)) {
+        return [
+                resType : "double",
+
+                plus : "+",
+                minus : "-",
+                multiply : "*",
+                div : "/",
+        ];
+    }
+    if (isLong(left) || isLong(right)){
+        return [
+                resType : "long",
+
+                plus : "+",
+                minus : "-",
+                multiply : "*",
+                div : "/",
+                or : "|",
+                and : "&",
+                xor : "^",
+                intdiv : "/",
+                mod : "%",
+                leftShift : "<<",
+                rightShift : ">>",
+                rightShiftUnsigned : ">>>"
+        ]
+    }
+    return [
+            resType : "int",
+
+            plus : "+",
+            minus : "-",
+            multiply : "*",
+            div : "/",
+            or : "|",
+            and : "&",
+            xor : "^",
+            intdiv : "/",
+            mod : "%",
+            leftShift : "<<",
+            rightShift : ">>",
+            rightShiftUnsigned : ">>>"
+    ]
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy b/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
new file mode 100644
index 0000000..7e84968
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
@@ -0,0 +1,301 @@
+/*
+ *  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.control.customizers
+
+import groovy.transform.CompilationUnitAware
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.expr.ClassExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ListExpression
+import org.codehaus.groovy.classgen.GeneratorContext
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.transform.ASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.Annotation
+
+/**
+ * This customizer allows applying an AST transformation to a source unit with
+ * several strategies.
+ *
+ * Creating a customizer with the {@link ASTTransformationCustomizer#ASTTransformationCustomizer(Class)
+ * class constructor} will trigger an AST transformation for
+ * each class node of a source unit. However, you cannot pass parameters to the annotation so the default values
+ * will be used. Writing :
+ * <pre>
+ *     def configuration = new CompilerConfiguration()
+ *     configuration.addCompilationCustomizers(new ASTTransformationCustomizer(Log))
+ *     def shell = new GroovyShell(configuration)
+ *     shell.evaluate("""
+ *        class MyClass {
+ *
+ *        }""")
+ * </pre>
+ *
+ * is equivalent to :
+ *
+ * <pre>
+ *     def shell = new GroovyShell()
+ *     shell.evaluate("""
+ *        &#64;Log
+ *        class MyClass {
+ *
+ *        }""")
+ * </pre>
+ *
+ * The class passed as a constructor parameter must be an AST transformation annotation.
+ *
+ * Alternatively, you can apply a global AST transformation by calling the
+ * {@link ASTTransformationCustomizer#ASTTransformationCustomizer(ASTTransformation) AST transformation
+ * constructor}. In that case, the transformation is applied once for the whole source unit.
+ *
+ * Unlike a global AST transformation declared in the META-INF/services/org.codehaus.groovy.transform.ASTTransformation
+ * file, which are applied if the file is in the classpath, using this customizer you'll have the choice to apply
+ * your transformation selectively. It can also be useful to debug global AST transformations without having to
+ * package your annotation in a jar file.
+ *
+ * @author Cedric Champeau
+ *
+ * @since 1.8.0
+ * 
+ */
+class ASTTransformationCustomizer extends CompilationCustomizer implements CompilationUnitAware {
+    private final AnnotationNode annotationNode;
+    final ASTTransformation transformation
+
+    protected CompilationUnit compilationUnit;
+    private boolean applied = false; // used for global AST transformations
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
+     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
+     * It's assumed that the annotation is not annotated with {@code GroovyASTTransformationClass} and so the
+     * second argument supplies the link to the ASTTransformation class that should be used.
+     * @param transformationAnnotation
+     * @param astTransformationClassName
+     * @param transformationClassLoader
+     */
+    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName, ClassLoader transformationClassLoader) {
+        super(findPhase(transformationAnnotation, astTransformationClassName, transformationClassLoader))
+        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, astTransformationClassName, transformationClassLoader)
+        this.transformation = clazz.newInstance()
+        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation. It's assumed that the annotation
+     * is not annotated with {@code GroovyASTTransformationClass} and so the second argument supplies the link to
+     * the ASTTransformation class that should be used.
+     * @param transformationAnnotation
+     * @param astTransformationClassName
+     */
+    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName) {
+        this(transformationAnnotation, astTransformationClassName, transformationAnnotation.classLoader)
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
+     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
+     * Additionally, you can pass a map of parameters that will be used to parameterize the annotation.
+     * It's assumed that the annotation is not annotated with {@code GroovyASTTransformationClass} and so the
+     * second argument supplies the link to the ASTTransformation class that should be used.
+     * @param transformationAnnotation
+     * @param astTransformationClassName
+     * @param transformationClassLoader
+     */
+    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName, ClassLoader transformationClassLoader) {
+        super(findPhase(transformationAnnotation, astTransformationClassName, transformationClassLoader))
+        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, astTransformationClassName, transformationClassLoader)
+        this.transformation = clazz.newInstance()
+        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
+        setAnnotationParameters(annotationParams)
+    }
+
+    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName) {
+        this(annotationParams, transformationAnnotation, transformationAnnotation.classLoader)
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
+     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
+     * @param transformationAnnotation
+     * @param transformationClassLoader
+     */
+    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, ClassLoader transformationClassLoader) {
+        super(findPhase(transformationAnnotation, transformationClassLoader))
+        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, transformationClassLoader)
+        this.transformation = clazz.newInstance()
+        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation.
+     * @param transformationAnnotation
+     */
+    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation) {
+        this(transformationAnnotation, transformationAnnotation.classLoader)
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified transformation.
+     */
+    ASTTransformationCustomizer(final ASTTransformation transformation) {
+        super(findPhase(transformation))
+        this.transformation = transformation
+        this.annotationNode = null
+    }
+
+    /**
+     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
+     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
+     * Additionally, you can pass a map of parameters that will be used to parameterize the annotation.
+     * @param transformationAnnotation
+     * @param transformationClassLoader
+     */
+    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, ClassLoader transformationClassLoader) {
+        super(findPhase(transformationAnnotation, transformationClassLoader))
+        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, transformationClassLoader)
+        this.transformation = clazz.newInstance()
+        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
+        setAnnotationParameters(annotationParams)
+    }
+
+    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation) {
+        this(annotationParams, transformationAnnotation, transformationAnnotation.classLoader)
+    }
+
+    ASTTransformationCustomizer(final Map annotationParams, final ASTTransformation transformation) {
+        this(transformation)
+        setAnnotationParameters(annotationParams)
+    }
+
+    void setCompilationUnit(CompilationUnit unit) {
+        compilationUnit = unit
+    }
+
+    private static Class<ASTTransformation> findASTTranformationClass(Class<? extends Annotation> anAnnotationClass, ClassLoader transformationClassLoader) {
+        final GroovyASTTransformationClass annotation = anAnnotationClass.getAnnotation(GroovyASTTransformationClass)
+        if (annotation==null) throw new IllegalArgumentException("Provided class doesn't look like an AST @interface")
+
+        Class[] classes = annotation.classes()
+        String[] classesAsStrings = annotation.value()
+        if (classes.length+classesAsStrings.length>1) {
+            throw new IllegalArgumentException("AST transformation customizer doesn't support AST transforms with multiple classes")
+        }
+        return classes?classes[0]:Class.forName(classesAsStrings[0], true, transformationClassLoader?:anAnnotationClass.classLoader)
+    }
+
+    private static Class<ASTTransformation> findASTTranformationClass(Class<? extends Annotation> anAnnotationClass, String astTransformationClassName, ClassLoader transformationClassLoader) {
+        return Class.forName(astTransformationClassName, true, transformationClassLoader?:anAnnotationClass.classLoader) as Class<ASTTransformation>
+    }
+
+    private static CompilePhase findPhase(ASTTransformation transformation) {
+        if (transformation==null) throw new IllegalArgumentException("Provided transformation must not be null")
+        final Class<?> clazz = transformation.class
+        final GroovyASTTransformation annotation = clazz.getAnnotation(GroovyASTTransformation)
+        if (annotation==null) throw new IllegalArgumentException("Provided ast transformation is not annotated with "+GroovyASTTransformation.name)
+
+        annotation.phase()
+    }
+
+    private static CompilePhase findPhase(Class<? extends Annotation> annotationClass, ClassLoader transformationClassLoader) {
+        Class<ASTTransformation> clazz = findASTTranformationClass(annotationClass, transformationClassLoader);
+
+        findPhase(clazz.newInstance())
+    }
+
+    private static CompilePhase findPhase(Class<? extends Annotation> annotationClass, String astTransformationClassName, ClassLoader transformationClassLoader) {
+        Class<ASTTransformation> clazz = findASTTranformationClass(annotationClass, astTransformationClassName, transformationClassLoader);
+
+        findPhase(clazz.newInstance())
+    }
+
+    /**
+     * Specify annotation parameters. For example, if the annotation is :
+     * <pre>@Log(value='logger')</pre>
+     * You could create an AST transformation customizer and specify the "value" parameter thanks to this method:
+     * <pre>annotationParameters = [value: 'logger']
+     *
+     * Note that you cannot specify annotation closure values directly. If the annotation you want to add takes
+     * a closure as an argument, you will have to set a {@link ClosureExpression} instead. This can be done by either
+     * creating a custom {@link ClosureExpression} from code, or using the {@link org.codehaus.groovy.ast.builder.AstBuilder}.
+     *
+     * Here is an example :
+     * <pre>
+     *        // add @Contract({distance >= 0 })
+     *        customizer = new ASTTransformationCustomizer(Contract)
+     *        final expression = new AstBuilder().buildFromCode(CompilePhase.CONVERSION) {->
+     *            distance >= 0
+     *        }.expression[0]
+     *        customizer.annotationParameters = [value: expression]</pre>
+     *
+     * @param params the annotation parameters
+     *
+     * @since 1.8.1
+     */
+    public void setAnnotationParameters(Map<String,Object> params) {
+        if (params==null || annotationNode==null) return;
+        params.each { key, value ->
+            if (!annotationNode.classNode.getMethod(key)) {
+                throw new IllegalArgumentException("${annotationNode.classNode.name} does not accept any [$key] parameter")
+            }
+            if (value instanceof Closure) {
+                throw new IllegalArgumentException("Direct usage of closure is not supported by the AST " +
+                "compilation customizer. Please use ClosureExpression instead.")
+            } else if (value instanceof Expression) {
+                // avoid NPEs due to missing source code
+                value.setLineNumber(0)
+                value.setLastLineNumber(0)
+                annotationNode.addMember(key, value)
+            } else if (value instanceof Class) {
+                annotationNode.addMember(key, new ClassExpression(ClassHelper.make(value)))
+            } else if (value instanceof List) {
+                annotationNode.addMember(key, new ListExpression(value.collect {
+                    it instanceof Class ? new ClassExpression(ClassHelper.make(it)) : new ConstantExpression(it)
+                }))
+            } else {
+                annotationNode.addMember(key, new ConstantExpression(value))
+            }
+        }
+    }
+
+    @Override
+    void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
+        if (transformation instanceof CompilationUnitAware) {
+            transformation.compilationUnit = compilationUnit
+        }
+        if (annotationNode!=null) {
+            // this is a local ast transformation which is applied on every class node
+            annotationNode.sourcePosition = classNode
+            transformation.visit([annotationNode, classNode] as ASTNode[], source)
+        } else {
+            // this is a global AST transformation
+            if (!applied) transformation.visit(null, source)
+        }
+        applied = true
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/control/customizers/builder/ASTTransformationCustomizerFactory.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/control/customizers/builder/ASTTransformationCustomizerFactory.groovy b/src/main/groovy/org/codehaus/groovy/control/customizers/builder/ASTTransformationCustomizerFactory.groovy
new file mode 100644
index 0000000..4e4f5be
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/control/customizers/builder/ASTTransformationCustomizerFactory.groovy
@@ -0,0 +1,60 @@
+/*
+ *  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.control.customizers.builder
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
+
+/**
+ * This factory generates an {@link ASTTransformationCustomizer ast transformation customizer}.
+ * <p>
+ * Simple syntax:
+ * <pre>builder.ast(ToString)</pre>
+ * With AST transformation options:
+ * <pre>builder.ast(includeNames:true, ToString)</pre>
+ *
+ * @author Cedric Champeau
+ * @since 2.1.0
+ */
+class ASTTransformationCustomizerFactory extends AbstractFactory {
+
+    @Override
+    @CompileStatic
+    public boolean isLeaf() {
+        true
+    }
+
+    @Override
+    @CompileStatic
+    public boolean onHandleNodeAttributes(final FactoryBuilderSupport builder, final Object node, final Map attributes) {
+        false
+    }
+
+    @Override
+    public Object newInstance(final FactoryBuilderSupport builder, final Object name, final Object value, final Map attributes) throws InstantiationException, IllegalAccessException {
+        ASTTransformationCustomizer customizer
+        if (attributes) {
+            customizer = new ASTTransformationCustomizer(attributes, value)
+        } else {
+            customizer = new ASTTransformationCustomizer(value)
+        }
+        customizer
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/control/customizers/builder/CompilerCustomizationBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/control/customizers/builder/CompilerCustomizationBuilder.groovy b/src/main/groovy/org/codehaus/groovy/control/customizers/builder/CompilerCustomizationBuilder.groovy
new file mode 100644
index 0000000..59b8cc5
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/control/customizers/builder/CompilerCustomizationBuilder.groovy
@@ -0,0 +1,64 @@
+/*
+ *  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.control.customizers.builder
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.control.CompilerConfiguration
+
+/**
+ * <p>A builder which allows easy configuration of compilation customizers. Instead of creating
+ * various compilation customizers by hand, you may use this builder instead, which provides a
+ * shorter syntax and removes most of the verbosity.
+ *
+ */
+@CompileStatic
+class CompilerCustomizationBuilder extends FactoryBuilderSupport {
+    public CompilerCustomizationBuilder() {
+        registerFactories()
+    }
+
+    public static CompilerConfiguration withConfig(CompilerConfiguration config, Closure code) {
+        CompilerCustomizationBuilder builder = new CompilerCustomizationBuilder()
+        config.invokeMethod('addCompilationCustomizers', builder.invokeMethod('customizers', code))
+
+        config
+    }
+
+    @Override
+    protected Object postNodeCompletion(final Object parent, final Object node) {
+        Object value = super.postNodeCompletion(parent, node)
+        Object factory = getContextAttribute(CURRENT_FACTORY)
+        if (factory instanceof PostCompletionFactory) {
+            value = factory.postCompleteNode(this, parent, value)
+            setParent(parent, value)
+        }
+
+        value
+    }
+
+    private void registerFactories() {
+        registerFactory("ast", new ASTTransformationCustomizerFactory())
+        registerFactory("customizers", new CustomizersFactory())
+        registerFactory("imports", new ImportCustomizerFactory())
+        registerFactory("inline", new InlinedASTCustomizerFactory())
+        registerFactory("secureAst", new SecureASTCustomizerFactory())
+        registerFactory("source", new SourceAwareCustomizerFactory())
+    }
+}


[34/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaClassRegistry.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaClassRegistry.java b/src/main/groovy/groovy/lang/MetaClassRegistry.java
new file mode 100644
index 0000000..f13c1c1
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaClassRegistry.java
@@ -0,0 +1,192 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.GeneratedClosure;
+import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
+
+import java.lang.reflect.Constructor;
+import java.util.Iterator;
+
+/**
+ * A MetaClassRegistry is an object that is responsible for managing the a cache of MetaClass instances. Each
+ * java.lang.Class instance has an associated MetaClass and client code can query this interface for the MetaClass for
+ * a given associated java.lang.Class
+ *
+ * @see groovy.lang.MetaClass
+ *
+ * @author John Wilson
+ * @author Graeme Rocher
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ *
+ */
+public interface MetaClassRegistry {
+    
+    /**
+     * The main function of the registry
+     * If a meta class exists then return it
+     * otherwise create one, put it in the registry and return it
+     */
+    MetaClass getMetaClass(Class theClass);
+    
+    /**
+     * Adds a metaclass to the registry for the given class
+     *
+     * @param theClass The class
+     * @param theMetaClass The MetaClass for theClass
+     */
+    void setMetaClass(Class theClass, MetaClass theMetaClass);
+
+    /**
+     * Removes a cached MetaClass from the registry
+     *
+     * @param theClass The Java class of the MetaClass to remove
+     */
+    void removeMetaClass(Class theClass);
+
+    /**
+     * Retrieves the MetaClassCreationHandle that is responsible for constructing MetaClass instances
+     *
+     * @return The MetaClassCreationHandle instance
+     */
+    MetaClassCreationHandle getMetaClassCreationHandler();
+
+    /**
+     * Sets the MetaClassCreationHandle instance that is responsible for constructing instances
+     *
+     * @param handle The handle instance
+     */
+    void setMetaClassCreationHandle(MetaClassCreationHandle handle);
+
+    /**
+     * Adds a meta class change listener for constant meta classes
+     *
+     * @param listener - the update listener
+     */
+    void addMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
+    
+    /**
+     * Adds a meta class change listener for constant meta classes. 
+     * This listener cannot be removed!
+     *
+     * @param listener - the update listener
+     */
+    void addNonRemovableMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
+
+    /**
+     * Removes a meta class change listener for constant meta classes
+     *
+     * @param listener - the update listener
+     */
+    void removeMetaClassRegistryChangeEventListener(MetaClassRegistryChangeEventListener listener);
+
+    /**
+     * Returns all registered class change listener for constant meta classes.
+     *
+     * @return an array containing all change listener
+     */
+    MetaClassRegistryChangeEventListener[] getMetaClassRegistryChangeEventListeners();
+
+    /**
+     * Gets a snapshot of the current constant meta classes and returns it as Iterator.
+     * Modifications done using this Iterator will not cause a ConcurrentModificationException.
+     * If a MetaClass is removed using this Iterator, then the MetaClass will only
+     * be removed if the MetaClass was not replaced by another MetaClass in the meantime.
+     * If a MetaClass is added while using this Iterator, then it will be part of the Iteration.
+     * If a MetaClass replaces another constant meta class, then the Iteration might show two
+     * meta classes for the same class.
+     * <p>
+     * Note: This Iterator may not used with multiple threads.
+     *
+     * @return Iterator for the constant meta classes
+     */
+    Iterator iterator();    
+    
+    /**
+     * Class used as base for the creation of MetaClass implementations.
+     * The Class defaults to MetaClassImpl, if the class loading fails to
+     * find a special meta class. The name for such a meta class would be
+     * the class name it is created for with the prefix
+     * "groovy.runtime.metaclass." By replacing the handle in the registry
+     * you can have any control over the creation of what MetaClass is used
+     * for a class that you want to have. 
+     * WARNING: experimental code, likely to change soon
+     * @author Jochen Theodorou
+     */
+    class MetaClassCreationHandle {
+        private boolean disableCustomMetaClassLookup;
+         
+        /**
+         * Creates a metaclass implementation for theClass.
+         * @param theClass The class to create a metaclass for
+         * @param registry The metaclass registry the metaclass we be registered in.
+         */
+        public final MetaClass create(Class theClass, MetaClassRegistry registry) {
+           if (disableCustomMetaClassLookup)
+               return createNormalMetaClass(theClass, registry);
+
+            return createWithCustomLookup(theClass, registry);
+        }
+
+        private MetaClass createWithCustomLookup(Class theClass, MetaClassRegistry registry) {
+            try {
+                final Class customMetaClass = Class.forName("groovy.runtime.metaclass." + theClass.getName() + "MetaClass");
+                if (DelegatingMetaClass.class.isAssignableFrom(customMetaClass)) {
+                    final Constructor customMetaClassConstructor = customMetaClass.getConstructor(MetaClass.class);
+                    MetaClass normalMetaClass = createNormalMetaClass(theClass, registry);
+                    return (MetaClass)customMetaClassConstructor.newInstance(normalMetaClass);
+                }
+                else {
+                    final Constructor customMetaClassConstructor = customMetaClass.getConstructor(MetaClassRegistry.class, Class.class);
+                    return (MetaClass)customMetaClassConstructor.newInstance(registry, theClass);
+                }
+            }
+            catch (final ClassNotFoundException e) {
+                return createNormalMetaClass(theClass, registry);
+            } catch (final Exception e) {
+                throw new GroovyRuntimeException("Could not instantiate custom Metaclass for class: " + theClass.getName() + ". Reason: " + e, e);
+            }
+        }
+
+        protected MetaClass createNormalMetaClass(Class theClass,MetaClassRegistry registry) {
+            if (GeneratedClosure.class.isAssignableFrom(theClass)) {
+                return new ClosureMetaClass(registry,theClass);
+            } else {
+                return new MetaClassImpl(registry, theClass);
+            }
+        }
+
+        /**
+         * Returns whether custom meta classes are disabled.
+         */
+        public boolean isDisableCustomMetaClassLookup() {
+            return disableCustomMetaClassLookup;
+        }
+
+        /**
+         * Set flag saying to disable lookup of custom meta classes
+         * It's enough to call this method only once in your application for handle which was set in to registry
+         * as every new handle will inherit this property
+         * @param disableCustomMetaClassLookup flag saying to disable lookup of custom meta classes
+         */
+        public void setDisableCustomMetaClassLookup(boolean disableCustomMetaClassLookup) {
+            this.disableCustomMetaClassLookup = disableCustomMetaClassLookup;
+        }
+    }
+ }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaClassRegistryChangeEvent.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaClassRegistryChangeEvent.java b/src/main/groovy/groovy/lang/MetaClassRegistryChangeEvent.java
new file mode 100644
index 0000000..c882fda
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaClassRegistryChangeEvent.java
@@ -0,0 +1,104 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.EventObject;
+
+/**
+ * An event used to propagate meta class updates
+ *
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ */
+public class MetaClassRegistryChangeEvent extends EventObject {
+    private final Class clazz;
+    private final Object instance;
+    private final MetaClass metaClass;
+    private final MetaClass oldMetaClass;
+
+    /**
+     *Constructs a new MetaClassRegistryChangeEvent Object
+     *
+     * @param source The object the the event originates at.
+     * @param instance Object instance  the MetaClass change is on.
+     * @param clazz  The class that is affected by the registry change
+     * @param oldMetaClass The old MetaClass
+     * @param newMetaClass The new MetaClass
+     */
+    public MetaClassRegistryChangeEvent(Object source, Object instance, Class clazz, MetaClass oldMetaClass, MetaClass newMetaClass) {
+        super(source);
+        this.clazz = clazz;
+        this.metaClass = newMetaClass;
+        this.oldMetaClass = oldMetaClass;
+        this.instance = instance;
+    }
+
+    /**
+     * Get the class that is updated.
+     *
+     *@return The updated class
+     */
+    public Class getClassToUpdate() {
+        return clazz;
+    }
+
+    /**
+     * Get the new MetaClass
+     *
+     * @return The new MetaClass
+     */
+    public MetaClass getNewMetaClass() {
+        return metaClass;
+    }
+
+    /**
+     * Get the old MetaClass
+     *
+     * @return The old MetaClass
+     */
+    public MetaClass getOldMetaClass() {
+        return oldMetaClass;
+    }
+
+    /**
+     * Determines if this event is for a change for a single instance or all instances of the Class.
+     *
+     * @return whether this event is for a single instance
+     */
+    public boolean isPerInstanceMetaClassChange() {
+        return instance!=null;
+    }
+
+    /**
+     * Returns the instance this event is for.
+     *
+     * @return the instance or null if this event is for a change for all instances of a class
+     */
+    public Object getInstance() {
+        return instance;
+    }
+
+    /**
+     * Get the MetaClassRegistry that originates this change
+     *
+     * @return the source MetaClassRegistry
+     */
+    public MetaClassRegistry getRegistry() {
+        return (MetaClassRegistry) source;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaClassRegistryChangeEventListener.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaClassRegistryChangeEventListener.java b/src/main/groovy/groovy/lang/MetaClassRegistryChangeEventListener.java
new file mode 100644
index 0000000..e7fd40c
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaClassRegistryChangeEventListener.java
@@ -0,0 +1,42 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.EventListener;
+
+/**
+ * A listener called whenever a constant MetaClass is set, removed or replaced. 
+ *
+ * @see groovy.lang.MetaClassRegistry
+ * @see groovy.lang.MetaClassRegistryChangeEvent
+ *
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+  *
+ */
+public interface MetaClassRegistryChangeEventListener extends EventListener{
+
+    /**
+     * Called when the a constant MetaClass is updated. If the new MetaClass is null, then the MetaClass
+     * is removed. Be careful, while this method is executed other updates may happen. If you want this
+     * method thread safe, you have to take care of that by yourself.
+     *
+     * @param cmcu - the change event
+     */
+    void updateConstantMetaClass(MetaClassRegistryChangeEvent cmcu);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaExpandoProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaExpandoProperty.java b/src/main/groovy/groovy/lang/MetaExpandoProperty.java
new file mode 100644
index 0000000..6eb2cf7
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaExpandoProperty.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 groovy.lang;
+
+import java.util.Map.Entry;
+
+/**
+ * Represents a property in an Expando object
+ *
+ * @author John Stump
+ */
+public class MetaExpandoProperty extends MetaProperty {
+
+    Object value = null;
+
+    public MetaExpandoProperty(Entry entry) {
+        super((String) entry.getKey(), Object.class);
+
+        value = entry.getValue();
+    }
+
+    /**
+     * @return the property of the given object
+     * @throws Exception if the property could not be evaluated
+     */
+    public Object getProperty(Object object) {
+        return value;
+    }
+
+    /**
+     * Sets the property on the given object to the new value
+     *
+     * @param object   on which to set the property
+     * @param newValue the new value of the property
+     */
+    public void setProperty(Object object, Object newValue) {
+        value = newValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaMethod.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaMethod.java b/src/main/groovy/groovy/lang/MetaMethod.java
new file mode 100644
index 0000000..3051675
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaMethod.java
@@ -0,0 +1,330 @@
+/*
+ *  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 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</a>
+ * @author Alex Tkachman
+ */
+public abstract class MetaMethod extends ParameterTypes implements Cloneable {
+    private String signature;
+    private String mopName;
+
+    /**
+     * Constructor for a metamethod with an empty parameter list
+     */
+    public MetaMethod() {
+    }
+
+    /**
+     *Constructor wit a list of parameter classes
+     *
+     * @param pt A list of parameters types
+     */
+    public MetaMethod(Class [] pt) {
+        super (pt);
+    }
+
+    /**
+     *Returns the modifiers for this method
+     *
+     * @return modifiers as an int.
+     */
+    public abstract int getModifiers();
+
+    /**
+     * Returns the name of the method represented by this class
+     * 
+     * @return name of this method
+     */
+    public abstract String getName();
+
+    /**
+     * Access the return type for this method
+     *
+     *@return the return type of this method
+     */
+    public abstract Class getReturnType();
+
+    /**
+     * Gets the class where this method is declared
+     *
+     * @return class of this method
+     */
+    public abstract CachedClass getDeclaringClass();
+
+    /**
+     * Invoke this method
+     *
+     * @param object The object this method should be invoked on
+     * @param arguments The arguments for the method if applicable
+     * @return The return value of the invocation
+     */
+    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));
+        }
+    }
+
+    /**
+     *Returns true if this this metamethod represents the same method as the argument.
+     *
+     * @param method A metaMethod instance
+     * @return true if method is for the same method as this method, false otherwise.
+     */
+    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;
+    }
+
+    /**
+     * Returns a string representation of this method
+     */
+    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);
+        }
+    }
+
+    /**
+     * Returns whether or not this method is static.
+     * @return true if this method is static
+     */
+    public boolean isStatic() {
+        return (getModifiers() & Modifier.STATIC) != 0;
+    }
+
+    /**
+     * Returns whether or not this method is abstract.
+     * @return true if this method is abstract
+     */
+    public boolean isAbstract() {
+        return (getModifiers() & Modifier.ABSTRACT) != 0;
+    }
+
+    /**
+     * Returns whether or not this method is private.
+     * @return true if this method is private
+     */
+    public final boolean isPrivate() {
+        return (getModifiers() & Modifier.PRIVATE) != 0;
+    }
+
+    /**
+     * Returns whether or not this method is protected.
+     * @return true if this method is protected
+     */
+    public final boolean isProtected() {
+        return (getModifiers() & Modifier.PROTECTED) != 0;
+    }
+
+    /**
+     * Returns whether or not this method is public.
+     * @return true if this method is public
+     */
+    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());
+    }
+
+    /**
+     * Checks the compatibility between two modifier masks. Checks that they are equal
+     * with regards to access and static modifier.
+     *
+     * @return true if the modifiers are compatible
+     */
+    private static boolean compatibleModifiers(int modifiersA, int modifiersB) {
+        int mask = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC | Modifier.STATIC;
+        return (modifiersA & mask) == (modifiersB & mask);
+    }
+
+    /**
+     * Returns whether this object is cacheable
+     */
+    public boolean isCacheable() {
+        return true;
+    }
+
+    /**
+     * Return a descriptor of this method based on the return type and parameters of this method.
+     */
+    public String getDescriptor() {
+        return BytecodeHelper.getMethodDescriptor(getReturnType(), getNativeParameterTypes());
+    }
+
+    /**
+     * Returns the signature of this method
+     *
+     * @return The signature of this method
+     */
+    public synchronized String getSignature() {
+        if (signature == null) {
+            CachedClass [] parameters = getParameterTypes();
+            final String name = getName();
+            StringBuilder buf = new StringBuilder(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;
+    }
+
+    /**
+     * This method is called when an exception occurs while invoking this method.
+     */
+    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);
+    }
+
+    /**
+     * Invokes the method this object represents. 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
+     *
+     * @param object The object the method is to be called at.
+     * @param argumentArray Arguments for the method invocation.
+     * @return The return value of the invoked method.
+     */
+    public Object doMethodInvoke(Object object, Object[] argumentArray) {
+        argumentArray = coerceArgumentsToClasses(argumentArray);
+        try {
+            return invoke(object, argumentArray);
+        } catch (Exception e) {
+            throw processDoMethodInvokeException(e, object, argumentArray);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaObjectProtocol.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaObjectProtocol.java b/src/main/groovy/groovy/lang/MetaObjectProtocol.java
new file mode 100644
index 0000000..4218831
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaObjectProtocol.java
@@ -0,0 +1,227 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.List;
+
+/**
+ * <p>An interface that defines the API usable by clients of Groovy's Meta Object Protocol (MOP). These methods are
+ * implemented by the reference implementation of the {@link groovy.lang.MetaClass} interface.
+ *
+ * @see MetaClassImpl
+ * @author John Wilson
+ * @author Graeme Rocher
+ */
+public interface MetaObjectProtocol {
+
+    /**
+     * Obtain a list of all meta properties available on this meta class
+     *
+     * @see groovy.lang.MetaProperty
+     * @return A list of MetaProperty instances
+     */
+    List<MetaProperty> getProperties();
+    /**
+     * Obtain a list of all the meta methods available on this meta class
+     *
+     * @see groovy.lang.MetaMethod
+     * @return A list of MetaMethod instances
+     */
+    List<MetaMethod> getMethods();
+    
+    /**
+     * <p>Returns an object satisfying Groovy truth if the implementing MetaClass responds to
+     * a method with the given name and arguments types.
+     *
+     * <p>Note that this method's return value is based on realised methods and does not take into account
+     * objects or classes that implement invokeMethod or methodMissing
+     *
+     * <p>This method is "safe" in that it will always return a value and never throw an exception
+     *
+     * @param obj The object to inspect
+     * @param name The name of the method of interest
+     * @param argTypes The argument types to match against
+     * @return A List of MetaMethods matching the argument types which will be empty if no matching methods exist
+     */
+    List<MetaMethod> respondsTo(Object obj, String name, Object[] argTypes);
+
+    /**
+     * <p>Returns an object satisfying Groovy truth if the implementing MetaClass responds to
+     * a method with the given name regardless of arguments. In other words this method will
+     * return for foo() and foo(String).
+     *
+     * <p>Note that this method's return value is based on realised methods and does not take into account
+     * objects or classes that implement invokeMethod or methodMissing
+     *
+     * <p>This method is "safe" in that it will always return a value and never throw an exception
+     *
+     * @param obj The object to inspect
+     * @param name The name of the method of interest
+     * @return A List of MetaMethods which will be empty if no methods with the given name exist
+     */
+    List<MetaMethod> respondsTo(Object obj, String name);
+
+    /**
+     * <p>Returns true of the implementing MetaClass has a property of the given name
+     *
+     * <p>Note that this method will only return true for realised properties and does not take into
+     * account implementation of getProperty or propertyMissing
+     *
+     * @param obj The object to inspect
+     * @param name The name of the property
+     * @return The MetaProperty or null if it doesn't exist
+     */
+    MetaProperty hasProperty(Object obj, String name);
+
+    /**
+     * Returns a MetaProperty for the given name or null if it doesn't exist
+     *
+     * @param name The name of the MetaProperty
+     * @return A MetaProperty or null
+     */
+    MetaProperty getMetaProperty(String name);
+
+    /**
+     * Retrieves a static MetaMethod for the given name and argument values, using the types of the arguments
+     * to establish the chosen MetaMethod
+     *
+     * @param name The name of the MetaMethod
+     * @param args The argument types
+     * @return A MetaMethod or null if it doesn't exist
+     */
+    MetaMethod getStaticMetaMethod(String name, Object[] args);
+
+
+    /**
+     * Retrieves an instance MetaMethod for the given name and argument values, using the types of the
+     * argument values to establish the chosen MetaMethod
+     *
+     * @param name The name of the MetaMethod
+     * @param args Array containing - 1) the argument values (using which their types are then inferred), or 2) the corresponding argument types  
+     * @return A MetaMethod or null if it doesn't exist
+     */
+    MetaMethod getMetaMethod(String name, Object[] args);
+
+    /**
+     * Retrieves that Java Class that the attached Meta behaviours apply to
+     *
+     * @return The java.lang.Class instance
+     */
+    Class getTheClass();
+
+    /**
+     * Invokes a constructor for the given arguments. The MetaClass will attempt to pick the best argument which
+     * matches the types of the objects passed within the arguments array
+     *
+     * @param arguments The arguments to the constructor
+     * @return An instance of the java.lang.Class that this MetaObjectProtocol object applies to
+     */
+    Object invokeConstructor(Object[] arguments);
+
+    /**
+     * Invokes a method on the given Object with the given name and arguments. The MetaClass will attempt to pick
+     * the best method for the given name and arguments. If a method cannot be invoked a MissingMethodException will be
+     * thrown.
+     *
+     * @see groovy.lang.MissingMethodException
+     * @param object The instance which the method is invoked on
+     * @param methodName The name of the method
+     * @param arguments The arguments to the method
+     * @return The return value of the method which is null if the return type is void
+     */
+    Object invokeMethod(Object object, String methodName, Object[] arguments);
+
+    /**
+     * Invokes a method on the given object, with the given name and single argument.
+     *
+     * @see #invokeMethod(Object, String, Object[])
+     * @param object The Object to invoke the method on
+     * @param methodName The name of the method
+     * @param arguments The argument to the method
+     * @return The return value of the method which is null if the return type is void
+     */
+     Object invokeMethod(Object object, String methodName, Object arguments);
+
+    /**
+     * Invokes a static method on the given Object with the given name and arguments.
+     * <p>
+     * The Object can either be an instance of the class that this
+     * MetaObjectProtocol instance applies to or the java.lang.Class instance itself. If a method cannot be invoked
+     * a MissingMethodException is will be thrown
+     *
+     * @see groovy.lang.MissingMethodException
+     * @param object An instance of the class returned by the getTheClass() method or the class itself
+     * @param methodName The name of the method
+     * @param arguments The arguments to the method
+     * @return The return value of the method which is null if the return type is void
+     */
+    Object invokeStaticMethod(Object object, String methodName, Object[] arguments);
+
+    /**
+     * Retrieves a property of an instance of the class returned by the getTheClass() method.
+     * <p>
+     * What this means is largely down to the MetaClass implementation, however the default case would result
+     * in an attempt to invoke a JavaBean getter, or if no such getter exists a public field of the instance.
+     *
+     * @see MetaClassImpl
+     * @param object An instance of the class returned by the getTheClass() method
+     * @param property The name of the property to retrieve the value for
+     * @return The properties value
+     */
+    Object getProperty(Object object, String property);
+
+    /**
+     * Sets a property of an instance of the class returned by the getTheClass() method.
+     * <p>
+     * What this means is largely down to the MetaClass implementation, however the default case would result
+     * in an attempt to invoke a JavaBean setter, or if no such setter exists to set a public field of the instance.
+     *
+     * @see MetaClassImpl
+     * @param object An instance of the class returned by the getTheClass() method
+     * @param property The name of the property to set
+     * @param newValue The new value of the property
+     */
+    void setProperty(Object object, String property, Object newValue);
+
+    /**
+     * Retrieves an attribute of an instance of the class returned by the getTheClass() method.
+     * <p>
+     * What this means is largely down to the MetaClass implementation, however the default case would result
+     * in attempt to read a field of the instance.
+     *
+     * @see MetaClassImpl
+     * @param object An instance of the class returned by the getTheClass() method
+     * @param attribute The name of the attribute to retrieve the value for
+     * @return The attribute value
+     */
+    Object getAttribute(Object object, String attribute);
+
+    /**
+     * Sets an attribute of an instance of the class returned by the getTheClass() method.
+     * <p>
+     * What this means is largely down to the MetaClass implementation, however the default case would result
+     * in an attempt to set a field of the instance.
+     *
+     * @see MetaClassImpl
+     * @param object An instance of the class returned by the getTheClass() method
+     * @param attribute The name of the attribute to set
+     * @param newValue The new value of the attribute
+     */
+    void setAttribute(Object object, String attribute, Object newValue);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaProperty.java b/src/main/groovy/groovy/lang/MetaProperty.java
new file mode 100644
index 0000000..d3c9633
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaProperty.java
@@ -0,0 +1,102 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.MetaClassHelper;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Represents a property on a bean which may have a getter and/or a setter
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public abstract class MetaProperty {
+
+    protected final String name;
+    protected Class type;
+    public static final String PROPERTY_SET_PREFIX = "set";
+
+    /**
+     * Constructor that sets the property name and type (class)
+     */
+    public MetaProperty(String name, Class type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    /**
+     * @return the property of the given object
+     * @throws Exception if the property could not be evaluated
+     */
+    public abstract Object getProperty(Object object);
+
+    /**
+     * Sets the property on the given object to the new value
+     * 
+     * @param object on which to set the property
+     * @param newValue the new value of the property
+     * @throws RuntimeException if the property could not be set
+     */
+    public abstract void setProperty(Object object, Object newValue);
+
+    /**
+     * Return the name of the property
+     *
+     * @return the name of the property
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the type of the property
+     */
+    public Class getType() {
+        return type;
+    }
+    
+    /**
+     * Returns the access modifier.
+     * @return Modifier.PUBLIC
+     */
+    public int getModifiers() {
+        return Modifier.PUBLIC;
+    }
+
+    /**
+     * Gets the name for the getter for this property
+     *
+     * @return The name of the property. The name is "get"+ the capitalized propertyName
+     *         or, in the case of boolean values, "is" + the capitalized propertyName
+     */
+    public static String getGetterName(String propertyName, Class type) {
+        String prefix = type == boolean.class || type == Boolean.class ? "is" : "get";
+        return prefix + MetaClassHelper.capitalize(propertyName);
+    }
+
+    /**
+     * Gets the setter for the getter for this property.
+     *
+     * @return The name of the property. The name is "set"+ the capitalized propertyName.
+     */
+    public static String getSetterName(String propertyName) {
+        return PROPERTY_SET_PREFIX + MetaClassHelper.capitalize(propertyName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MissingClassException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MissingClassException.java b/src/main/groovy/groovy/lang/MissingClassException.java
new file mode 100644
index 0000000..ad8e5f5
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MissingClassException.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 groovy.lang;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+
+/**
+ * An exception occurred if a dynamic method dispatch fails with an unknown class.
+ * 
+ * Note that the Missing*Exception classes were named for consistency and
+ * to avoid conflicts with JDK exceptions of the same name.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class MissingClassException extends GroovyRuntimeException {
+
+    private final String type;
+
+    public MissingClassException(String type, ASTNode node, String message) {
+        super("No such class: " + type + " " + message, node);
+        this.type = type;
+    }
+    
+    public MissingClassException(ClassNode type, String message){
+        super("No such class: " + type.getName() + " " + message);
+        this.type = type.getName();
+    }
+
+    /**
+     * 
+     * @return The type that could not be resolved
+     */
+    public String getType() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MissingFieldException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MissingFieldException.java b/src/main/groovy/groovy/lang/MissingFieldException.java
new file mode 100644
index 0000000..3c17d39
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MissingFieldException.java
@@ -0,0 +1,67 @@
+/*
+ *  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 groovy.lang;
+
+
+/**
+ * An exception occurred if a dynamic field dispatch fails with an unknown field.
+ * 
+ * Note that the Missing*Exception classes were named for consistency and
+ * to avoid conflicts with JDK exceptions of the same name.
+ * 
+ * @author <a href="mailto:jstrachan@protique.com">James Strachan</a>
+ */
+public class MissingFieldException extends GroovyRuntimeException {
+
+    private final String field;
+    private final Class type;
+
+    public MissingFieldException(String field, Class type) {
+        super("No such field: " + field + " for class: " + type.getName());
+        this.field = field;
+        this.type = type;
+    }
+
+    public MissingFieldException(String field, Class type, Throwable e) {
+        super("No such field: " + field + " for class: " + type.getName() + ". Reason: " + e, e);
+        this.field = field;
+        this.type = type;
+    }
+
+    public MissingFieldException(String message, String field, Class type) {
+        super(message);
+        this.field = field;
+        this.type = type;
+    }
+
+    /**
+     * @return the name of the field that could not be found
+     */
+    public String getField() {
+        return field;
+    }
+
+    /**
+     * 
+     * @return The type on which the field was attempted to be called
+     */
+    public Class getType() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MissingMethodException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MissingMethodException.java b/src/main/groovy/groovy/lang/MissingMethodException.java
new file mode 100644
index 0000000..0902150
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MissingMethodException.java
@@ -0,0 +1,88 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.MethodRankHelper;
+
+/**
+ * An exception occurred if a dynamic method dispatch fails with an unknown method.
+ * <p>
+ * Note that the Missing*Exception classes were named for consistency and
+ * to avoid conflicts with JDK exceptions of the same name.
+ */
+public class MissingMethodException extends GroovyRuntimeException {
+
+    private final String method;
+    private final Class type;
+    private final boolean isStatic;
+
+    public Object[] getArguments() {
+        return arguments;
+    }
+
+    private final Object arguments[];
+
+    public MissingMethodException(String method, Class type, Object[] arguments) {
+        this(method, type, arguments, false);
+    }
+
+    public MissingMethodException(String method, Class type, Object[] arguments, boolean isStatic) {
+        super();
+        this.method = method;
+        this.type = type;
+        this.isStatic = isStatic;
+        this.arguments = arguments;
+    }
+
+    public String getMessage() {
+        return "No signature of method: "
+                + (isStatic ? "static " : "")
+                + type.getName()
+                + "."
+                + method
+                + "() is applicable for argument types: ("
+                + InvokerHelper.toTypeString(arguments, 60)
+                + ") values: "
+                + InvokerHelper.toArrayString(arguments, 60, true)
+                + MethodRankHelper.getMethodSuggestionString(method, type, arguments);
+    }
+
+    /**
+     * @return the name of the method that could not be found
+     */
+    public String getMethod() {
+        return method;
+    }
+
+    /**
+     * @return The type on which the method was attempted to be called
+     */
+    public Class getType() {
+        return type;
+    }
+
+    /**
+     * @return Whether the method was called in a static way,
+     *         i.e. on a class rather than an object.
+     */
+    public boolean isStatic() {
+        return isStatic;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MissingPropertyException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MissingPropertyException.java b/src/main/groovy/groovy/lang/MissingPropertyException.java
new file mode 100644
index 0000000..270f039
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MissingPropertyException.java
@@ -0,0 +1,88 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.MethodRankHelper;
+
+
+/**
+ * An exception occurred if a dynamic property dispatch fails with an unknown property.
+ * 
+ * Note that the Missing*Exception classes were named for consistency and
+ * to avoid conflicts with JDK exceptions of the same name.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class MissingPropertyException extends GroovyRuntimeException {
+
+    public static final Object MPE = new Object();
+
+    private final String property;
+    private final Class type;
+
+    public MissingPropertyException(String property, Class type) {
+        this.property = property;
+        this.type = type;
+    }
+
+    public MissingPropertyException(String property, Class type, Throwable t) {
+        super(t);
+        this.property = property;
+        this.type = type;
+    }
+
+    public MissingPropertyException(String message) {
+        super(message);
+        this.property = null;
+        this.type = null;
+    }
+
+    public MissingPropertyException(String message, String property, Class type) {
+        super(message);
+        this.property = property;
+        this.type = type;
+    }
+
+    public String getMessageWithoutLocationText() {
+        final Throwable cause = getCause();
+        if (cause == null) {
+            if (super.getMessageWithoutLocationText() != null) {
+                return super.getMessageWithoutLocationText();
+            }
+            return "No such property: " + property + " for class: " + type.getName() +
+                   MethodRankHelper.getPropertySuggestionString(property, type);
+        }
+        return "No such property: " + property + " for class: " + type.getName() + ". Reason: " + cause;
+    }
+
+    /**
+     * @return the name of the property that could not be found
+     */
+    public String getProperty() {
+        return property;
+    }
+
+    /**
+     * 
+     * @return The type on which the property was attempted to be called
+     */
+    public Class getType() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Mixin.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Mixin.java b/src/main/groovy/groovy/lang/Mixin.java
new file mode 100644
index 0000000..22ef4b9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Mixin.java
@@ -0,0 +1,42 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Provides a mechanism for mixing in methods into a class.
+ *
+ * @deprecated static mixins have been deprecated in favour of traits (trait keyword).
+ *
+ * @author Alex Tkachman
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@GroovyASTTransformationClass("org.codehaus.groovy.ast.MixinASTTransformation")
+@Deprecated
+public @interface Mixin {
+    Class [] value ();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MutableMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MutableMetaClass.java b/src/main/groovy/groovy/lang/MutableMetaClass.java
new file mode 100644
index 0000000..903c895
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MutableMetaClass.java
@@ -0,0 +1,79 @@
+/*
+ *  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 groovy.lang;
+
+import java.lang.reflect.Method;
+
+/**
+ * An interface that defines methods that implementers of mutable Meta classes should specify. It provides operations to perform mutations
+ * on the MetaClass instance.
+ * <p>
+ * Whether a MetaClass allows mutation is up to the MetaClass itself and considerations of Thread safety
+ * need to be taken into account when making a MetaClass mutable
+ * <p>
+ * The default implementation allows mutation of MetaClass instances before initialisation (before the initialize() method is called)
+ * but not after, thus ensuring Thread safety once a MetaClass has been constructed and placed in the registry
+ *
+ * @see MetaClassImpl
+ * @see MetaClass
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public interface MutableMetaClass extends MetaClass {
+
+    /**
+     * Return whether the MetaClass has been modified or not
+     * @return True if it has
+     */
+    boolean isModified();
+
+    /**
+     * adds a new instance method to this MetaClass. Instance
+     * methods are able to overwrite the original methods of the
+     * class. Calling this method should not be done after
+     * initialise was called.
+     *
+     * @param method the method to be added
+     */
+     void addNewInstanceMethod(Method method);
+
+    /**
+     * adds a new static method to this MetaClass. This is only
+     * possible as long as initialise was not called.
+     *
+     * @param method the method to be added
+     */
+     void addNewStaticMethod(Method method);
+
+    /**
+     * Adds a new MetaMethod to the MetaClass
+     *
+     * @param metaMethod The MetaMethod to add
+     */
+    void addMetaMethod(MetaMethod metaMethod);
+
+    /**
+     * Adds a new MetaBeanProperty to the MetaClass
+     *
+     * @param metaBeanProperty The MetaBeanProperty instance
+     */
+    void addMetaBeanProperty(MetaBeanProperty metaBeanProperty);
+    
+    // TODO: Add methods like addMetaConstructor, addMetaAttribute, addMetaAnnotation etc.
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Newify.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Newify.java b/src/main/groovy/groovy/lang/Newify.java
new file mode 100644
index 0000000..525cecb
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Newify.java
@@ -0,0 +1,109 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation that supports writing constructor call expressions without the 'new'
+ * keyword. Instead they can be written "Ruby-style" as a method call to a 'new'
+ * method or "Python-style" by just omitting the 'new' keyword.
+ * <p>
+ * It allows you to write code snippets like this ("Python-style"):
+ * <pre>
+ * {@code @Newify([Tree,Leaf])} class MyTreeProcessor {
+ *     def myTree = Tree(Tree(Leaf("A"), Leaf("B")), Leaf("C"))
+ *     def process() { ... }
+ * }
+ * </pre>
+ * or this ("Ruby-style"):
+ * <pre>
+ * {@code @Newify} class MyTreeProcessor {
+ *     def myTree = Tree.new(Tree.new(Leaf.new("A"), Leaf.new("B")), Leaf.new("C"))
+ *     def process() { ... }
+ * }
+ * </pre>
+ *
+ * After the AST transformation, the following code is passed on for further compilation:
+ * <pre>
+ * class MyTreeProcessor {
+ *     def myTree = new Tree(new Tree(new Leaf("A"), new Leaf("B")), new Leaf("C"))
+ *     def process() { ... }
+ * }
+ * </pre>
+ * The annotation can be used on a whole class as shown above or selectively on a particular
+ * method, constructor or field.
+ * <p>
+ * The "Ruby-style" new conversions occur automatically unless the 'auto=false'
+ * flag is given when using the annotation. You might do this if you create a new method
+ * using meta programming.
+ * <p>
+ * The "Python-style" conversions require you to specify each class on which you want them
+ * to apply. The transformation then works by matching the basename of the provided classes to any
+ * similarly named instance method calls not specifically bound to an object, i.e. associated
+ * with the 'this' object. In other words <code>Leaf("A")</code> would be transformed to
+ * <code>new Leaf("A")</code> but <code>x.Leaf("A")</code> would not be touched.
+ * <p>
+ * An example showing how to use the annotation at different levels:
+ * <pre>
+ * {@code @Newify(auto=false, value=Foo)}
+ * class Main {
+ *     {@code @Newify} // turn auto on for field
+ *     def field1 = java.math.BigInteger.new(42)
+ *     def field2, field3, field4
+ *
+ *     {@code @Newify(Bar)}
+ *     def process() {
+ *         field2 = Bar("my bar")
+ *     }
+ *
+ *     {@code @Newify(Baz)}
+ *     Main() {
+ *         field3 = Foo("my foo")
+ *         field4 = Baz("my baz")
+ *     }
+ * }
+ * </pre>
+ *
+ * The annotation is intended to be used sparingly; perhaps in DSL scenarios or when
+ * using deeply nested structural types. In particular, there is no support for using
+ * the facility with two similarly named classes from different packages at the same time.
+ * Though it is OK to have different packages in different contexts. Also, there is
+ * no support for turning "Ruby-style" conversions off at the method, constructor or
+ * field level if already turned on at the class level.
+ *
+ * @author Paul King
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.NewifyASTTransformation")
+public @interface Newify {
+    Class<?>[] value() default {};
+
+    /**
+     * @return if automatic conversion of "Ruby-style" new method calls should occur
+     */
+    boolean auto() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/NonEmptySequence.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/NonEmptySequence.java b/src/main/groovy/groovy/lang/NonEmptySequence.java
new file mode 100644
index 0000000..f069b7a
--- /dev/null
+++ b/src/main/groovy/groovy/lang/NonEmptySequence.java
@@ -0,0 +1,47 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.List;
+
+/**
+ * Represents a sequence of objects which represents one or many instances of
+ * of objects of a given type. The type can be omitted in which case any type of
+ * object can be added.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class NonEmptySequence extends Sequence {
+
+    public NonEmptySequence() {
+        super(null);
+    }
+
+    public NonEmptySequence(Class type) {
+        super(type);
+    }
+
+    public NonEmptySequence(Class type, List content) {
+        super(type, content);
+    }
+
+    public int minimumSize() {
+        return 1;
+    }
+}
\ No newline at end of file


[16/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaClassImpl.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassImpl.java b/src/main/groovy/lang/MetaClassImpl.java
deleted file mode 100644
index 601d5bb..0000000
--- a/src/main/groovy/lang/MetaClassImpl.java
+++ /dev/null
@@ -1,3958 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.apache.groovy.internal.util.UncheckedThrow;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.classgen.asm.BytecodeHelper;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.reflection.CacheAccessControlException;
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.reflection.CachedConstructor;
-import org.codehaus.groovy.reflection.CachedField;
-import org.codehaus.groovy.reflection.CachedMethod;
-import org.codehaus.groovy.reflection.ClassInfo;
-import org.codehaus.groovy.reflection.GeneratedMetaMethod;
-import org.codehaus.groovy.reflection.ParameterTypes;
-import org.codehaus.groovy.reflection.ReflectionCache;
-import org.codehaus.groovy.reflection.android.AndroidSupport;
-import org.codehaus.groovy.runtime.ConvertedClosure;
-import org.codehaus.groovy.runtime.CurriedClosure;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.GeneratedClosure;
-import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.MethodClosure;
-import org.codehaus.groovy.runtime.callsite.AbstractCallSite;
-import org.codehaus.groovy.runtime.callsite.CallSite;
-import org.codehaus.groovy.runtime.callsite.ConstructorSite;
-import org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
-import org.codehaus.groovy.runtime.metaclass.MetaMethodIndex;
-import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
-import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty;
-import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.TransformMetaMethod;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-import org.codehaus.groovy.runtime.typehandling.NumberMathModificationInfo;
-import org.codehaus.groovy.runtime.wrappers.Wrapper;
-import org.codehaus.groovy.util.ComplexKeyHashMap;
-import org.codehaus.groovy.util.FastArray;
-import org.codehaus.groovy.util.SingleKeyHashMap;
-import org.objectweb.asm.ClassVisitor;
-
-import java.beans.BeanInfo;
-import java.beans.EventSetDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
-import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;
-
-/**
- * Allows methods to be dynamically added to existing classes at runtime
- * @see groovy.lang.MetaClass
- */
-public class MetaClassImpl implements MetaClass, MutableMetaClass {
-
-    public static final Object[] EMPTY_ARGUMENTS = {};
-
-    protected static final String STATIC_METHOD_MISSING = "$static_methodMissing";
-    protected static final String STATIC_PROPERTY_MISSING = "$static_propertyMissing";
-    protected static final String METHOD_MISSING = "methodMissing";
-    protected static final String PROPERTY_MISSING = "propertyMissing";
-    protected static final String INVOKE_METHOD_METHOD = "invokeMethod";
-
-    private static final String CLOSURE_CALL_METHOD = "call";
-    private static final String CLOSURE_DO_CALL_METHOD = "doCall";
-    private static final String GET_PROPERTY_METHOD = "getProperty";
-    private static final String SET_PROPERTY_METHOD = "setProperty";
-    private static final Class[] METHOD_MISSING_ARGS = new Class[]{String.class, Object.class};
-    private static final Class[] GETTER_MISSING_ARGS = new Class[]{String.class};
-    private static final Class[] SETTER_MISSING_ARGS = METHOD_MISSING_ARGS;
-    private static final Comparator<CachedClass> CACHED_CLASS_NAME_COMPARATOR = new Comparator<CachedClass>() {
-        public int compare(final CachedClass o1, final CachedClass o2) {
-            return o1.getName().compareTo(o2.getName());
-        }
-    };
-    private static final MetaMethod[] EMPTY = new MetaMethod[0];
-    private static final MetaMethod AMBIGUOUS_LISTENER_METHOD = new DummyMetaMethod();
-
-    protected final Class theClass;
-    protected final CachedClass theCachedClass;
-    protected final boolean isGroovyObject;
-    protected final boolean isMap;
-    protected final MetaMethodIndex metaMethodIndex;
-
-    private final Index classPropertyIndex = new MethodIndex();
-    private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
-    private final Map<String, MetaMethod> listeners = new HashMap<String, MetaMethod>();
-    private final List<MetaMethod> allMethods = new ArrayList<MetaMethod>();
-    // we only need one of these that can be reused over and over.
-    private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
-    private final Index classPropertyIndexForSuper = new MethodIndex();
-    private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<MetaMethod>();
-    private final MetaMethod [] myNewMetaMethods;
-    private final MetaMethod [] additionalMetaMethods;
-
-    protected MetaMethod getPropertyMethod;
-    protected MetaMethod invokeMethodMethod;
-    protected MetaMethod setPropertyMethod;
-    protected MetaClassRegistry registry;
-    private ClassNode classNode;
-    private FastArray constructors;
-    private volatile boolean initialized;
-    private MetaMethod genericGetMethod;
-    private MetaMethod genericSetMethod;
-    private MetaMethod propertyMissingGet;
-    private MetaMethod propertyMissingSet;
-    private MetaMethod methodMissing;
-    private MetaMethodIndex.Header mainClassMethodHeader;
-
-     /**
-      * Constructor
-      *
-      * @param theClass The class this is the metaclass dor
-      * @param add The methods for this class
-      */
-    public MetaClassImpl(final Class theClass, MetaMethod [] add) {
-        this.theClass = theClass;
-        theCachedClass = ReflectionCache.getCachedClass(theClass);
-        this.isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
-        this.isMap = Map.class.isAssignableFrom(theClass);
-        this.registry = GroovySystem.getMetaClassRegistry();
-        metaMethodIndex = new MetaMethodIndex(theCachedClass);
-        final MetaMethod[] metaMethods = theCachedClass.getNewMetaMethods();
-        if (add != null && !(add.length == 0)) {
-            List<MetaMethod> arr = new ArrayList<MetaMethod>();
-            arr.addAll(Arrays.asList(metaMethods));
-            arr.addAll(Arrays.asList(add));
-            myNewMetaMethods = arr.toArray(new MetaMethod[arr.size()]);
-            additionalMetaMethods = metaMethods;
-        }
-        else {
-            myNewMetaMethods = metaMethods;
-            additionalMetaMethods = EMPTY;
-        }
-    }
-
-    /**
-      * Constructor that sets the methods to null
-      *
-      * @param theClass The class this is the metaclass dor
-      */
-    public MetaClassImpl(final Class theClass) {
-        this(theClass, null);
-    }
-
-    /**
-     * Constructor with registry
-     *
-     * @param registry The metaclass registry for this MetaClass
-     * @param theClass The class
-     * @param add The methods
-     */
-    public MetaClassImpl(MetaClassRegistry registry, final Class theClass, MetaMethod add []) {
-        this(theClass, add);
-        this.registry = registry;
-        this.constructors = new FastArray(theCachedClass.getConstructors());
-    }
-
-    /**
-     * Constructor with registry setting methods to null
-     *
-     * @param registry The metaclass registry for this MetaClass
-     * @param theClass The class
-     */
-    public MetaClassImpl(MetaClassRegistry registry, final Class theClass) {
-        this(registry, theClass, null);
-    }
-
-    /**
-     * Returns the cached class for this metaclass
-     *
-     * @return The cached class.
-     */
-    public final CachedClass getTheCachedClass() {
-        return theCachedClass;
-    }
-
-    /**
-     * Returns the registry for this metaclass
-     * 
-     * @return The resgistry
-     */
-    public MetaClassRegistry getRegistry() {
-        return registry;
-    }
-
-    /**
-     * @see MetaObjectProtocol#respondsTo(Object, String, Object[])
-     */
-    public List respondsTo(Object obj, String name, Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
-        MetaMethod m = getMetaMethod(name, classes);
-        if (m!=null) {
-            return Collections.singletonList(m);
-        }
-        return Collections.emptyList();
-    }
-
-    /**
-     * @see MetaObjectProtocol#respondsTo(Object, String)
-     */
-    public List respondsTo(final Object obj, final String name) {
-        final Object o = getMethods(getTheClass(), name, false);
-        if (o instanceof FastArray)
-            return ((FastArray) o).toList();
-        else
-            return Collections.singletonList(o);
-    }
-
-    /**
-     * @see MetaObjectProtocol#hasProperty(Object,String)
-     */
-    public MetaProperty hasProperty(Object obj, String name) {
-        return getMetaProperty(name);
-    }
-
-    /**
-     * @see MetaObjectProtocol#getMetaProperty(String)
-     */
-    public MetaProperty getMetaProperty(String name) {
-        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
-        if (propertyMap.containsKey(name)) {
-            return (MetaProperty) propertyMap.get(name);
-        } else if (staticPropertyIndex.containsKey(name)) {
-            return (MetaProperty) staticPropertyIndex.get(name);
-        } else {
-            propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
-            if (propertyMap.containsKey(name))
-                return (MetaProperty) propertyMap.get(name);
-            else {
-                CachedClass superClass = theCachedClass;
-                while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
-                    final MetaBeanProperty property = findPropertyInClassHierarchy(name, superClass);
-                    if (property != null) {
-                        onSuperPropertyFoundInHierarchy(property);
-                        return property;
-                    }
-                    superClass = superClass.getCachedSuperClass();
-                }
-                return null;
-            }
-        }
-    }
-
-    /**
-     * @see MetaObjectProtocol#getStaticMetaMethod(String, Object[])
-     */
-    public MetaMethod getStaticMetaMethod(String name, Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
-        return pickStaticMethod(name, classes);
-    }
-
-
-    /**
-     * @see MetaObjectProtocol#getMetaMethod(String, Object[])
-     */
-    public MetaMethod getMetaMethod(String name, Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
-        return pickMethod(name, classes);
-    }
-
-    /**
-     *Returns the class this object this is the metaclass of.
-     * 
-     * @return The class contained by this metaclass
-     */
-    public Class getTheClass() {
-        return this.theClass;
-    }
-
-    /**
-     * Return wether the class represented by this metaclass instance is an instance of the GroovyObject class
-     *
-     * @return true if this is a groovy class, false otherwise.
-     */
-    public boolean isGroovyObject() {
-        return isGroovyObject;
-    }
-
-    /**
-     * Fills the method index
-     */
-    private void fillMethodIndex() {
-        mainClassMethodHeader = metaMethodIndex.getHeader(theClass);
-        LinkedList<CachedClass> superClasses = getSuperClasses();
-        CachedClass firstGroovySuper = calcFirstGroovySuperClass(superClasses);
-
-        Set<CachedClass> interfaces = theCachedClass.getInterfaces();
-        addInterfaceMethods(interfaces);
-
-        populateMethods(superClasses, firstGroovySuper);
-
-        inheritInterfaceNewMetaMethods(interfaces);
-        if (isGroovyObject) {
-          metaMethodIndex.copyMethodsToSuper();
-
-          connectMultimethods(superClasses, firstGroovySuper);
-          removeMultimethodsOverloadedWithPrivateMethods();
-
-          replaceWithMOPCalls(theCachedClass.mopMethods);
-        }
-    }
-
-    private void populateMethods(LinkedList<CachedClass> superClasses, CachedClass firstGroovySuper) {
-
-        MetaMethodIndex.Header header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
-        CachedClass c;
-        Iterator<CachedClass> iter = superClasses.iterator();
-        for (; iter.hasNext();) {
-            c = iter.next();
-
-            CachedMethod[] cachedMethods = c.getMethods();
-            for (CachedMethod metaMethod : cachedMethods) {
-                addToAllMethodsIfPublic(metaMethod);
-                if (!metaMethod.isPrivate() || c == firstGroovySuper)
-                    addMetaMethodToIndex(metaMethod, header);
-            }
-
-            MetaMethod[] cachedMethods1 = getNewMetaMethods(c);
-            for (final MetaMethod method : cachedMethods1) {
-                if (!newGroovyMethodsSet.contains(method)) {
-                    newGroovyMethodsSet.add(method);
-                    addMetaMethodToIndex(method, header);
-                }
-            }
-
-            if (c == firstGroovySuper)
-              break;
-        }
-
-        MetaMethodIndex.Header last = header;
-        for (;iter.hasNext();) {
-            c = iter.next();
-            header = metaMethodIndex.getHeader(c.getTheClass());
-
-            if (last != null) {
-                metaMethodIndex.copyNonPrivateMethods(last, header);
-            }
-            last = header;
-
-            for (CachedMethod metaMethod : c.getMethods()) {
-                addToAllMethodsIfPublic(metaMethod);
-                addMetaMethodToIndex(metaMethod, header);
-            }
-
-            for (final MetaMethod method : getNewMetaMethods(c)) {
-                if (method.getName().equals("<init>") && !method.getDeclaringClass().equals(theCachedClass)) continue;
-                if (!newGroovyMethodsSet.contains(method)) {
-                    newGroovyMethodsSet.add(method);
-                    addMetaMethodToIndex(method, header);
-                }
-            }
-        }
-    }
-
-    private MetaMethod[] getNewMetaMethods(CachedClass c) {
-        if (theCachedClass != c)
-          return c.getNewMetaMethods();
-
-        return myNewMetaMethods;
-    }
-
-    private void addInterfaceMethods(Set<CachedClass> interfaces) {
-        MetaMethodIndex.Header header = metaMethodIndex.getHeader(theClass);
-        for (CachedClass c : interfaces) {
-            final CachedMethod[] m = c.getMethods();
-            for (int i = 0; i != m.length; ++i) {
-                MetaMethod method = m[i];
-                addMetaMethodToIndex(method, header);
-            }
-        }
-    }
-
-    protected LinkedList<CachedClass> getSuperClasses() {
-        LinkedList<CachedClass> superClasses = new LinkedList<CachedClass>();
-
-        if (theClass.isInterface()) {
-            superClasses.addFirst(ReflectionCache.OBJECT_CLASS);
-        } else {
-            for (CachedClass c = theCachedClass; c != null; c = c.getCachedSuperClass()) {
-                superClasses.addFirst(c);
-            }
-            if (theCachedClass.isArray && theClass != Object[].class && !theClass.getComponentType().isPrimitive()) {
-                superClasses.addFirst(ReflectionCache.OBJECT_ARRAY_CLASS);
-            }
-        }
-        return superClasses;
-    }
-
-    private void removeMultimethodsOverloadedWithPrivateMethods() {
-        MethodIndexAction mia = new MethodIndexAction() {
-            public boolean skipClass(Class clazz) {
-                return clazz == theClass;
-            }
-
-            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
-                if (e.methods == null)
-                  return;
-
-                boolean hasPrivate = false;
-                if (e.methods instanceof FastArray) {
-                    FastArray methods = (FastArray) e.methods;
-                    final int len = methods.size();
-                    final Object[] data = methods.getArray();
-                    for (int i = 0; i != len; ++i) {
-                        MetaMethod method = (MetaMethod) data[i];
-                        if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
-                            hasPrivate = true;
-                            break;
-                        }
-                    }
-                }
-                else {
-                    MetaMethod method = (MetaMethod) e.methods;
-                    if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
-                       hasPrivate = true;
-                    }
-                }
-
-                if (!hasPrivate) return;
-
-                // We have private methods for that name, so remove the
-                // multimethods. That is the same as in our index for
-                // super, so just copy the list from there. It is not
-                // possible to use a pointer here, because the methods
-                // in the index for super are replaced later by MOP
-                // methods like super$5$foo
-                final Object o = e.methodsForSuper;
-                if (o instanceof FastArray)
-                  e.methods = ((FastArray) o).copy();
-                else
-                  e.methods = o;
-            }
-        };
-        mia.iterate();
-    }
-
-
-    private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
-        // no MOP methods if not a child of GroovyObject
-        if (!isGroovyObject) return;
-
-        class MOPIter extends MethodIndexAction {
-            boolean useThis;
-
-            @Override
-            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
-                if (useThis) {
-                    if (e.methods == null)
-                      return;
-
-                    if (e.methods instanceof FastArray) {
-                        FastArray methods = (FastArray) e.methods;
-                        processFastArray(methods);
-                    }
-                    else {
-                        MetaMethod method = (MetaMethod) e.methods;
-                        if (method instanceof NewMetaMethod)
-                          return;
-                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
-                        String mopName = method.getMopName();
-                        int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
-                        if (index >= 0) {
-                            int from = index;
-                            while (from > 0 && mopMethods[from-1].getName().equals(mopName))
-                              from--;
-                            int to = index;
-                            while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
-                              to++;
-
-                            int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
-                            if (matchingMethod != -1) {
-                                e.methods = mopMethods[matchingMethod];
-                            }
-                        }
-                    }
-                }
-                else {
-                    if (e.methodsForSuper == null)
-                      return;
-
-                    if (e.methodsForSuper instanceof FastArray) {
-                        FastArray methods = (FastArray) e.methodsForSuper;
-                        processFastArray(methods);
-                    }
-                    else {
-                        MetaMethod method = (MetaMethod) e.methodsForSuper;
-                        if (method instanceof NewMetaMethod)
-                          return;
-                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
-                        String mopName = method.getMopName();
-                        // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
-                        // with the highest number. If we don't, no method may be found, leading to a stack overflow
-                        String[] decomposedMopName = decomposeMopName(mopName);
-                        int distance = Integer.parseInt(decomposedMopName[1]);
-                        while (distance>0) {
-                            String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
-                            int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
-                            if (index >= 0) {
-                                int from = index;
-                                while (from > 0 && mopMethods[from-1].getName().equals(fixedMopName))
-                                  from--;
-                                int to = index;
-                                while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(fixedMopName))
-                                  to++;
-    
-                                int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
-                                if (matchingMethod != -1) {
-                                    e.methodsForSuper = mopMethods[matchingMethod];
-                                    distance = 0;
-                                }
-                            }
-                            distance--;
-                        }
-                    }
-                }
-            }
-
-            private String[] decomposeMopName(final String mopName) {
-                int idx = mopName.indexOf("$");
-                if (idx>0) {
-                    int eidx = mopName.indexOf("$", idx+1);
-                    if (eidx>0) {
-                        return new String[] {
-                                mopName.substring(0, idx+1),
-                                mopName.substring(idx+1, eidx),
-                                mopName.substring(eidx)
-                        };
-                    }
-                }
-                return new String[]{"","0",mopName};
-            }
-
-            private void processFastArray(FastArray methods) {
-                final int len = methods.size();
-                final Object[] data = methods.getArray();
-                for (int i = 0; i != len; ++i) {
-                    MetaMethod method = (MetaMethod) data[i];
-                    if (method instanceof NewMetaMethod) continue;
-                    boolean isPrivate = Modifier.isPrivate(method.getModifiers());
-                    if (useThis ^ isPrivate) continue;
-                    String mopName = method.getMopName();
-                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
-                    if (index >= 0) {
-                        int from = index;
-                        while (from > 0 && mopMethods[from-1].getName().equals(mopName))
-                          from--;
-                        int to = index;
-                        while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
-                          to++;
-
-                        int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
-                        if (matchingMethod != -1) {
-                            methods.set(i, mopMethods[matchingMethod]);
-                        }
-                    }
-                }
-            }
-        }
-        MOPIter iter = new MOPIter();
-
-        // replace all calls for super with the correct MOP method
-        iter.useThis = false;
-        iter.iterate();
-        // replace all calls for this with the correct MOP method
-        iter.useThis = true;
-        iter.iterate();
-    }
-
-    private void inheritInterfaceNewMetaMethods(Set<CachedClass> interfaces) {
-        // add methods declared by DGM for interfaces
-        for (CachedClass cls : interfaces) {
-            MetaMethod methods[] = getNewMetaMethods(cls);
-            for (MetaMethod method : methods) {
-                boolean skip = false;
-                // skip DGM methods on an interface if the class already has the method
-                // but don't skip for GroovyObject-related methods as it breaks things :-(
-                if (method instanceof GeneratedMetaMethod && !isAssignableFrom(GroovyObject.class, method.getDeclaringClass().getTheClass())) {
-                    for (Method m : theClass.getMethods()) {
-                        if (method.getName().equals(m.getName())
-                                // below not true for DGM#push and also co-variant return scenarios
-                                //&& method.getReturnType().equals(m.getReturnType())
-                                && MetaMethod.equal(method.getParameterTypes(), m.getParameterTypes())) {
-                            skip = true;
-                            break;
-                        }
-                    }
-                }
-                if (!skip) {
-                    if (!newGroovyMethodsSet.contains(method)) {
-                        newGroovyMethodsSet.add(method);
-                    }
-                    addMetaMethodToIndex(method, mainClassMethodHeader);
-                }
-            }
-        }
-    }
-
-    private void connectMultimethods(List<CachedClass> superClasses, CachedClass firstGroovyClass) {
-        superClasses = DefaultGroovyMethods.reverse(superClasses);
-        MetaMethodIndex.Header last = null;
-        for (final CachedClass c : superClasses) {
-            MetaMethodIndex.Header methodIndex = metaMethodIndex.getHeader(c.getTheClass());
-            // We don't copy DGM methods to superclasses' indexes
-            // The reason we can do that is particular set of DGM methods in use,
-            // if at some point we will define DGM method for some Groovy class or
-            // for a class derived from such, we will need to revise this condition.
-            // It saves us a lot of space and some noticeable time
-            if (last != null) metaMethodIndex.copyNonPrivateNonNewMetaMethods(last, methodIndex);
-            last = methodIndex;
-
-            if (c == firstGroovyClass)
-                break;
-        }
-    }
-
-    private CachedClass calcFirstGroovySuperClass(Collection superClasses) {
-        if (theCachedClass.isInterface)
-          return ReflectionCache.OBJECT_CLASS;
-
-        CachedClass firstGroovy = null;
-        Iterator iter = superClasses.iterator();
-        for (; iter.hasNext();) {
-            CachedClass c = (CachedClass) iter.next();
-            if (GroovyObject.class.isAssignableFrom(c.getTheClass())) {
-              firstGroovy = c;
-              break;
-            }
-        }
-
-        if (firstGroovy == null)
-          firstGroovy = theCachedClass;
-        else {
-            if (firstGroovy.getTheClass() == GroovyObjectSupport.class && iter.hasNext()) {
-                firstGroovy = (CachedClass) iter.next();
-                if (firstGroovy.getTheClass() == Closure.class && iter.hasNext()) {
-                    firstGroovy = (CachedClass) iter.next();
-                }
-            }
-        }
-
-        return GroovyObject.class.isAssignableFrom(firstGroovy.getTheClass()) ? firstGroovy.getCachedSuperClass() : firstGroovy;
-    }
-
-    /**
-     * Gets all instance methods available on this class for the given name
-     *
-     * @return all the normal instance methods available on this class for the
-     *         given name
-     */
-    private Object getMethods(Class sender, String name, boolean isCallToSuper) {
-        Object answer;
-
-        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
-        if (entry == null)
-            answer = FastArray.EMPTY_LIST;
-        else
-            if (isCallToSuper) {
-                answer = entry.methodsForSuper;
-            } else {
-                answer = entry.methods;
-            }
-
-        if (answer == null) answer = FastArray.EMPTY_LIST;
-
-        if (!isCallToSuper) {
-            List used = GroovyCategorySupport.getCategoryMethods(name);
-            if (used != null) {
-                FastArray arr;
-                if (answer instanceof MetaMethod) {
-                    arr = new FastArray();
-                    arr.add(answer);
-                }
-                else
-                    arr = ((FastArray) answer).copy();
-
-                for (Iterator iter = used.iterator(); iter.hasNext();) {
-                    MetaMethod element = (MetaMethod) iter.next();
-                    if (!element.getDeclaringClass().getTheClass().isAssignableFrom(sender))
-                      continue;
-                    filterMatchingMethodForCategory(arr, element);
-                }
-                answer = arr;
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Returns all the normal static methods on this class for the given name 
-     *
-     * @return all the normal static methods available on this class for the
-     *         given name
-     */
-    private Object getStaticMethods(Class sender, String name) {
-        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
-        if (entry == null)
-            return FastArray.EMPTY_LIST;
-        Object answer = entry.staticMethods;
-        if (answer == null)
-            return FastArray.EMPTY_LIST;
-        return answer;
-    }
-
-    /**
-     * Returns whether this MetaClassImpl has been modified. Since MetaClassImpl
-     * is not designed for modification this method always returns false
-     *
-     * @return false
-     */
-    public boolean isModified() {
-        return false;  // MetaClassImpl not designed for modification, just return false
-    }
-
-    /**
-     *Adds an instance method to this metaclass.
-     *
-     * @param method The method to be added
-     */
-    public void addNewInstanceMethod(Method method) {
-        final CachedMethod cachedMethod = CachedMethod.find(method);
-        NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
-        final CachedClass declaringClass = newMethod.getDeclaringClass();
-        addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
-    }
-
-    private void addNewInstanceMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
-        if (!newGroovyMethodsSet.contains(newMethod)) {
-            newGroovyMethodsSet.add(newMethod);
-            addMetaMethodToIndex(newMethod, header);
-        }
-    }
-
-    /**
-     *Adds a static method to this metaclass.
-     *
-     * @param method The method to be added
-     */
-    public void addNewStaticMethod(Method method) {
-        final CachedMethod cachedMethod = CachedMethod.find(method);
-        NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
-        final CachedClass declaringClass = newMethod.getDeclaringClass();
-        addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
-    }
-
-    private void addNewStaticMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
-        if (!newGroovyMethodsSet.contains(newMethod)) {
-            newGroovyMethodsSet.add(newMethod);
-            addMetaMethodToIndex(newMethod, header);
-        }
-    }
-
-    /**
-     * Invoke a method on the given object with the given arguments.
-     *
-     * @param object The object the method should be invoked on.
-     * @param methodName The name of the method to invoke.
-     * @param arguments The arguments to the invoked method as null, a Tuple, an array or a single argument of any type.
-     *
-     * @return The result of the method invocation.
-     */
-    public Object invokeMethod(Object object, String methodName, Object arguments) {
-        if (arguments == null) {
-            return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
-        }
-        if (arguments instanceof Tuple) {
-            Tuple tuple = (Tuple) arguments;
-            return invokeMethod(object, methodName, tuple.toArray());
-        }
-        if (arguments instanceof Object[]) {
-            return invokeMethod(object, methodName, (Object[]) arguments);
-        } else {
-            return invokeMethod(object, methodName, new Object[]{arguments});
-        }
-    }
-
-    /**
-     * Invoke a missing method on the given object with the given arguments.
-     *
-     * @param instance The object the method should be invoked on.
-     * @param methodName The name of the method to invoke.
-     * @param arguments The arguments to the invoked method.
-     *
-     * @return The result of the method invocation.
-     */
-    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
-        return invokeMissingMethod(instance, methodName, arguments, null, false);
-    }
-    
-    /**
-     * Invoke a missing property on the given object with the given arguments.
-     *
-     * @param instance The object the method should be invoked on.
-     * @param propertyName The name of the property to invoke.
-     * @param optionalValue The (optional) new value for the property
-     * @param isGetter Wether the method is a getter
-     *
-     * @return The result of the method invocation.
-     */
-    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
-        Class theClass = instance instanceof Class ? (Class)instance : instance.getClass();
-        CachedClass superClass = theCachedClass;
-        while(superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
-            final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
-            if(property != null) {
-                onSuperPropertyFoundInHierarchy(property);
-                if(!isGetter) {
-                    property.setProperty(instance, optionalValue);
-                    return null;
-                }
-                else {
-                    return property.getProperty(instance);
-                }
-            }
-            superClass = superClass.getCachedSuperClass();
-        }
-        // got here to property not found, look for getProperty or setProperty overrides
-        if(isGetter) {
-            final Class[] getPropertyArgs = {String.class};
-            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
-            if(method != null && method instanceof ClosureMetaMethod) {
-                onGetPropertyFoundInHierarchy(method);
-                return method.invoke(instance,new Object[]{propertyName});
-            }
-        }
-        else {
-            final Class[] setPropertyArgs = {String.class, Object.class};
-            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
-            if(method != null && method instanceof ClosureMetaMethod) {
-                onSetPropertyFoundInHierarchy(method);
-                return method.invoke(instance, new Object[]{propertyName, optionalValue});
-            }
-        }
-
-        try {
-            if (!(instance instanceof Class)) {
-                if (isGetter) {
-                    if (propertyMissingGet != null) {
-                        return propertyMissingGet.invoke(instance, new Object[]{propertyName});
-                    }
-                } else {
-                    if (propertyMissingSet != null) {
-                        return propertyMissingSet.invoke(instance, new Object[]{propertyName, optionalValue});
-                    }
-                }
-            }
-        } catch (InvokerInvocationException iie) {
-            boolean shouldHandle = isGetter && propertyMissingGet != null;
-            if (!shouldHandle) shouldHandle = !isGetter && propertyMissingSet != null;
-            if (shouldHandle &&  iie.getCause() instanceof MissingPropertyException) {
-                throw (MissingPropertyException) iie.getCause();
-            }
-            throw iie;
-        }
-
-        if (instance instanceof Class && theClass != Class.class) {
-           final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
-           if (metaProperty != null)
-             if (isGetter)
-               return metaProperty.getProperty(instance);
-             else {
-               metaProperty.setProperty(instance, optionalValue);
-               return null;
-             }
-        }
-        throw new MissingPropertyExceptionNoStack(propertyName, theClass);
-    }
-
-    private Object invokeMissingMethod(Object instance, String methodName, Object[] arguments, RuntimeException original, boolean isCallToSuper) {
-        if (!isCallToSuper) {
-            Class instanceKlazz = instance.getClass();
-            if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
-              instanceKlazz = theClass;
-
-            Class[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);
-
-            MetaMethod method = findMixinMethod(methodName, argClasses);
-            if(method != null) {
-                onMixinMethodFound(method);
-                return method.invoke(instance, arguments);
-            }
-
-            method = findMethodInClassHierarchy(instanceKlazz, methodName, argClasses, this);
-            if(method != null) {
-                onSuperMethodFoundInHierarchy(method);
-                return method.invoke(instance, arguments);
-            }
-
-            // still not method here, so see if there is an invokeMethod method up the hierarchy
-            final Class[] invokeMethodArgs = {String.class, Object[].class};
-            method = findMethodInClassHierarchy(instanceKlazz, INVOKE_METHOD_METHOD, invokeMethodArgs, this );
-            if(method != null && method instanceof ClosureMetaMethod) {
-                onInvokeMethodFoundInHierarchy(method);
-                return method.invoke(instance, invokeMethodArgs);
-            }
-        }
-
-        if (methodMissing != null) {
-            try {
-                return methodMissing.invoke(instance, new Object[]{methodName, arguments});
-            } catch (InvokerInvocationException iie) {
-                if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
-                    MissingMethodException mme =  (MissingMethodException) iie.getCause();
-                    throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
-                                                            mme.getArguments(),mme.isStatic(),mme);
-                }
-                throw iie;
-            } catch (MissingMethodException mme) {
-                if (methodMissing instanceof ClosureMetaMethod)
-                    throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
-                                                        mme.getArguments(),mme.isStatic(),mme);
-                else
-                    throw mme;
-            }
-        } else if (original != null) throw original;
-        else throw new MissingMethodExceptionNoStack(methodName, theClass, arguments, false);
-    }
-
-    protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
-    }
-
-    protected void onMixinMethodFound(MetaMethod method) {
-    }
-
-    protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
-    }
-
-    protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
-    }
-
-    protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
-    }
-
-    protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
-    }
-
-
-    /**
-     * Hook to deal with the case of MissingProperty for static properties. The method will look attempt to look up
-     * "propertyMissing" handlers and invoke them otherwise thrown a MissingPropertyException
-     *
-     * @param instance      The instance
-     * @param propertyName  The name of the property
-     * @param optionalValue The value in the case of a setter
-     * @param isGetter      True if its a getter
-     * @return The value in the case of a getter or a MissingPropertyException
-     */
-    protected Object invokeStaticMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
-        MetaClass mc = instance instanceof Class ? registry.getMetaClass((Class) instance) : this;
-        if (isGetter) {
-            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, GETTER_MISSING_ARGS);
-            if (propertyMissing != null) {
-                return propertyMissing.invoke(instance, new Object[]{propertyName});
-            }
-        } else {
-            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, SETTER_MISSING_ARGS);
-            if (propertyMissing != null) {
-                return propertyMissing.invoke(instance, new Object[]{propertyName, optionalValue});
-            }
-        }
-
-        if (instance instanceof Class) {
-            throw new MissingPropertyException(propertyName, (Class) instance);
-        }
-        throw new MissingPropertyException(propertyName, theClass);
-    }
-
-    
-    /**
-     * Invokes a method on the given receiver for the specified arguments. 
-     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
-     *
-     *
-     * @param object The object which the method was invoked on
-     * @param methodName The name of the method
-     * @param originalArguments The arguments to the method
-     *
-     * @return The return value of the method
-     * 
-     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
-     */
-    public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
-        return invokeMethod(theClass, object, methodName, originalArguments, false, false);
-    }
-
-
-    /**
-     * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
-     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
-     *
-     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
-     * to the super class if necessary
-     *
-     * @param sender The java.lang.Class instance that invoked the method
-     * @param object The object which the method was invoked on
-     * @param methodName The name of the method
-     * @param originalArguments The arguments to the method
-     * @param isCallToSuper Whether the method is a call to a super class method
-     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
-     *
-     * @return The return value of the method
-     *
-     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
-     */
-    public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
-        checkInitalised();
-        if (object == null) {
-            throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
-        }
-
-        final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS : originalArguments;
-//        final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-//
-//        unwrap(arguments);
-
-        MetaMethod method = null;
-        if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
-            method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
-        } 
-        if (method==null) {
-            method = getMethodWithCaching(sender, methodName, arguments, isCallToSuper);
-        }
-        MetaClassHelper.unwrap(arguments);
-
-        if (method == null)
-            method = tryListParamMetaMethod(sender, methodName, isCallToSuper, arguments);
-
-        final boolean isClosure = object instanceof Closure;
-        if (isClosure) {
-            final Closure closure = (Closure) object;
-
-            final Object owner = closure.getOwner();
-
-            if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
-                final Class objectClass = object.getClass();
-                if (objectClass == MethodClosure.class) {
-                    final MethodClosure mc = (MethodClosure) object;
-                    methodName = mc.getMethod();
-                    final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
-                    final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
-                    return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
-                } else if (objectClass == CurriedClosure.class) {
-                    final CurriedClosure cc = (CurriedClosure) object;
-                    // change the arguments for an uncurried call
-                    final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
-                    final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
-                    final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
-                    return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
-                }
-                if (method==null) invokeMissingMethod(object,methodName,arguments);
-            }
-
-            final Object delegate = closure.getDelegate();
-            final boolean isClosureNotOwner = owner != closure;
-            final int resolveStrategy = closure.getResolveStrategy();
-
-            final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-
-            switch (resolveStrategy) {
-                case Closure.TO_SELF:
-                    method = closure.getMetaClass().pickMethod(methodName, argClasses);
-                    if (method != null) return method.invoke(closure, arguments);
-                    break;
-                case Closure.DELEGATE_ONLY:
-                    if (method == null && delegate != closure && delegate != null) {
-                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
-                        method = delegateMetaClass.pickMethod(methodName, argClasses);
-                        if (method != null)
-                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
-                        else if (delegate != closure && (delegate instanceof GroovyObject)) {
-                            return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
-                        }
-                    }
-                    break;
-                case Closure.OWNER_ONLY:
-                    if (method == null && owner != closure) {
-                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
-                        return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
-                    }
-                    break;
-                case Closure.DELEGATE_FIRST:
-                    if (method == null && delegate != closure && delegate != null) {
-                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
-                        method = delegateMetaClass.pickMethod(methodName, argClasses);
-                        if (method != null)
-                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
-                    }
-                    if (method == null && owner != closure) {
-                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
-                        method = ownerMetaClass.pickMethod(methodName, argClasses);
-                        if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
-                    }
-                    if (method == null && resolveStrategy != Closure.TO_SELF) {
-                        // still no methods found, test if delegate or owner are GroovyObjects
-                        // and invoke the method on them if so.
-                        MissingMethodException last = null;
-                        if (delegate != closure && (delegate instanceof GroovyObject)) {
-                            try {
-                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
-                            } catch (MissingMethodException mme) {
-                                if (last == null) last = mme;
-                            }
-                        }
-                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
-                            try {
-                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
-                            } catch (MissingMethodException mme) {
-                                last = mme;
-                            }
-                        }
-                        if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
-                    }
-
-                    break;
-                default:
-                    if (method == null && owner != closure) {
-                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
-                        method = ownerMetaClass.pickMethod(methodName, argClasses);
-                        if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
-                    }
-                    if (method == null && delegate != closure && delegate != null) {
-                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
-                        method = delegateMetaClass.pickMethod(methodName, argClasses);
-                        if (method != null)
-                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
-                    }
-                    if (method == null && resolveStrategy != Closure.TO_SELF) {
-                        // still no methods found, test if delegate or owner are GroovyObjects
-                        // and invoke the method on them if so.
-                        MissingMethodException last = null;
-                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
-                            try {
-                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
-                            } catch (MissingMethodException mme) {
-                                if (methodName.equals(mme.getMethod())) {
-                                    if (last == null) last = mme;
-                                } else {
-                                    throw mme;
-                                }
-                            }
-                            catch (InvokerInvocationException iie) {
-                                if (iie.getCause() instanceof MissingMethodException) {
-                                    MissingMethodException mme = (MissingMethodException) iie.getCause();
-                                    if (methodName.equals(mme.getMethod())) {
-                                        if (last == null) last = mme;
-                                    } else {
-                                        throw iie;
-                                    }
-                                }
-                                else
-                                  throw iie;
-                            }
-                        }
-                        if (delegate != closure && (delegate instanceof GroovyObject)) {
-                            try {
-                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
-                            } catch (MissingMethodException mme) {
-                                last = mme;
-                            }
-                            catch (InvokerInvocationException iie) {
-                                if (iie.getCause() instanceof MissingMethodException) {
-                                    last = (MissingMethodException) iie.getCause();
-                                }
-                                else
-                                  throw iie;
-                            }
-                        }
-                        if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
-                    }
-            }
-        }
-
-        if (method != null) {
-            return method.doMethodInvoke(object, arguments);
-        } else {
-            return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
-        }
-    }
-
-    private MetaMethod tryListParamMetaMethod(Class sender, String methodName, boolean isCallToSuper, Object[] arguments) {
-        MetaMethod method = null;
-        if (arguments.length == 1 && arguments[0] instanceof List) {
-            Object[] newArguments = ((List) arguments[0]).toArray();
-            method = createTransformMetaMethod(getMethodWithCaching(sender, methodName, newArguments, isCallToSuper));
-        }
-        return method;
-    }
-
-    protected MetaMethod createTransformMetaMethod(MetaMethod method) {
-        if (method == null) {
-            return null;
-        }
-
-        return new TransformMetaMethod(method) {
-            public Object invoke(Object object, Object[] arguments) {
-                Object firstArgument = arguments[0];
-                List list = (List) firstArgument;
-                arguments = list.toArray();
-                return super.invoke(object, arguments);
-            }
-        };
-    }
-
-    private Object invokePropertyOrMissing(Object object, String methodName, Object[] originalArguments, boolean fromInsideClass, boolean isCallToSuper) {
-        // if no method was found, try to find a closure defined as a field of the class and run it
-        Object value = null;
-        final MetaProperty metaProperty = this.getMetaProperty(methodName, false);
-        if (metaProperty != null)
-          value = metaProperty.getProperty(object);
-        else {
-            if (object instanceof Map)
-              value = ((Map)object).get(methodName);
-        }
-
-        if (value instanceof Closure) {  // This test ensures that value != this If you ever change this ensure that value != this
-            Closure closure = (Closure) value;
-            MetaClass delegateMetaClass = closure.getMetaClass();
-            return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
-        }
-
-        if (object instanceof Script) {
-            Object bindingVar = ((Script) object).getBinding().getVariables().get(methodName);
-            if (bindingVar != null) {
-                MetaClass bindingVarMC = ((MetaClassRegistryImpl) registry).getMetaClass(bindingVar);
-                return bindingVarMC.invokeMethod(bindingVar, CLOSURE_CALL_METHOD, originalArguments);
-            }
-        }
-        return invokeMissingMethod(object, methodName, originalArguments, null, isCallToSuper);
-    }
-
-    private MetaClass lookupObjectMetaClass(Object object) {
-        if (object instanceof GroovyObject) {
-            GroovyObject go = (GroovyObject) object;
-            return go.getMetaClass();
-        }
-        Class ownerClass = object.getClass();
-        if (ownerClass == Class.class) ownerClass = (Class) object;
-        MetaClass metaClass = registry.getMetaClass(ownerClass);
-        return metaClass;
-    }
-
-    private static Object invokeMethodOnGroovyObject(String methodName, Object[] originalArguments, Object owner) {
-        GroovyObject go = (GroovyObject) owner;
-        return go.invokeMethod(methodName, originalArguments);
-    }
-
-    public MetaMethod getMethodWithCaching(Class sender, String methodName, Object[] arguments, boolean isCallToSuper) {
-        // let's try use the cache to find the method
-        if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
-            return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
-        } else {
-            final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, methodName);
-            if (e == null)
-              return null;
-
-            return isCallToSuper ? getSuperMethodWithCaching(arguments, e) : getNormalMethodWithCaching(arguments, e);
-        }
-    }
-
-    private static boolean sameClasses(Class[] params, Class[] arguments) {
-        // we do here a null check because the params field might not have been set yet
-        if (params == null) return false;
-
-        if (params.length != arguments.length)
-            return false;
-
-        for (int i = params.length - 1; i >= 0; i--) {
-            Object arg = arguments[i];
-            if (arg != null) {
-                if (params[i] != arguments[i]) return false;
-            } else return false;
-        }
-
-        return true;
-    }
-
-    // This method should be called by CallSite only
-    private MetaMethod getMethodWithCachingInternal (Class sender, CallSite site, Class [] params) {
-        if (GroovyCategorySupport.hasCategoryInCurrentThread())
-            return getMethodWithoutCaching(sender, site.getName (), params, false);
-
-        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, site.getName());
-        if (e == null) {
-            return null;
-        }
-
-        MetaMethodIndex.CacheEntry cacheEntry;
-        final Object methods = e.methods;
-        if (methods == null)
-          return null;
-
-        cacheEntry = e.cachedMethod;
-        if (cacheEntry != null && (sameClasses(cacheEntry.params, params))) {
-             return cacheEntry.method;
-        }
-
-        cacheEntry = new MetaMethodIndex.CacheEntry (params, (MetaMethod) chooseMethod(e.name, methods, params));
-        e.cachedMethod = cacheEntry;
-        return cacheEntry.method;
-    }
-
-    private MetaMethod getSuperMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
-        MetaMethodIndex.CacheEntry cacheEntry;
-        if (e.methodsForSuper == null)
-          return null;
-
-        cacheEntry = e.cachedMethodForSuper;
-
-        if (cacheEntry != null &&
-            MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methodsForSuper instanceof MetaMethod))
-        {
-            MetaMethod method = cacheEntry.method;
-            if (method!=null) return method;
-        }
-
-        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
-        MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methodsForSuper, classes);
-        cacheEntry = new MetaMethodIndex.CacheEntry (classes, method.isAbstract()?null:method);
-
-        e.cachedMethodForSuper = cacheEntry;
-
-        return cacheEntry.method;
-    }
-
-    private MetaMethod getNormalMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
-        MetaMethodIndex.CacheEntry cacheEntry;
-        final Object methods = e.methods;
-        if (methods == null)
-          return null;
-
-        cacheEntry = e.cachedMethod;
-
-        if (cacheEntry != null &&
-            MetaClassHelper.sameClasses(cacheEntry.params, arguments, methods instanceof MetaMethod))
-        {
-            MetaMethod method = cacheEntry.method;
-            if (method!=null) return method;
-        }
-
-        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
-        cacheEntry = new MetaMethodIndex.CacheEntry (classes, (MetaMethod) chooseMethod(e.name, methods, classes));
-
-        e.cachedMethod = cacheEntry;
-
-        return cacheEntry.method;
-    }
-
-    public Constructor retrieveConstructor(Class[] arguments) {
-        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
-        if (constructor != null) {
-            return constructor.cachedConstructor;
-        }
-        constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
-        if (constructor != null) {
-            return constructor.cachedConstructor;
-        }
-        return null;
-    }
-
-    public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
-        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(theClass, methodName);
-        MetaMethodIndex.CacheEntry cacheEntry;
-        if (e != null) {
-            cacheEntry = e.cachedStaticMethod;
-
-            if (cacheEntry != null &&
-                MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.staticMethods instanceof MetaMethod))
-            {
-                 return cacheEntry.method;
-            }
-
-            final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
-            cacheEntry = new MetaMethodIndex.CacheEntry (classes, pickStaticMethod(methodName, classes));
-
-            e.cachedStaticMethod = cacheEntry;
-
-            return cacheEntry.method;
-        }
-        else
-          return pickStaticMethod(methodName, MetaClassHelper.convertToTypeArray(arguments));
-    }
-
-    public MetaMethod getMethodWithoutCaching(Class sender, String methodName, Class[] arguments, boolean isCallToSuper) {
-        MetaMethod method = null;
-        Object methods = getMethods(sender, methodName, isCallToSuper);
-        if (methods != null) {
-            method = (MetaMethod) chooseMethod(methodName, methods, arguments);
-        }
-        return method;
-    }
-
-    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
-        checkInitalised();
-
-        final Class sender = object instanceof Class ? (Class) object : object.getClass();
-        if (sender != theClass) {
-            MetaClass mc = registry.getMetaClass(sender);
-            return mc.invokeStaticMethod(sender, methodName, arguments);
-        }
-        if (sender == Class.class) {
-            return invokeMethod(object, methodName, arguments);
-        }
-
-        if (arguments == null) arguments = EMPTY_ARGUMENTS;
-//        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-
-        MetaMethod method = retrieveStaticMethod(methodName, arguments);
-        // let's try use the cache to find the method
-
-        if (method != null) {
-            MetaClassHelper.unwrap(arguments);
-            return method.doMethodInvoke(object, arguments);
-        }
-        Object prop = null;
-        try {
-            prop = getProperty(theClass, theClass, methodName, false, false);
-        } catch (MissingPropertyException mpe) {
-            // ignore
-        }
-
-        if (prop instanceof Closure) {
-            return invokeStaticClosureProperty(arguments, prop);
-        }
-
-        Object[] originalArguments = arguments.clone();
-        MetaClassHelper.unwrap(arguments);
-
-        Class superClass = sender.getSuperclass();
-        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-        while (superClass != Object.class && superClass != null) {
-            MetaClass mc = registry.getMetaClass(superClass);
-            method = mc.getStaticMetaMethod(methodName, argClasses);
-            if (method != null) return method.doMethodInvoke(object, arguments);
-
-            try {
-                prop = mc.getProperty(superClass, superClass, methodName, false, false);
-            } catch (MissingPropertyException mpe) {
-                // ignore
-            }
-
-            if (prop instanceof Closure) {
-                return invokeStaticClosureProperty(originalArguments, prop);
-            }
-
-            superClass = superClass.getSuperclass();
-        }
-
-        if (prop != null) {
-            MetaClass propMC = registry.getMetaClass(prop.getClass());
-            return propMC.invokeMethod(prop, CLOSURE_CALL_METHOD, arguments);
-        }
-
-        return invokeStaticMissingMethod(sender, methodName, arguments);
-    }
-
-    private static Object invokeStaticClosureProperty(Object[] originalArguments, Object prop) {
-        Closure closure = (Closure) prop;
-        MetaClass delegateMetaClass = closure.getMetaClass();
-        return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, false);
-    }
-
-    private Object invokeStaticMissingMethod(Class sender, String methodName, Object[] arguments) {
-        MetaMethod metaMethod = getStaticMetaMethod(STATIC_METHOD_MISSING, METHOD_MISSING_ARGS);
-        if (metaMethod != null) {
-            return metaMethod.invoke(sender, new Object[]{methodName, arguments});
-        }
-        throw new MissingMethodException(methodName, sender, arguments, true);
-    }
-
-    private MetaMethod pickStaticMethod(String methodName, Class[] arguments) {
-        MetaMethod method = null;
-        MethodSelectionException mse = null;
-        Object methods = getStaticMethods(theClass, methodName);
-
-        if (!(methods instanceof FastArray) || !((FastArray)methods).isEmpty()) {
-            try {
-                method = (MetaMethod) chooseMethod(methodName, methods, arguments);
-            } catch(MethodSelectionException msex) {
-                mse = msex;
-            }
-        }
-        if (method == null && theClass != Class.class) {
-            MetaClass classMetaClass = registry.getMetaClass(Class.class);
-            method = classMetaClass.pickMethod(methodName, arguments);
-        }
-        if (method == null) {
-            method = (MetaMethod) chooseMethod(methodName, methods, MetaClassHelper.convertToTypeArray(arguments));
-        }
-
-        if (method == null && mse != null) {
-            throw mse;
-        } else {
-            return method;
-        }
-    }
-
-    public Object invokeConstructor(Object[] arguments) {
-        return invokeConstructor(theClass, arguments);
-    }
-
-    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
-        if (numberOfConstructors==-1) {
-            return selectConstructorAndTransformArguments1(arguments);
-        } else {
-            // falling back to pre 2.1.9 selection algorithm
-            // in practice this branch will only be reached if the class calling this code is a Groovy class
-            // compiled with an earlier version of the Groovy compiler
-            return selectConstructorAndTransformArguments0(numberOfConstructors, arguments);
-        }
-
-
-    }
-
-    private int selectConstructorAndTransformArguments0(final int numberOfConstructors, Object[] arguments) {
-        //TODO: that is just a quick prototype, not the real thing!
-        if (numberOfConstructors != constructors.size()) {
-            throw new IncompatibleClassChangeError("the number of constructors during runtime and compile time for " +
-                    this.theClass.getName() + " do not match. Expected " + numberOfConstructors + " but got " + constructors.size());
-        }
-
-        CachedConstructor constructor = createCachedConstructor(arguments);
-        List l = new ArrayList(constructors.toList());
-        Comparator comp = new Comparator() {
-            public int compare(Object arg0, Object arg1) {
-                CachedConstructor c0 = (CachedConstructor) arg0;
-                CachedConstructor c1 = (CachedConstructor) arg1;
-                String descriptor0 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c0.getNativeParameterTypes());
-                String descriptor1 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c1.getNativeParameterTypes());
-                return descriptor0.compareTo(descriptor1);
-            }
-        };
-        Collections.sort(l, comp);
-        int found = -1;
-        for (int i = 0; i < l.size(); i++) {
-            if (l.get(i) != constructor) continue;
-            found = i;
-            break;
-        }
-        // NOTE: must be changed to "1 |" if constructor was vargs
-        return 0 | (found << 8);
-    }
-
-    private CachedConstructor createCachedConstructor(Object[] arguments) {
-        if (arguments == null) arguments = EMPTY_ARGUMENTS;
-        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-        MetaClassHelper.unwrap(arguments);
-        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
-        if (constructor == null) {
-            constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
-        }
-        if (constructor == null) {
-            throw new GroovyRuntimeException(
-                    "Could not find matching constructor for: "
-                            + theClass.getName()
-                            + "(" + InvokerHelper.toTypeString(arguments) + ")");
-        }
-        return constructor;
-    }
-
-    /**
-     * Constructor selection algorithm for Groovy 2.1.9+.
-     * This selection algorithm was introduced as a workaround for GROOVY-6080. Instead of generating an index between
-     * 0 and N where N is the number of super constructors at the time the class is compiled, this algorithm uses
-     * a hash of the constructor descriptor instead.
-     *
-     * This has the advantage of letting the super class add new constructors while being binary compatible. But there
-     * are still problems with this approach:
-     * <ul>
-     *     <li>There's a risk of hash collision, even if it's very low (two constructors of the same class must have the same hash)</li>
-     *     <li>If the super class adds a new constructor which takes as an argument a superclass of an existing constructor parameter and
-     *     that this new constructor is selected at runtime, it would not find it.</li>
-     * </ul>
-     *
-     * Hopefully in the last case, the error message is much nicer now since it explains that it's a binary incompatible change.
-     *
-     * @param arguments the actual constructor call arguments
-     * @return a hash used to identify the constructor to be called
-     * @since 2.1.9
-     */
-    private int selectConstructorAndTransformArguments1(Object[] arguments) {
-        CachedConstructor constructor = createCachedConstructor(arguments);
-        final String methodDescriptor = BytecodeHelper.getMethodDescriptor(Void.TYPE, constructor.getNativeParameterTypes());
-        // keeping 3 bits for additional information such as vargs
-        return BytecodeHelper.hashCode(methodDescriptor);
-    }
-
-
-    /**
-     * checks if the initialisation of the class id complete.
-     * This method should be called as a form of assert, it is no
-     * way to test if there is still initialisation work to be done.
-     * Such logic must be implemented in a different way.
-     *
-     * @throws IllegalStateException if the initialisation is incomplete yet
-     */
-    protected void checkInitalised() {
-        if (!isInitialized())
-            throw new IllegalStateException(
-                    "initialize must be called for meta " +
-                            "class of " + theClass +
-                            "(" + this.getClass() + ") " +
-                            "to complete initialisation process " +
-                            "before any invocation or field/property " +
-                            "access can be done");
-    }
-    
-    /**
-     * This is a helper class introduced in Groovy 2.1.0, which is used only by
-     * indy. This class is for internal use only.
-     * @since Groovy 2.1.0
-     */
-    public static final class MetaConstructor extends MetaMethod {
-        private final CachedConstructor cc;
-        private final boolean beanConstructor;
-        private MetaConstructor(CachedConstructor cc, boolean bean) {
-            super(cc.getNativeParameterTypes());
-            this.setParametersTypes(cc.getParameterTypes());
-            this.cc = cc;
-            this.beanConstructor = bean;
-        }
-        @Override
-        public int getModifiers() { return cc.getModifiers(); }
-        @Override
-        public String getName() { return "<init>"; }
-        @Override
-        public Class getReturnType() { return cc.getCachedClass().getTheClass(); }
-        @Override
-        public CachedClass getDeclaringClass() { return cc.getCachedClass(); }
-        @Override
-        public Object invoke(Object object, Object[] arguments) {
-            return cc.doConstructorInvoke(arguments);
-        }
-        public CachedConstructor getCachedConstrcutor() { return cc; }
-        public boolean isBeanConstructor() { return beanConstructor; }
-    }
-    
-    /**
-     * This is a helper method added in Groovy 2.1.0, which is used only by indy.
-     * This method is for internal use only.
-     * @since Groovy 2.1.0
-     */
-    public MetaMethod retrieveConstructor(Object[] arguments) {
-        checkInitalised();
-        if (arguments == null) arguments = EMPTY_ARGUMENTS;
-        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-        MetaClassHelper.unwrap(arguments);
-        Object res = chooseMethod("<init>", constructors, argClasses);
-        if (res instanceof MetaMethod) return (MetaMethod) res;
-        CachedConstructor constructor = (CachedConstructor) res;
-        if (constructor != null) return new MetaConstructor(constructor, false);
-        if (arguments.length == 1 && arguments[0] instanceof Map) {
-            res = chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
-        } else if (
-                arguments.length == 2 && arguments[1] instanceof Map && 
-                theClass.getEnclosingClass()!=null && 
-                theClass.getEnclosingClass().isAssignableFrom(argClasses[0])) 
-        {
-            res = chooseMethod("<init>", constructors, new Class[]{argClasses[0]});
-        }
-        if (res instanceof MetaMethod) return (MetaMethod) res;
-        constructor = (CachedConstructor) res;
-        if (constructor != null) return new MetaConstructor(constructor, true);
-
-        return null;
-    }
-    
-    private Object invokeConstructor(Class at, Object[] arguments) {
-        checkInitalised();
-        if (arguments == null) arguments = EMPTY_ARGUMENTS;
-        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-        MetaClassHelper.unwrap(arguments);
-        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
-        if (constructor != null) {
-            return constructor.doConstructorInvoke(arguments);
-        }
-
-        if (arguments.length == 1) {
-            Object firstArgument = arguments[0];
-            if (firstArgument instanceof Map) {
-                constructor = (CachedConstructor) chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
-                if (constructor != null) {
-                    Object bean = constructor.doConstructorInvoke(MetaClassHelper.EMPTY_ARRAY);
-                    setProperties(bean, ((Map) firstArgument));
-                    return bean;
-                }
-            }
-        }
-        throw new GroovyRuntimeException(
-                "Could not find matching constructor for: "
-                        + theClass.getName()
-                        + "(" + InvokerHelper.toTypeString(arguments) + ")");
-    }
-
-    /**
-     * Sets a number of bean properties from the given Map where the keys are
-     * the String names of properties and the values are the values of the
-     * properties to set
-     */
-    public void setProperties(Object bean, Map map) {
-        checkInitalised();
-        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
-            Map.Entry entry = (Map.Entry) iter.next();
-            String key = entry.getKey().toString();
-
-            Object value = entry.getValue();
-            setProperty(bean, key, value);
-        }
-    }
-
-    /**
-     * @return the given property's value on the object
-     */
-    public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {
-
-        //----------------------------------------------------------------------
-        // handling of static
-        //----------------------------------------------------------------------
-        boolean isStatic = theClass != Class.class && object instanceof Class;
-        if (isStatic && object != theClass) {
-            MetaClass mc = registry.getMetaClass((Class) object);
-            return mc.getProperty(sender, object, name, useSuper, false);
-        }
-
-        checkInitalised();
-
-        //----------------------------------------------------------------------
-        // turn getProperty on a Map to get on the Map itself
-        //----------------------------------------------------------------------
-        if (!isStatic && this.isMap) {
-            return ((Map) object).get(name);
-        }
-
-        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, sender, name, useSuper, isStatic);
-        MetaMethod method = methodAndProperty.getFirst();
-
-        //----------------------------------------------------------------------
-        // getter
-        //----------------------------------------------------------------------
-        MetaProperty mp = methodAndProperty.getSecond();
-
-        //----------------------------------------------------------------------
-        // field
-        //----------------------------------------------------------------------
-        if (method == null && mp != null) {
-            try {
-                return mp.getProperty(object);
-            } catch (IllegalArgumentException e) {
-                // can't access the field directly but there may be a getter
-                mp = null;
-            } catch (CacheAccessControlException e) {
-                // can't access the field directly but there may be a getter
-                mp = null;
-            }
-        }
-
-        //----------------------------------------------------------------------
-        // generic get method
-        //----------------------------------------------------------------------
-        // check for a generic get method provided through a category
-        Object[] arguments = EMPTY_ARGUMENTS;
-        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
-            method = getCategoryMethodGetter(sender, "get", true);
-            if (method != null) arguments = new Object[]{name};
-        }
-
-        // the generic method is valid, if available (!=null), if static or
-        // if it is not static and we do no static access
-        if (method == null && genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
-            arguments = new Object[]{name};
-            method = genericGetMethod;
-        }
-
-        //----------------------------------------------------------------------
-        // special cases
-        //----------------------------------------------------------------------
-        if (method == null) {
-            /** todo these special cases should be special MetaClasses maybe */
-            if (theClass != Class.class && object instanceof Class) {
-                MetaClass mc = registry.getMetaClass(Class.class);
-                return mc.getProperty(Class.class, object, name, useSuper, false);
-            } else if (object instanceof Collection) {
-                return DefaultGroovyMethods.getAt((Collection) object, name);
-            } else if (object instanceof Object[]) {
-                return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), name);
-            } else {
-                MetaMethod addListenerMethod = listeners.get(name);
-                if (addListenerMethod != null) {
-                    //TODO: one day we could try return the previously registered Closure listener for easy removal
-                    return null;
-                }
-            }
-        } else {
-
-            //----------------------------------------------------------------------
-            // executing the getter method
-            //----------------------------------------------------------------------
-            return method.doMethodInvoke(object, arguments);
-        }
-
-        //----------------------------------------------------------------------
-        // error due to missing method/field
-        //----------------------------------------------------------------------
-        if (isStatic || object instanceof Class)
-            return invokeStaticMissingProperty(object, name, null, true);
-        else
-            return invokeMissingProperty(object, name, null, true);
-    }
-
-    public MetaProperty getEffectiveGetMetaProperty(final Class sender, final Object object, String name, final boolean useSuper) {
-
-        //----------------------------------------------------------------------
-        // handling of static
-        //----------------------------------------------------------------------
-        boolean isStatic = theClass != Class.class && object instanceof Class;
-        if (isStatic && object != theClass) {
-            return new MetaProperty(name, Object.class) {
-                final MetaClass mc = registry.getMetaClass((Class) object);
-
-                public Object getProperty(Object object) {
-                    return mc.getProperty(sender, object, name, useSuper,false);
-                }
-
-                public void setProperty(Object object, Object newValue) {
-                    throw new UnsupportedOperationException();
-                }
-            };
-        }
-
-        checkInitalised();
-
-        //----------------------------------------------------------------------
-        // turn getProperty on a Map to get on the Map itself
-        //----------------------------------------------------------------------
-        if (!isStatic && this.isMap) {
-            return new MetaProperty(name, Object.class) {
-                public Object getProperty(Object object) {
-                    return ((Map) object).get(name);
-                }
-
-                public void setProperty(Object object, Object newValue) {
-                    throw new UnsupportedOperationException();
-                }
-            };
-        }
-
-        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, theClass, name, useSuper, isStatic);
-        MetaMethod method = methodAndProperty.getFirst();
-
-        //----------------------------------------------------------------------
-        // getter
-        //----------------------------------------------------------------------
-        MetaProperty mp = methodAndProperty.getSecond();
-
-        //----------------------------------------------------------------------
-        // field
-        //----------------------------------------------------------------------
-        if (method != null)
-            return new GetBeanMethodMetaProperty(name, method);
-
-        if (mp != null) {
-            return mp;
-//            try {
-//                return mp.getProperty(object);
-//            } catch (IllegalArgumentException e) {
-//                // can't access the field directly but there may be a getter
-//                mp = null;
-//            }
-        }
-
-        //----------------------------------------------------------------------
-        // generic get method
-        //----------------------------------------------------------------------
-        // check for a generic get method provided through a category
-        if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
-            method = getCategoryMethodGetter(sender, "get", true);
-            if (method != null)
-                return new GetMethodMetaProperty(name, method);
-        }
-
-        // the generic method is valid, if available (!=null), if static or
-        // if it is not static and we do no static access
-        if (genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
-            method = genericGetMethod;
-            return new GetMethodMetaProperty(name, method);
-        }
-
-        //----------------------------------------------------------------------
-        // special cases
-        //----------------------------------------------------------------------
-        /** todo these special cases should be special MetaClasses maybe */
-        if (theClass != Class.class && object instanceof Class) {
-            return new MetaProperty(name, Object.class) {
-                public Object getPro

<TRUNCATED>

[45/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/StatementReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/StatementReplacer.groovy b/src/main/groovy/StatementReplacer.groovy
deleted file mode 100644
index 3a9dab3..0000000
--- a/src/main/groovy/StatementReplacer.groovy
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.CodeVisitorSupport
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.DoWhileStatement
-import org.codehaus.groovy.ast.stmt.ForStatement
-import org.codehaus.groovy.ast.stmt.IfStatement
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.ast.stmt.WhileStatement
-
-/**
- * Tool for replacing Statement objects in an AST by other Statement instances.
- *
- * Within @TailRecursive it is used to swap ReturnStatements with looping back to RECUR label
- *
- * @author Johannes Link
- */
-@CompileStatic
-class StatementReplacer extends CodeVisitorSupport {
-
-    Closure<Boolean> when = { Statement node -> false }
-    Closure<Statement> replaceWith = { Statement statement -> statement }
-    int closureLevel = 0
-
-    void replaceIn(ASTNode root) {
-        root.visit(this)
-    }
-
-    public void visitClosureExpression(ClosureExpression expression) {
-        closureLevel++
-        try {
-            super.visitClosureExpression(expression)
-        } finally {
-            closureLevel--
-        }
-    }
-
-    public void visitBlockStatement(BlockStatement block) {
-        List<Statement> copyOfStatements = new ArrayList<Statement>(block.statements)
-        copyOfStatements.eachWithIndex { Statement statement, int index ->
-            replaceIfNecessary(statement) { Statement node -> block.statements[index] = node }
-        }
-        super.visitBlockStatement(block);
-    }
-
-    public void visitIfElse(IfStatement ifElse) {
-        replaceIfNecessary(ifElse.ifBlock) { Statement s -> ifElse.ifBlock = s }
-        replaceIfNecessary(ifElse.elseBlock) { Statement s -> ifElse.elseBlock = s }
-        super.visitIfElse(ifElse);
-    }
-
-    public void visitForLoop(ForStatement forLoop) {
-        replaceIfNecessary(forLoop.loopBlock) { Statement s -> forLoop.loopBlock = s }
-        super.visitForLoop(forLoop);
-    }
-
-    public void visitWhileLoop(WhileStatement loop) {
-        replaceIfNecessary(loop.loopBlock) { Statement s -> loop.loopBlock = s }
-        super.visitWhileLoop(loop);
-    }
-
-    public void visitDoWhileLoop(DoWhileStatement loop) {
-        replaceIfNecessary(loop.loopBlock) { Statement s -> loop.loopBlock = s }
-        super.visitDoWhileLoop(loop);
-    }
-
-
-    private void replaceIfNecessary(Statement nodeToCheck, Closure replacementCode) {
-        if (conditionFulfilled(nodeToCheck)) {
-            ASTNode replacement = replaceWith(nodeToCheck)
-            replacement.setSourcePosition(nodeToCheck);
-            replacement.copyNodeMetaData(nodeToCheck);
-            replacementCode(replacement)
-        }
-    }
-
-    private boolean conditionFulfilled(ASTNode nodeToCheck) {
-        if (when.maximumNumberOfParameters < 2)
-            return when(nodeToCheck)
-        else
-            return when(nodeToCheck, isInClosure())
-    }
-
-    private boolean isInClosure() {
-        closureLevel > 0
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/StringUtil.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/StringUtil.groovy b/src/main/groovy/StringUtil.groovy
deleted file mode 100644
index ed83e53..0000000
--- a/src/main/groovy/StringUtil.groovy
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  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.util
-
-import groovy.transform.CompileStatic
-
-/**
- * String utility functions.
- */
-@CompileStatic
-class StringUtil {
-    /**
-     * Provides Groovy with functionality similar to the unix tr command
-     * which translates a string replacing characters from a source set
-     * with characters from a replacement set.
-     *
-     * @since 1.7.3
-     */
-    static String tr(String text, String source, String replacement) {
-        if (!text || !source) { return text }
-        source = expandHyphen(source)
-        replacement = expandHyphen(replacement)
-
-        // padding replacement with a last character, if necessary
-        replacement = replacement.padRight(source.size(), replacement[replacement.size() - 1])
-
-        return text.collect { String original ->
-            if (source.contains(original)) {
-                replacement[source.lastIndexOf(original)]
-            } else {
-                original
-            }
-        }.join('')
-    }
-
-    // no expansion for hyphen at start or end of Strings
-    private static String expandHyphen(String text) {
-        if (!text.contains('-')) { return text }
-        return text.replaceAll(/(.)-(.)/, { all, begin, end -> (begin..end).join('') })
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/TailRecursiveASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/TailRecursiveASTTransformation.groovy b/src/main/groovy/TailRecursiveASTTransformation.groovy
deleted file mode 100644
index 0605f18..0000000
--- a/src/main/groovy/TailRecursiveASTTransformation.groovy
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import groovy.transform.Memoized
-import groovy.transform.TailRecursive
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
-import org.codehaus.groovy.ast.expr.TernaryExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.classgen.ReturnAdder
-import org.codehaus.groovy.classgen.VariableScopeVisitor
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.transform.AbstractASTTransformation
-import org.codehaus.groovy.transform.GroovyASTTransformation
-
-/**
- * Handles generation of code for the @TailRecursive annotation.
- *
- * It's doing its work in the earliest possible compile phase
- *
- * @author Johannes Link
- */
-@CompileStatic
-@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
-class TailRecursiveASTTransformation extends AbstractASTTransformation {
-
-    private static final Class MY_CLASS = TailRecursive.class;
-    private static final ClassNode MY_TYPE = new ClassNode(MY_CLASS);
-    static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage()
-    private HasRecursiveCalls hasRecursiveCalls = new HasRecursiveCalls()
-    private TernaryToIfStatementConverter ternaryToIfStatement = new TernaryToIfStatementConverter()
-
-
-    @Override
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        init(nodes, source);
-
-        MethodNode method = nodes[1] as MethodNode
-
-        if (method.isAbstract()) {
-            addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", method);
-            return;
-        }
-
-        if (hasAnnotation(method, ClassHelper.make(Memoized))) {
-            ClassNode memoizedClassNode = ClassHelper.make(Memoized)
-            for (AnnotationNode annotationNode in method.annotations) {
-                if (annotationNode.classNode == MY_TYPE)
-                    break
-                if (annotationNode.classNode == memoizedClassNode) {
-                    addError("Annotation " + MY_TYPE_NAME + " must be placed before annotation @Memoized.", annotationNode)
-                    return
-                }
-            }
-        }
-
-        if (!hasRecursiveMethodCalls(method)) {
-            AnnotationNode annotationNode = method.getAnnotations(ClassHelper.make(TailRecursive))[0]
-            addError("No recursive calls detected. You must remove annotation " + MY_TYPE_NAME + ".", annotationNode)
-            return;
-        }
-
-        transformToIteration(method, source)
-        ensureAllRecursiveCallsHaveBeenTransformed(method)
-    }
-
-    private boolean hasAnnotation(MethodNode methodNode, ClassNode annotation) {
-        List annots = methodNode.getAnnotations(annotation);
-        return (annots != null && annots.size() > 0);
-    }
-
-
-    private void transformToIteration(MethodNode method, SourceUnit source) {
-        if (method.isVoidMethod()) {
-            transformVoidMethodToIteration(method, source)
-        } else {
-            transformNonVoidMethodToIteration(method, source)
-        }
-    }
-
-    private void transformVoidMethodToIteration(MethodNode method, SourceUnit source) {
-        addError("Void methods are not supported by @TailRecursive yet.", method)
-    }
-
-    private void transformNonVoidMethodToIteration(MethodNode method, SourceUnit source) {
-        addMissingDefaultReturnStatement(method)
-        replaceReturnsWithTernariesToIfStatements(method)
-        wrapMethodBodyWithWhileLoop(method)
-
-        Map<String, Map> nameAndTypeMapping = name2VariableMappingFor(method)
-        replaceAllAccessToParams(method, nameAndTypeMapping)
-        addLocalVariablesForAllParameters(method, nameAndTypeMapping) //must happen after replacing access to params
-
-        Map<Integer, Map> positionMapping = position2VariableMappingFor(method)
-        replaceAllRecursiveReturnsWithIteration(method, positionMapping)
-        repairVariableScopes(source, method)
-    }
-
-    private void repairVariableScopes(SourceUnit source, MethodNode method) {
-        new VariableScopeVisitor(source).visitClass(method.declaringClass)
-    }
-
-    private void replaceReturnsWithTernariesToIfStatements(MethodNode method) {
-        Closure<Boolean> whenReturnWithTernary = { ASTNode node ->
-            if (!(node instanceof ReturnStatement)) {
-                return false
-            }
-            return (((ReturnStatement) node).expression instanceof TernaryExpression)
-        }
-        Closure<Statement> replaceWithIfStatement = { ReturnStatement statement ->
-            ternaryToIfStatement.convert(statement)
-        }
-        StatementReplacer replacer = new StatementReplacer(when: whenReturnWithTernary, replaceWith: replaceWithIfStatement)
-        replacer.replaceIn(method.code)
-
-    }
-
-    private void addLocalVariablesForAllParameters(MethodNode method, Map<String, Map> nameAndTypeMapping) {
-        BlockStatement code = method.code as BlockStatement
-        nameAndTypeMapping.each { String paramName, Map localNameAndType ->
-            code.statements.add(0, AstHelper.createVariableDefinition(
-                    (String) localNameAndType['name'],
-                    (ClassNode) localNameAndType['type'],
-                    new VariableExpression(paramName, (ClassNode) localNameAndType['type'])
-            ))
-        }
-    }
-
-    private void replaceAllAccessToParams(MethodNode method, Map<String, Map> nameAndTypeMapping) {
-        new VariableAccessReplacer(nameAndTypeMapping: nameAndTypeMapping).replaceIn(method.code)
-    }
-
-    // Public b/c there are tests for this method
-    Map<String, Map> name2VariableMappingFor(MethodNode method) {
-        Map<String, Map> nameAndTypeMapping = [:]
-        method.parameters.each { Parameter param ->
-            String paramName = param.name
-            ClassNode paramType = param.type as ClassNode
-            String iterationVariableName = iterationVariableName(paramName)
-            nameAndTypeMapping[paramName] = [name: iterationVariableName, type: paramType]
-        }
-        return nameAndTypeMapping
-    }
-
-    // Public b/c there are tests for this method
-    Map<Integer, Map> position2VariableMappingFor(MethodNode method) {
-        Map<Integer, Map> positionMapping = [:]
-        method.parameters.eachWithIndex { Parameter param, int index ->
-            String paramName = param.name
-            ClassNode paramType = param.type as ClassNode
-            String iterationVariableName = this.iterationVariableName(paramName)
-            positionMapping[index] = [name: iterationVariableName, type: paramType]
-        }
-        return positionMapping
-    }
-
-    private String iterationVariableName(String paramName) {
-        '_' + paramName + '_'
-    }
-
-    private void replaceAllRecursiveReturnsWithIteration(MethodNode method, Map positionMapping) {
-        replaceRecursiveReturnsOutsideClosures(method, positionMapping)
-        replaceRecursiveReturnsInsideClosures(method, positionMapping)
-    }
-
-    private void replaceRecursiveReturnsOutsideClosures(MethodNode method, Map<Integer, Map> positionMapping) {
-        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean inClosure ->
-            if (inClosure)
-                return false
-            if (!(statement instanceof ReturnStatement)) {
-                return false
-            }
-            Expression inner = ((ReturnStatement) statement).expression
-            if (!(inner instanceof MethodCallExpression) && !(inner instanceof StaticMethodCallExpression)) {
-                return false
-            }
-            return isRecursiveIn(inner, method)
-        }
-        Closure<Statement> replaceWithContinueBlock = { ReturnStatement statement ->
-            new ReturnStatementToIterationConverter().convert(statement, positionMapping)
-        }
-        def replacer = new StatementReplacer(when: whenRecursiveReturn, replaceWith: replaceWithContinueBlock)
-        replacer.replaceIn(method.code)
-    }
-
-    private void replaceRecursiveReturnsInsideClosures(MethodNode method, Map<Integer, Map> positionMapping) {
-        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean inClosure ->
-            if (!inClosure)
-                return false
-            if (!(statement instanceof ReturnStatement)) {
-                return false
-            }
-            Expression inner = ((ReturnStatement )statement).expression
-            if (!(inner instanceof MethodCallExpression) && !(inner instanceof StaticMethodCallExpression)) {
-                return false
-            }
-            return isRecursiveIn(inner, method)
-        }
-        Closure<Statement> replaceWithThrowLoopException = { ReturnStatement statement ->
-            new ReturnStatementToIterationConverter(recurStatement: AstHelper.recurByThrowStatement()).convert(statement, positionMapping)
-        }
-        StatementReplacer replacer = new StatementReplacer(when: whenRecursiveReturn, replaceWith: replaceWithThrowLoopException)
-        replacer.replaceIn(method.code)
-    }
-
-    private void wrapMethodBodyWithWhileLoop(MethodNode method) {
-        new InWhileLoopWrapper().wrap(method)
-    }
-
-    private void addMissingDefaultReturnStatement(MethodNode method) {
-        new ReturnAdder().visitMethod(method)
-        new ReturnAdderForClosures().visitMethod(method)
-    }
-
-    private void ensureAllRecursiveCallsHaveBeenTransformed(MethodNode method) {
-        List<Expression> remainingRecursiveCalls = new CollectRecursiveCalls().collect(method)
-        for(Expression expression : remainingRecursiveCalls) {
-            addError("Recursive call could not be transformed by @TailRecursive. Maybe it's not a tail call.", expression)
-        }
-    }
-
-    private boolean hasRecursiveMethodCalls(MethodNode method) {
-        hasRecursiveCalls.test(method)
-    }
-
-    private boolean isRecursiveIn(Expression methodCall, MethodNode method) {
-        if (methodCall instanceof MethodCallExpression)
-            return new RecursivenessTester().isRecursive(method, (MethodCallExpression) methodCall)
-        if (methodCall instanceof StaticMethodCallExpression)
-            return new RecursivenessTester().isRecursive(method, (StaticMethodCallExpression) methodCall)
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/TernaryToIfStatementConverter.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/TernaryToIfStatementConverter.groovy b/src/main/groovy/TernaryToIfStatementConverter.groovy
deleted file mode 100644
index c47e1d2..0000000
--- a/src/main/groovy/TernaryToIfStatementConverter.groovy
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.expr.TernaryExpression
-import org.codehaus.groovy.ast.stmt.IfStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.ast.stmt.Statement
-
-/**
- * Since a ternary statement has more than one exit point tail-recursiveness testing cannot be easily done.
- * Therefore this class translates a ternary statement (or Elvis operator) into the equivalent if-else statement.
- *
- * @author Johannes Link
- */
-@CompileStatic
-class TernaryToIfStatementConverter {
-
-    Statement convert(ReturnStatement statementWithInnerTernaryExpression) {
-        if (!(statementWithInnerTernaryExpression.expression instanceof TernaryExpression))
-            return statementWithInnerTernaryExpression
-        TernaryExpression ternary = statementWithInnerTernaryExpression.expression as TernaryExpression
-        return new IfStatement(ternary.booleanExpression, new ReturnStatement(ternary.trueExpression), new ReturnStatement(ternary.falseExpression))
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ThreadInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ThreadInterruptibleASTTransformation.groovy b/src/main/groovy/ThreadInterruptibleASTTransformation.groovy
deleted file mode 100644
index a4fb4c3..0000000
--- a/src/main/groovy/ThreadInterruptibleASTTransformation.groovy
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  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.transform
-
-import groovy.transform.CompileStatic
-import groovy.transform.ThreadInterrupt
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
-import org.codehaus.groovy.ast.expr.ClassExpression
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.control.CompilePhase
-
-/**
- * Allows "interrupt-safe" executions of scripts by adding Thread.currentThread().isInterrupted()
- * checks on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
- * statement on the beginning of method calls.
- *
- * @see groovy.transform.ThreadInterrupt
- *
- * @author Cedric Champeau
- * @author Hamlet D'Arcy
- *
- * @since 1.8.0
- */
-@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
-@CompileStatic
-public class ThreadInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
-
-    private static final ClassNode MY_TYPE = ClassHelper.make(ThreadInterrupt)
-    private static final ClassNode THREAD_TYPE = ClassHelper.make(Thread)
-    private static final MethodNode CURRENTTHREAD_METHOD
-    private static final MethodNode ISINTERRUPTED_METHOD
-
-    static {
-        CURRENTTHREAD_METHOD = THREAD_TYPE.getMethod('currentThread', Parameter.EMPTY_ARRAY)
-        ISINTERRUPTED_METHOD = THREAD_TYPE.getMethod('isInterrupted', Parameter.EMPTY_ARRAY)
-    }
-
-    protected ClassNode type() {
-        return MY_TYPE;
-    }
-
-    protected String getErrorMessage() {
-        'Execution interrupted. The current thread has been interrupted.'
-    }
-
-    protected Expression createCondition() {
-        def currentThread = new MethodCallExpression(new ClassExpression(THREAD_TYPE),
-                'currentThread',
-                ArgumentListExpression.EMPTY_ARGUMENTS)
-        currentThread.methodTarget = CURRENTTHREAD_METHOD
-        def isInterrupted = new MethodCallExpression(
-                currentThread,
-                'isInterrupted', ArgumentListExpression.EMPTY_ARGUMENTS)
-        isInterrupted.methodTarget = ISINTERRUPTED_METHOD
-        [currentThread, isInterrupted]*.implicitThis = false
-
-        isInterrupted
-    }
-
-
-    @Override
-    public void visitClosureExpression(ClosureExpression closureExpr) {
-        def code = closureExpr.code
-        closureExpr.code = wrapBlock(code)
-        super.visitClosureExpression closureExpr
-    }
-
-    @Override
-    public void visitMethod(MethodNode node) {
-        if (checkOnMethodStart && !node.isSynthetic() && !node.isAbstract()) {
-            def code = node.code
-            node.code = wrapBlock(code);
-        }
-        super.visitMethod(node)
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/TimedInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/TimedInterruptibleASTTransformation.groovy b/src/main/groovy/TimedInterruptibleASTTransformation.groovy
deleted file mode 100644
index fbc923b..0000000
--- a/src/main/groovy/TimedInterruptibleASTTransformation.groovy
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- *  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.transform
-
-import groovy.transform.TimedInterrupt
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotatedNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassCodeVisitorSupport
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.FieldNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.PropertyNode
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.expr.DeclarationExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.DoWhileStatement
-import org.codehaus.groovy.ast.stmt.ForStatement
-import org.codehaus.groovy.ast.stmt.WhileStatement
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.SourceUnit
-
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeoutException
-
-import static org.codehaus.groovy.ast.ClassHelper.make
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ltX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.plusX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
-
-/**
- * Allows "interrupt-safe" executions of scripts by adding timer expiration
- * checks on loops (for, while, do) and first statement of closures. By default,
- * also adds an interrupt check statement on the beginning of method calls.
- *
- * @author Cedric Champeau
- * @author Hamlet D'Arcy
- * @author Paul King
- * @see groovy.transform.ThreadInterrupt
- * @since 1.8.0
- */
-@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
-public class TimedInterruptibleASTTransformation extends AbstractASTTransformation {
-
-    private static final ClassNode MY_TYPE = make(TimedInterrupt)
-    private static final String CHECK_METHOD_START_MEMBER = 'checkOnMethodStart'
-    private static final String APPLY_TO_ALL_CLASSES = 'applyToAllClasses'
-    private static final String APPLY_TO_ALL_MEMBERS = 'applyToAllMembers'
-    private static final String THROWN_EXCEPTION_TYPE = "thrown"
-
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        init(nodes, source);
-        AnnotationNode node = nodes[0]
-        AnnotatedNode annotatedNode = nodes[1]
-        if (!MY_TYPE.equals(node.getClassNode())) {
-            internalError("Transformation called from wrong annotation: $node.classNode.name")
-        }
-
-        def checkOnMethodStart = getConstantAnnotationParameter(node, CHECK_METHOD_START_MEMBER, Boolean.TYPE, true)
-        def applyToAllMembers = getConstantAnnotationParameter(node, APPLY_TO_ALL_MEMBERS, Boolean.TYPE, true)
-        def applyToAllClasses = applyToAllMembers ? getConstantAnnotationParameter(node, APPLY_TO_ALL_CLASSES, Boolean.TYPE, true) : false
-        def maximum = getConstantAnnotationParameter(node, 'value', Long.TYPE, Long.MAX_VALUE)
-        def thrown = AbstractInterruptibleASTTransformation.getClassAnnotationParameter(node, THROWN_EXCEPTION_TYPE, make(TimeoutException))
-
-        Expression unit = node.getMember('unit') ?: propX(classX(TimeUnit), "SECONDS")
-
-        // should be limited to the current SourceUnit or propagated to the whole CompilationUnit
-        // DO NOT inline visitor creation in code below. It has state that must not persist between calls
-        if (applyToAllClasses) {
-            // guard every class and method defined in this script
-            source.getAST()?.classes?.each { ClassNode it ->
-                def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-                visitor.visitClass(it)
-            }
-        } else if (annotatedNode instanceof ClassNode) {
-            // only guard this particular class
-            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-            visitor.visitClass annotatedNode
-        } else if (!applyToAllMembers && annotatedNode instanceof MethodNode) {
-            // only guard this particular method (plus initCode for class)
-            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-            visitor.visitMethod annotatedNode
-            visitor.visitClass annotatedNode.declaringClass
-        } else if (!applyToAllMembers && annotatedNode instanceof FieldNode) {
-            // only guard this particular field (plus initCode for class)
-            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-            visitor.visitField annotatedNode
-            visitor.visitClass annotatedNode.declaringClass
-        } else if (!applyToAllMembers && annotatedNode instanceof DeclarationExpression) {
-            // only guard this particular declaration (plus initCode for class)
-            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-            visitor.visitDeclarationExpression annotatedNode
-            visitor.visitClass annotatedNode.declaringClass
-        } else {
-            // only guard the script class
-            source.getAST()?.classes?.each { ClassNode it ->
-                if (it.isScript()) {
-                    def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
-                    visitor.visitClass(it)
-                }
-            }
-        }
-    }
-
-    static def getConstantAnnotationParameter(AnnotationNode node, String parameterName, Class type, defaultValue) {
-        def member = node.getMember(parameterName)
-        if (member) {
-            if (member instanceof ConstantExpression) {
-                // TODO not sure this try offers value - testing Groovy annotation type handing - throw GroovyBugError or remove?
-                try {
-                    return member.value.asType(type)
-                } catch (ignore) {
-                    internalError("Expecting boolean value for ${parameterName} annotation parameter. Found $member")
-                }
-            } else {
-                internalError("Expecting boolean value for ${parameterName} annotation parameter. Found $member")
-            }
-        }
-        return defaultValue
-    }
-
-    private static void internalError(String message) {
-        throw new RuntimeException("Internal error: $message")
-    }
-
-    private static class TimedInterruptionVisitor extends ClassCodeVisitorSupport {
-        final private SourceUnit source
-        final private boolean checkOnMethodStart
-        final private boolean applyToAllClasses
-        final private boolean applyToAllMembers
-        private FieldNode expireTimeField = null
-        private FieldNode startTimeField = null
-        private final Expression unit
-        private final maximum
-        private final ClassNode thrown
-        private final String basename
-
-        TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, hash) {
-            this.source = source
-            this.checkOnMethodStart = checkOnMethodStart
-            this.applyToAllClasses = applyToAllClasses
-            this.applyToAllMembers = applyToAllMembers
-            this.unit = unit
-            this.maximum = maximum
-            this.thrown = thrown
-            this.basename = 'timedInterrupt' + hash
-        }
-
-        /**
-         * @return Returns the interruption check statement.
-         */
-        final createInterruptStatement() {
-            ifS(
-
-                    ltX(
-                            propX(varX("this"), basename + '$expireTime'),
-                            callX(make(System), 'nanoTime')
-                    ),
-                    throwS(
-                            ctorX(thrown,
-                                    args(
-                                            plusX(
-                                                    plusX(
-                                                            constX('Execution timed out after ' + maximum + ' '),
-                                                            callX(callX(unit, 'name'), 'toLowerCase', propX(classX(Locale), 'US'))
-                                                    ),
-                                                    plusX(
-                                                            constX('. Start time: '),
-                                                            propX(varX("this"), basename + '$startTime')
-                                                    )
-                                            )
-
-                                    )
-                            )
-                    )
-            )
-        }
-
-        /**
-         * Takes a statement and wraps it into a block statement which first element is the interruption check statement.
-         * @param statement the statement to be wrapped
-         * @return a {@link BlockStatement block statement}    which first element is for checking interruption, and the
-         * second one the statement to be wrapped.
-         */
-        private wrapBlock(statement) {
-            def stmt = new BlockStatement();
-            stmt.addStatement(createInterruptStatement());
-            stmt.addStatement(statement);
-            stmt
-        }
-
-        @Override
-        void visitClass(ClassNode node) {
-            if (node.getDeclaredField(basename + '$expireTime')) {
-                return
-            }
-            expireTimeField = node.addField(basename + '$expireTime',
-                    ACC_FINAL | ACC_PRIVATE,
-                    ClassHelper.long_TYPE,
-                    plusX(
-                            callX(make(System), 'nanoTime'),
-                            callX(
-                                    propX(classX(TimeUnit), 'NANOSECONDS'),
-                                    'convert',
-                                    args(constX(maximum, true), unit)
-                            )
-                    )
-            );
-            expireTimeField.synthetic = true
-            startTimeField = node.addField(basename + '$startTime',
-                    ACC_FINAL | ACC_PRIVATE,
-                    make(Date),
-                    ctorX(make(Date))
-            )
-            startTimeField.synthetic = true
-
-            // force these fields to be initialized first
-            node.fields.remove(expireTimeField)
-            node.fields.remove(startTimeField)
-            node.fields.add(0, startTimeField)
-            node.fields.add(0, expireTimeField)
-            if (applyToAllMembers) {
-                super.visitClass node
-            }
-        }
-
-        @Override
-        void visitClosureExpression(ClosureExpression closureExpr) {
-            def code = closureExpr.code
-            if (code instanceof BlockStatement) {
-                code.statements.add(0, createInterruptStatement())
-            } else {
-                closureExpr.code = wrapBlock(code)
-            }
-            super.visitClosureExpression closureExpr
-        }
-
-        @Override
-        void visitField(FieldNode node) {
-            if (!node.isStatic() && !node.isSynthetic()) {
-                super.visitField node
-            }
-        }
-
-        @Override
-        void visitProperty(PropertyNode node) {
-            if (!node.isStatic() && !node.isSynthetic()) {
-                super.visitProperty node
-            }
-        }
-
-        /**
-         * Shortcut method which avoids duplicating code for every type of loop.
-         * Actually wraps the loopBlock of different types of loop statements.
-         */
-        private visitLoop(loopStatement) {
-            def statement = loopStatement.loopBlock
-            loopStatement.loopBlock = wrapBlock(statement)
-        }
-
-        @Override
-        void visitForLoop(ForStatement forStatement) {
-            visitLoop(forStatement)
-            super.visitForLoop(forStatement)
-        }
-
-        @Override
-        void visitDoWhileLoop(final DoWhileStatement doWhileStatement) {
-            visitLoop(doWhileStatement)
-            super.visitDoWhileLoop(doWhileStatement)
-        }
-
-        @Override
-        void visitWhileLoop(final WhileStatement whileStatement) {
-            visitLoop(whileStatement)
-            super.visitWhileLoop(whileStatement)
-        }
-
-        @Override
-        void visitMethod(MethodNode node) {
-            if (checkOnMethodStart && !node.isSynthetic() && !node.isStatic() && !node.isAbstract()) {
-                def code = node.code
-                node.code = wrapBlock(code);
-            }
-            if (!node.isSynthetic() && !node.isStatic()) {
-                super.visitMethod(node)
-            }
-        }
-
-        protected SourceUnit getSourceUnit() {
-            return source;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/TransformTestHelper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/TransformTestHelper.groovy b/src/main/groovy/TransformTestHelper.groovy
deleted file mode 100644
index d9921d5..0000000
--- a/src/main/groovy/TransformTestHelper.groovy
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- *  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.tools.ast
-
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.classgen.GeneratorContext
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.CompilerConfiguration
-import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.transform.ASTTransformation
-
-import java.security.CodeSource
-
-/*
-* This TestHarness exists so that a global transform can be run without
-* using the Jar services mechanism, which requires building a jar.
-* 
-* To use this simply create an instance of TransformTestHelper with
-* an ASTTransformation and CompilePhase, then invoke parse(File) or
-* parse(String). 
-* 
-* This test harness is not exactly the same as executing a global transformation
-* but can greatly aide in debugging and testing a transform. You should still
-* test your global transformation when packaged as a jar service before
-* releasing it. 
-* 
-* @author Hamlet D'Arcy
-*/
-class TransformTestHelper {
-
-    private final ASTTransformation transform
-    private final CompilePhase phase
-
-    /**
-     * Creates the test helper.
-     * @param transform
-     *      the transform to run when compiling the file later
-     * @param phase
-     *      the phase to run the transform in 
-     */
-    def TransformTestHelper(ASTTransformation transform, CompilePhase phase) {
-        this.transform = transform
-        this.phase = phase
-    }
-
-    /**
-     * Compiles the File into a Class applying the transform specified in the constructor.
-     * @input input
-     *      must be a groovy source file
-     */
-    public Class parse(File input) {
-        TestHarnessClassLoader loader = new TestHarnessClassLoader(transform, phase)
-        return loader.parseClass(input)
-    }
-
-    /**
-     * Compiles the String into a Class applying the transform specified in the constructor.
-     * @input input
-     *      must be a valid groovy source string
-     */
-    public Class parse(String input) {
-        TestHarnessClassLoader loader = new TestHarnessClassLoader(transform, phase)
-        return loader.parseClass(input)
-    }
-}
-
-/**
-* ClassLoader exists so that TestHarnessOperation can be wired into the compile. 
-*
-* @author Hamlet D'Arcy
-*/
-@groovy.transform.PackageScope class TestHarnessClassLoader extends GroovyClassLoader {
-
-    private final ASTTransformation transform
-    private final CompilePhase phase
-
-    TestHarnessClassLoader(ASTTransformation transform, CompilePhase phase) {
-        this.transform = transform
-        this.phase = phase
-    }
-
-    protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource codeSource) {
-        CompilationUnit cu = super.createCompilationUnit(config, codeSource)
-        cu.addPhaseOperation(new TestHarnessOperation(transform), phase.getPhaseNumber())
-        return cu
-    }
-}
-
-/**
-* Operation exists so that an AstTransformation can be run against the SourceUnit.
-*
-* @author Hamlet D'Arcy
-*/
-@groovy.transform.PackageScope class TestHarnessOperation extends PrimaryClassNodeOperation {
-
-    private final ASTTransformation transform
-
-    def TestHarnessOperation(transform) {
-        this.transform = transform;
-    }
-
-    public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
-        transform.visit(null, source)
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/VariableAccessReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/VariableAccessReplacer.groovy b/src/main/groovy/VariableAccessReplacer.groovy
deleted file mode 100644
index d62dc46..0000000
--- a/src/main/groovy/VariableAccessReplacer.groovy
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.expr.VariableExpression
-
-/**
- * Replace all access to variables and args by new variables.
- * The variable names to replace as well as their replacement name and type have to be configured
- * in nameAndTypeMapping before calling replaceIn().
- *
- * The VariableReplacedListener can be set if clients want to react to variable replacement.
- *
- * @author Johannes Link
- */
-@CompileStatic
-class VariableAccessReplacer {
-
-    /**
-     * Nested map of variable accesses to replace
-     * e.g.: [
-     *          'varToReplace': [name: 'newVar', type: TypeOfVar],
-     *          'varToReplace2': [name: 'newVar2', type: TypeOfVar2],
-     *       ]
-     */
-    Map<String, Map> nameAndTypeMapping = [:]
-
-    VariableReplacedListener listener = VariableReplacedListener.NULL
-
-    void replaceIn(ASTNode root) {
-        Closure<Boolean> whenParam = { VariableExpression expr ->
-            return nameAndTypeMapping.containsKey(expr.name)
-        }
-        Closure<VariableExpression> replaceWithLocalVariable = { VariableExpression expr ->
-            Map nameAndType = nameAndTypeMapping[expr.name]
-            VariableExpression newVar = AstHelper.createVariableReference(nameAndType)
-            listener.variableReplaced(expr, newVar)
-            return newVar
-        }
-        new VariableExpressionReplacer(when: whenParam, replaceWith: replaceWithLocalVariable).replaceIn(root)
-    }
-
-}
-
-@CompileStatic
-interface VariableReplacedListener {
-    void variableReplaced(VariableExpression oldVar, VariableExpression newVar)
-
-    static VariableReplacedListener NULL = new VariableReplacedListener() {
-        @Override
-        void variableReplaced(VariableExpression oldVar, VariableExpression newVar) {
-            //do nothing
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/VariableExpressionReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/VariableExpressionReplacer.groovy b/src/main/groovy/VariableExpressionReplacer.groovy
deleted file mode 100644
index 1f14490..0000000
--- a/src/main/groovy/VariableExpressionReplacer.groovy
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.CodeVisitorSupport
-import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.ExpressionTransformer
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.AssertStatement
-import org.codehaus.groovy.ast.stmt.CaseStatement
-import org.codehaus.groovy.ast.stmt.DoWhileStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
-import org.codehaus.groovy.ast.stmt.ForStatement
-import org.codehaus.groovy.ast.stmt.IfStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.ast.stmt.SwitchStatement
-import org.codehaus.groovy.ast.stmt.SynchronizedStatement
-import org.codehaus.groovy.ast.stmt.ThrowStatement
-import org.codehaus.groovy.ast.stmt.WhileStatement
-
-import java.lang.reflect.Method
-
-/**
- * Tool for replacing VariableExpression instances in an AST by other VariableExpression instances.
- * Regardless of a real change taking place in nested expressions, all considered expression (trees) will be replaced.
- * This could be optimized to accelerate compilation.
- *
- * Within @TailRecursive it is used
- * - to swap the access of method args with the access to iteration variables
- * - to swap the access of iteration variables with the access of temp vars
- *
- * @author Johannes Link
- */
-@CompileStatic
-class VariableExpressionReplacer extends CodeVisitorSupport {
-
-    Closure<Boolean> when = { VariableExpression node -> false }
-    Closure<VariableExpression> replaceWith = { VariableExpression variableExpression -> variableExpression }
-
-    private ExpressionTransformer transformer
-
-    synchronized void replaceIn(ASTNode root) {
-        transformer = new VariableExpressionTransformer(when: when, replaceWith: replaceWith)
-        root.visit(this)
-    }
-
-    public void visitReturnStatement(ReturnStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitReturnStatement(statement);
-    }
-
-    public void visitIfElse(IfStatement ifElse) {
-        replaceExpressionPropertyWhenNecessary(ifElse, 'booleanExpression', BooleanExpression)
-        super.visitIfElse(ifElse);
-    }
-
-    public void visitForLoop(ForStatement forLoop) {
-        replaceExpressionPropertyWhenNecessary(forLoop, 'collectionExpression')
-        super.visitForLoop(forLoop);
-    }
-
-    /**
-     * It's the only Expression type in which replacing is considered.
-     * That's an abuse of the class, but I couldn't think of a better way.
-     */
-    public void visitBinaryExpression(BinaryExpression expression) {
-        //A hack: Only replace right expression b/c ReturnStatementToIterationConverter needs it that way :-/
-        replaceExpressionPropertyWhenNecessary(expression, 'rightExpression')
-        expression.getRightExpression().visit(this);
-        super.visitBinaryExpression(expression)
-    }
-
-    public void visitWhileLoop(WhileStatement loop) {
-        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', BooleanExpression)
-        super.visitWhileLoop(loop);
-    }
-
-    public void visitDoWhileLoop(DoWhileStatement loop) {
-        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', BooleanExpression)
-        super.visitDoWhileLoop(loop);
-    }
-
-    public void visitSwitch(SwitchStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitSwitch(statement)
-    }
-
-    public void visitCaseStatement(CaseStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitCaseStatement(statement)
-    }
-
-    public void visitExpressionStatement(ExpressionStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitExpressionStatement(statement);
-    }
-
-    public void visitThrowStatement(ThrowStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitThrowStatement(statement)
-    }
-
-    public void visitAssertStatement(AssertStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement, 'booleanExpression', BooleanExpression)
-        replaceExpressionPropertyWhenNecessary(statement, 'messageExpression')
-        super.visitAssertStatement(statement)
-    }
-
-    public void visitSynchronizedStatement(SynchronizedStatement statement) {
-        replaceExpressionPropertyWhenNecessary(statement)
-        super.visitSynchronizedStatement(statement)
-    }
-
-    private void replaceExpressionPropertyWhenNecessary(ASTNode node, String propName = "expression", Class propClass = Expression) {
-        Expression expr = getExpression(node, propName)
-
-        if (expr instanceof VariableExpression) {
-            if (when(expr)) {
-                VariableExpression newExpr = replaceWith(expr)
-                replaceExpression(node, propName, propClass, expr, newExpr)
-            }
-        } else {
-            Expression newExpr = expr.transformExpression(transformer)
-            replaceExpression(node, propName, propClass, expr, newExpr)
-        }
-    }
-
-    private void replaceExpression(ASTNode node, String propName, Class propClass, Expression oldExpr, Expression newExpr) {
-        //Use reflection to enable CompileStatic
-        String setterName = 'set' + capitalizeFirst(propName)
-        Method setExpressionMethod = node.class.getMethod(setterName, [propClass].toArray(new Class[1]))
-        newExpr.setSourcePosition(oldExpr);
-        newExpr.copyNodeMetaData(oldExpr);
-        setExpressionMethod.invoke(node, [newExpr].toArray())
-    }
-
-    private Expression getExpression(ASTNode node, String propName) {
-        //Use reflection to enable CompileStatic
-        String getterName = 'get' + capitalizeFirst(propName)
-        Method getExpressionMethod = node.class.getMethod(getterName, new Class[0])
-        getExpressionMethod.invoke(node, new Object[0]) as Expression
-    }
-
-    private String capitalizeFirst(String propName) {
-        propName[0].toUpperCase() + propName[1..-1]
-    }
-
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/VariableExpressionTransformer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/VariableExpressionTransformer.groovy b/src/main/groovy/VariableExpressionTransformer.groovy
deleted file mode 100644
index 106a2f1..0000000
--- a/src/main/groovy/VariableExpressionTransformer.groovy
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.ExpressionTransformer
-import org.codehaus.groovy.ast.expr.VariableExpression
-
-/**
- * An expression transformer used in the process of replacing the access to variables
- *
- * @author Johannes Link
- */
-@CompileStatic
-class VariableExpressionTransformer implements ExpressionTransformer {
-
-    Closure<Boolean> when
-    Closure<VariableExpression> replaceWith
-
-    @Override
-    Expression transform(Expression expr) {
-        if ((expr instanceof VariableExpression) && when(expr)) {
-            VariableExpression newExpr = replaceWith(expr)
-            newExpr.setSourcePosition(expr);
-            newExpr.copyNodeMetaData(expr);
-            return newExpr
-        }
-        return expr.transformExpression(this)
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/Bindable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/Bindable.java b/src/main/groovy/beans/Bindable.java
deleted file mode 100644
index cf0a5c9..0000000
--- a/src/main/groovy/beans/Bindable.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotates a groovy property or a class.
- *
- * When annotating a property it indicates that the property should be a
- * bound property according to the JavaBeans spec, announcing to listeners
- * that the value has changed.
- * <p>
- * When annotating a class it indicates that all groovy properties in that
- * class should be bound as though each property had the annotation (even
- * if it already has it explicitly).
- * <p>
- * It is a compilation error to place this annotation on a field (that is
- * not a property, i.e. has scope visibility modifiers).
- * <p>
- * If a property with a user defined setter method is annotated the code
- * block is wrapped with the needed code to fire off the event.
- * <p>
- * The following example shows how you can use this annotation on fields
- * of a class: 
- * <pre>
- * class Person {
- *    &#064;groovy.beans.Bindable
- *    String firstName
- *
- *    &#064;groovy.beans.Bindable
- *    def zipCode
- * }
- * </pre>
- * The above example will generate code that is similar to the next snippet. 
- * Notice the difference between a String property and a def/Object property: 
- * <pre>
- * public class Person { 
- *     &#064;groovy.beans.Bindable
- *     private java.lang.String firstName 
- *     &#064;groovy.beans.Bindable
- *     private java.lang.Object zipCode 
- *     final private java.beans.PropertyChangeSupport this$propertyChangeSupport 
- * 
- *     public Person() {
- *         this$propertyChangeSupport = new java.beans.PropertyChangeSupport(this)
- *     }
- * 
- *     public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {
- *         this$propertyChangeSupport.addPropertyChangeListener(listener)
- *     }
- * 
- *     public void addPropertyChangeListener(java.lang.String name, java.beans.PropertyChangeListener listener) {
- *         this$propertyChangeSupport.addPropertyChangeListener(name, listener)
- *     }
- * 
- *     public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {
- *         this$propertyChangeSupport.removePropertyChangeListener(listener)
- *     }
- * 
- *     public void removePropertyChangeListener(java.lang.String name, java.beans.PropertyChangeListener listener) {
- *         this$propertyChangeSupport.removePropertyChangeListener(name, listener)
- *     }
- * 
- *     public void firePropertyChange(java.lang.String name, java.lang.Object oldValue, java.lang.Object newValue) {
- *         this$propertyChangeSupport.firePropertyChange(name, oldValue, newValue)
- *     }
- * 
- *     public java.beans.PropertyChangeListener[] getPropertyChangeListeners() {
- *         return this$propertyChangeSupport.getPropertyChangeListeners()
- *     }
- * 
- *     public java.beans.PropertyChangeListener[] getPropertyChangeListeners(java.lang.String name) {
- *         return this$propertyChangeSupport.getPropertyChangeListeners(name)
- *     }
- * 
- *     public void setFirstName(java.lang.String value) {
- *         this.firePropertyChange('firstName', firstName, firstName = value )
- *     }
- * 
- *     public void setZipCode(java.lang.Object value) {
- *         this.firePropertyChange('zipCode', zipCode, zipCode = value )
- *     }
- * }
- * </pre>
- *
- * @see BindableASTTransformation
- * @author Danno Ferrin (shemnon)
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.FIELD, ElementType.TYPE})
-@GroovyASTTransformationClass("groovy.beans.BindableASTTransformation")
-public @interface Bindable {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/BindableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/BindableASTTransformation.java b/src/main/groovy/beans/BindableASTTransformation.java
deleted file mode 100644
index f987295..0000000
--- a/src/main/groovy/beans/BindableASTTransformation.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.PropertyNode;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.tools.PropertyNodeUtils;
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.messages.SimpleMessage;
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.syntax.SyntaxException;
-import org.codehaus.groovy.transform.ASTTransformation;
-import org.codehaus.groovy.transform.GroovyASTTransformation;
-import org.objectweb.asm.Opcodes;
-
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-
-/**
- * Handles generation of code for the {@code @Bindable} annotation when {@code @Vetoable}
- * is not present.
- * <p>
- * Generally, it adds (if needed) a PropertyChangeSupport field and
- * the needed add/removePropertyChangeListener methods to support the
- * listeners.
- * <p>
- * It also generates the setter and wires the setter through the
- * PropertyChangeSupport.
- * <p>
- * If a {@link Vetoable} annotation is detected it does nothing and
- * lets the {@link VetoableASTTransformation} handle all the changes.
- *
- * @author Danno Ferrin (shemnon)
- * @author Chris Reeves
- */
-@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION)
-public class BindableASTTransformation implements ASTTransformation, Opcodes {
-
-    protected static ClassNode boundClassNode = ClassHelper.make(Bindable.class);
-
-    /**
-     * Convenience method to see if an annotated node is {@code @Bindable}.
-     *
-     * @param node the node to check
-     * @return true if the node is bindable
-     */
-    public static boolean hasBindableAnnotation(AnnotatedNode node) {
-        for (AnnotationNode annotation : node.getAnnotations()) {
-            if (boundClassNode.equals(annotation.getClassNode())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Handles the bulk of the processing, mostly delegating to other methods.
-     *
-     * @param nodes   the ast nodes
-     * @param source  the source unit for the nodes
-     */
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
-            throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
-        }
-        AnnotationNode node = (AnnotationNode) nodes[0];
-        AnnotatedNode parent = (AnnotatedNode) nodes[1];
-
-        if (VetoableASTTransformation.hasVetoableAnnotation(parent)) {
-            // VetoableASTTransformation will handle both @Bindable and @Vetoable
-            return;
-        }
-
-        ClassNode declaringClass = parent.getDeclaringClass();
-        if (parent instanceof FieldNode) {
-            if ((((FieldNode) parent).getModifiers() & Opcodes.ACC_FINAL) != 0) {
-                source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                        new SyntaxException("@groovy.beans.Bindable cannot annotate a final property.",
-                                node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                        source));
-            }
-
-            if (VetoableASTTransformation.hasVetoableAnnotation(parent.getDeclaringClass())) {
-                // VetoableASTTransformation will handle both @Bindable and @Vetoable
-                return;
-            }
-            addListenerToProperty(source, node, declaringClass, (FieldNode) parent);
-        } else if (parent instanceof ClassNode) {
-            addListenerToClass(source, (ClassNode) parent);
-        }
-    }
-
-    private void addListenerToProperty(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field) {
-        String fieldName = field.getName();
-        for (PropertyNode propertyNode : declaringClass.getProperties()) {
-            if (propertyNode.getName().equals(fieldName)) {
-                if (field.isStatic()) {
-                    //noinspection ThrowableInstanceNeverThrown
-                    source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                            new SyntaxException("@groovy.beans.Bindable cannot annotate a static property.",
-                                    node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                            source));
-                } else {
-                    if (needsPropertyChangeSupport(declaringClass, source)) {
-                        addPropertyChangeSupport(declaringClass);
-                    }
-                    createListenerSetter(declaringClass, propertyNode);
-                }
-                return;
-            }
-        }
-        //noinspection ThrowableInstanceNeverThrown
-        source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
-                new SyntaxException("@groovy.beans.Bindable must be on a property, not a field.  Try removing the private, protected, or public modifier.",
-                        node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
-                source));
-    }
-
-    private void addListenerToClass(SourceUnit source, ClassNode classNode) {
-        if (needsPropertyChangeSupport(classNode, source)) {
-            addPropertyChangeSupport(classNode);
-        }
-        for (PropertyNode propertyNode : classNode.getProperties()) {
-            FieldNode field = propertyNode.getField();
-            // look to see if per-field handlers will catch this one...
-            if (hasBindableAnnotation(field)
-                || ((field.getModifiers() & Opcodes.ACC_FINAL) != 0)
-                || field.isStatic()
-                || VetoableASTTransformation.hasVetoableAnnotation(field))
-            {
-                // explicitly labeled properties are already handled,
-                // don't transform final properties
-                // don't transform static properties
-                // VetoableASTTransformation will handle both @Bindable and @Vetoable
-                continue;
-            }
-            createListenerSetter(classNode, propertyNode);
-        }
-    }
-
-    /*
-     * Wrap an existing setter.
-     */
-    private static void wrapSetterMethod(ClassNode classNode, String propertyName) {
-        String getterName = "get" + MetaClassHelper.capitalize(propertyName);
-        MethodNode setter = classNode.getSetterMethod("set" + MetaClassHelper.capitalize(propertyName));
-
-        if (setter != null) {
-            // Get the existing code block
-            Statement code = setter.getCode();
-
-            Expression oldValue = varX("$oldValue");
-            Expression newValue = varX("$newValue");
-            BlockStatement block = new BlockStatement();
-
-            // create a local variable to hold the old value from the getter
-            block.addStatement(declS(oldValue, callThisX(getterName)));
-
-            // call the existing block, which will presumably set the value properly
-            block.addStatement(code);
-
-            // get the new value to emit in the event
-            block.addStatement(declS(newValue, callThisX(getterName)));
-
-            // add the firePropertyChange method call
-            block.addStatement(stmt(callThisX("firePropertyChange", args(constX(propertyName), oldValue, newValue))));
-
-            // replace the existing code block with our new one
-            setter.setCode(block);
-        }
-    }
-
-    private void createListenerSetter(ClassNode classNode, PropertyNode propertyNode) {
-        String setterName = "set" + MetaClassHelper.capitalize(propertyNode.getName());
-        if (classNode.getMethods(setterName).isEmpty()) {
-            Statement setterBlock = createBindableStatement(propertyNode, fieldX(propertyNode.getField()));
-
-            // create method void <setter>(<type> fieldName)
-            createSetterMethod(classNode, propertyNode, setterName, setterBlock);
-        } else {
-            wrapSetterMethod(classNode, propertyNode.getName());
-        }
-    }
-
-    /**
-     * Creates a statement body similar to:
-     * <code>this.firePropertyChange("field", field, field = value)</code>
-     *
-     * @param propertyNode           the field node for the property
-     * @param fieldExpression a field expression for setting the property value
-     * @return the created statement
-     */
-    protected Statement createBindableStatement(PropertyNode propertyNode, Expression fieldExpression) {
-        // create statementBody
-        return stmt(callThisX("firePropertyChange", args(constX(propertyNode.getName()), fieldExpression, assignX(fieldExpression, varX("value")))));
-    }
-
-    /**
-     * Creates a setter method with the given body.
-     *
-     * @param declaringClass the class to which we will add the setter
-     * @param propertyNode          the field to back the setter
-     * @param setterName     the name of the setter
-     * @param setterBlock    the statement representing the setter block
-     */
-    protected void createSetterMethod(ClassNode declaringClass, PropertyNode propertyNode, String setterName, Statement setterBlock) {
-        MethodNode setter = new MethodNode(
-                setterName,
-                PropertyNodeUtils.adjustPropertyModifiersForMethod(propertyNode),
-                ClassHelper.VOID_TYPE,
-                params(param(propertyNode.getType(), "value")),
-                ClassNode.EMPTY_ARRAY,
-                setterBlock);
-        setter.setSynthetic(true);
-        // add it to the class
-        declaringClass.addMethod(setter);
-    }
-
-    /**
-     * Snoops through the declaring class and all parents looking for methods
-     * <code>void addPropertyChangeListener(PropertyChangeListener)</code>,
-     * <code>void removePropertyChangeListener(PropertyChangeListener)</code>, and
-     * <code>void firePropertyChange(String, Object, Object)</code>. If any are defined all
-     * must be defined or a compilation error results.
-     *
-     * @param declaringClass the class to search
-     * @param sourceUnit the source unit, for error reporting. {@code @NotNull}.
-     * @return true if property change support should be added
-     */
-    protected boolean needsPropertyChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) {
-        boolean foundAdd = false, foundRemove = false, foundFire = false;
-        ClassNode consideredClass = declaringClass;
-        while (consideredClass!= null) {
-            for (MethodNode method : consideredClass.getMethods()) {
-                // just check length, MOP will match it up
-                foundAdd = foundAdd || method.getName().equals("addPropertyChangeListener") && method.getParameters().length == 1;
-                foundRemove = foundRemove || method.getName().equals("removePropertyChangeListener") && method.getParameters().length == 1;
-                foundFire = foundFire || method.getName().equals("firePropertyChange") && method.getParameters().length == 3;
-                if (foundAdd && foundRemove && foundFire) {
-                    return false;
-                }
-            }
-            consideredClass = consideredClass.getSuperClass();
-        }
-        // check if a super class has @Bindable annotations
-        consideredClass = declaringClass.getSuperClass();
-        while (consideredClass!=null) {
-            if (hasBindableAnnotation(consideredClass)) return false;
-            for (FieldNode field : consideredClass.getFields()) {
-                if (hasBindableAnnotation(field)) return false;
-            }
-            consideredClass = consideredClass.getSuperClass();
-        }
-        if (foundAdd || foundRemove || foundFire) {
-            sourceUnit.getErrorCollector().addErrorAndContinue(
-                new SimpleMessage("@Bindable cannot be processed on "
-                    + declaringClass.getName()
-                    + " because some but not all of addPropertyChangeListener, removePropertyChange, and firePropertyChange were declared in the current or super classes.",
-                sourceUnit)
-            );
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Adds the necessary field and methods to support property change support.
-     * <p>
-     * Adds a new field:
-     * <pre>
-     * <code>protected final java.beans.PropertyChangeSupport this$PropertyChangeSupport = new java.beans.PropertyChangeSupport(this)</code>"
-     * </pre>
-     * <p>
-     * Also adds support methods:
-     * <pre>
-     * <code>public void addPropertyChangeListener(java.beans.PropertyChangeListener)</code>
-     * <code>public void addPropertyChangeListener(String, java.beans.PropertyChangeListener)</code>
-     * <code>public void removePropertyChangeListener(java.beans.PropertyChangeListener)</code>
-     * <code>public void removePropertyChangeListener(String, java.beans.PropertyChangeListener)</code>
-     * <code>public java.beans.PropertyChangeListener[] getPropertyChangeListeners()</code>
-     * </pre>
-     *
-     * @param declaringClass the class to which we add the support field and methods
-     */
-    protected void addPropertyChangeSupport(ClassNode declaringClass) {
-        ClassNode pcsClassNode = ClassHelper.make(PropertyChangeSupport.class);
-        ClassNode pclClassNode = ClassHelper.make(PropertyChangeListener.class);
-        //String pcsFieldName = "this$propertyChangeSupport";
-
-        // add field:
-        // protected final PropertyChangeSupport this$propertyChangeSupport = new java.beans.PropertyChangeSupport(this)
-        FieldNode pcsField = declaringClass.addField(
-                "this$propertyChangeSupport",
-                ACC_FINAL | ACC_PRIVATE | ACC_SYNTHETIC,
-                pcsClassNode,
-                ctorX(pcsClassNode, args(varX("this"))));
-
-        // add method:
-        // void addPropertyChangeListener(listener) {
-        //     this$propertyChangeSupport.addPropertyChangeListener(listener)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "addPropertyChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(pclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(pcsField), "addPropertyChangeListener", args(varX("listener", pclClassNode))))));
-
-        // add method:
-        // void addPropertyChangeListener(name, listener) {
-        //     this$propertyChangeSupport.addPropertyChangeListener(name, listener)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "addPropertyChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(pclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(pcsField), "addPropertyChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", pclClassNode))))));
-
-        // add method:
-        // boolean removePropertyChangeListener(listener) {
-        //    return this$propertyChangeSupport.removePropertyChangeListener(listener);
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "removePropertyChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(pclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(pcsField), "removePropertyChangeListener", args(varX("listener", pclClassNode))))));
-
-        // add method: void removePropertyChangeListener(name, listener)
-        declaringClass.addMethod(
-                new MethodNode(
-                        "removePropertyChangeListener",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(pclClassNode, "listener")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(pcsField), "removePropertyChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", pclClassNode))))));
-
-        // add method:
-        // void firePropertyChange(String name, Object oldValue, Object newValue) {
-        //     this$propertyChangeSupport.firePropertyChange(name, oldValue, newValue)
-        //  }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "firePropertyChange",
-                        ACC_PUBLIC,
-                        ClassHelper.VOID_TYPE,
-                        params(param(ClassHelper.STRING_TYPE, "name"), param(ClassHelper.OBJECT_TYPE, "oldValue"), param(ClassHelper.OBJECT_TYPE, "newValue")),
-                        ClassNode.EMPTY_ARRAY,
-                        stmt(callX(fieldX(pcsField), "firePropertyChange", args(varX("name", ClassHelper.STRING_TYPE), varX("oldValue"), varX("newValue"))))));
-
-        // add method:
-        // PropertyChangeListener[] getPropertyChangeListeners() {
-        //   return this$propertyChangeSupport.getPropertyChangeListeners
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "getPropertyChangeListeners",
-                        ACC_PUBLIC,
-                        pclClassNode.makeArray(),
-                        Parameter.EMPTY_ARRAY,
-                        ClassNode.EMPTY_ARRAY,
-                        returnS(callX(fieldX(pcsField), "getPropertyChangeListeners"))));
-
-        // add method:
-        // PropertyChangeListener[] getPropertyChangeListeners(String name) {
-        //   return this$propertyChangeSupport.getPropertyChangeListeners(name)
-        // }
-        declaringClass.addMethod(
-                new MethodNode(
-                        "getPropertyChangeListeners",
-                        ACC_PUBLIC,
-                        pclClassNode.makeArray(),
-                        params(param(ClassHelper.STRING_TYPE, "name")),
-                        ClassNode.EMPTY_ARRAY,
-                        returnS(callX(fieldX(pcsField), "getPropertyChangeListeners", args(varX("name", ClassHelper.STRING_TYPE))))));
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/DefaultPropertyAccessor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/DefaultPropertyAccessor.java b/src/main/groovy/beans/DefaultPropertyAccessor.java
deleted file mode 100644
index 47dae41..0000000
--- a/src/main/groovy/beans/DefaultPropertyAccessor.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  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 groovy.beans;
-
-/**
- * @author Andres Almiray
- */
-public class DefaultPropertyAccessor implements PropertyAccessor {
-    public static final PropertyAccessor INSTANCE = new DefaultPropertyAccessor();
-
-    public Object read(Object owner, String propertyName) {
-        return DefaultPropertyReader.INSTANCE.read(owner, propertyName);
-    }
-
-    public void write(Object owner, String propertyName, Object value) {
-        DefaultPropertyWriter.INSTANCE.write(owner, propertyName, value);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/beans/DefaultPropertyReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/beans/DefaultPropertyReader.java b/src/main/groovy/beans/DefaultPropertyReader.java
deleted file mode 100644
index a03b9a3..0000000
--- a/src/main/groovy/beans/DefaultPropertyReader.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 groovy.beans;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * @author Andres Almiray
- */
-public class DefaultPropertyReader implements PropertyReader {
-    public static final PropertyReader INSTANCE = new DefaultPropertyReader();
-
-    public Object read(Object owner, String propertyName) {
-        return InvokerHelper.getPropertySafe(owner, propertyName);
-    }
-}


[27/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/ui/GroovySocketServer.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/ui/GroovySocketServer.java b/src/main/groovy/groovy/ui/GroovySocketServer.java
new file mode 100644
index 0000000..b0d27c5
--- /dev/null
+++ b/src/main/groovy/groovy/ui/GroovySocketServer.java
@@ -0,0 +1,226 @@
+/*
+ *  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 groovy.ui;
+
+import groovy.lang.GroovyCodeSource;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.GroovyShell;
+import groovy.lang.Script;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.regex.Pattern;
+
+/**
+ * Simple server that executes supplied script against a socket.
+ * <p>
+ * Typically this is used from the groovy command line agent but it can be 
+ * invoked programmatically. To run this program from the command line please
+ * refer to the command line documentation at
+ * <a href="http://docs.groovy-lang.org/docs/latest/html/documentation/#_running_groovy_from_the_commandline">
+ * Running Groovy from the commandline</a>.
+ * <p>
+ * Here is an example of how to use this class to open a listening socket on the server, 
+ * listen for incoming data, and then echo the data back to the client in reverse order: 
+ * <pre>
+ * new GroovySocketServer(
+ *         new GroovyShell(),      // evaluator
+ *         false,                  // is not a file
+ *         "println line.reverse()",         // script to evaluate
+ *         true,                   // return result to client
+ *         1960)                   //port
+ * </pre>
+ * There are several variables in the script binding:
+ * <ul>
+ * <li>line - The data from the socket</li> 
+ * <li>out - The output PrintWriter, should you need it for some reason.</li> 
+ * <li>socket - The socket, should you need it for some reason.</li> 
+ * </ul>
+ * 
+ * @author Jeremy Rayner
+ */
+public class GroovySocketServer implements Runnable {
+    private URL url;
+    private final GroovyShell groovy;
+    private final GroovyCodeSource source;
+    private final boolean autoOutput;
+    private static int counter;
+
+    /**
+     * This creates and starts the socket server on a new Thread. There is no need to call run or spawn
+     * a new thread yourself.
+     * @param groovy
+     *       The GroovyShell object that evaluates the incoming text. If you need additional classes in the
+     *       classloader then configure that through this object.
+     * @param isScriptFile
+     *       Whether the incoming socket data String will be a script or a file path.
+     * @param scriptFilenameOrText
+     *       This will be a groovy script or a file location depending on the argument isScriptFile.
+     * @param autoOutput
+     *       whether output should be automatically echoed back to the client
+     * @param port
+     *       the port to listen on
+     *
+     */
+    public GroovySocketServer(GroovyShell groovy, boolean isScriptFile, String scriptFilenameOrText, boolean autoOutput, int port) {
+        this(groovy, getCodeSource(isScriptFile, scriptFilenameOrText), autoOutput, port);
+    }
+
+    private static GroovyCodeSource getCodeSource(boolean scriptFile, String scriptFilenameOrText) {
+        if (scriptFile) {
+            try {
+                if (URI_PATTERN.matcher(scriptFilenameOrText).matches()) {
+                    return new GroovyCodeSource(new URI(scriptFilenameOrText));
+                } else {
+                    return new GroovyCodeSource(GroovyMain.searchForGroovyScriptFile(scriptFilenameOrText));
+                }
+            } catch (IOException e) {
+                throw new GroovyRuntimeException("Unable to get script from: " + scriptFilenameOrText, e);
+            } catch (URISyntaxException e) {
+                throw new GroovyRuntimeException("Unable to get script from URI: " + scriptFilenameOrText, e);
+            }
+        } else {
+            // We could jump through some hoops to have GroovyShell make our script name, but that seems unwarranted.
+            // If we *did* jump through that hoop then we should probably change the run loop to not recompile
+            // the script on every iteration since the script text can't change (the reason for the recompilation).
+            return new GroovyCodeSource(scriptFilenameOrText, generateScriptName(), GroovyShell.DEFAULT_CODE_BASE);
+        }
+    }
+
+    private static synchronized String generateScriptName() {
+        return "ServerSocketScript" + (++counter) + ".groovy";
+    }
+
+
+    // RFC2396
+    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+    private static final Pattern URI_PATTERN = Pattern.compile("\\p{Alpha}[-+.\\p{Alnum}]*:.*");
+
+    /**
+    * This creates and starts the socket server on a new Thread. There is no need to call run or spawn
+    * a new thread yourself. 
+    * @param groovy
+    *       The GroovyShell object that evaluates the incoming text. If you need additional classes in the 
+    *       classloader then configure that through this object. 
+    * @param source
+    *       GroovyCodeSource for the Groovy script
+    * @param autoOutput
+    *       whether output should be automatically echoed back to the client
+    * @param port
+    *       the port to listen on
+    * @since 2.3.0
+    */ 
+    public GroovySocketServer(GroovyShell groovy, GroovyCodeSource source, boolean autoOutput, int port) {
+        this.groovy = groovy;
+        this.source = source;
+        this.autoOutput = autoOutput;
+        try {
+            url = new URL("http", InetAddress.getLocalHost().getHostAddress(), port, "/");
+            System.out.println("groovy is listening on port " + port);
+        } catch (IOException e) { 
+            e.printStackTrace();
+        }
+        new Thread(this).start();
+    }
+
+    /**
+    * Runs this server. There is typically no need to call this method, as the object's constructor
+    * creates a new thread and runs this object automatically. 
+    */ 
+    public void run() {
+        try {
+            ServerSocket serverSocket = new ServerSocket(url.getPort());
+            while (true) {
+                // Create one script per socket connection.
+                // This is purposefully not caching the Script
+                // so that the script source file can be changed on the fly,
+                // as each connection is made to the server.
+                //FIXME: Groovy has other mechanisms specifically for watching to see if source code changes.
+                // We should probably be using that here.
+                // See also the comment about the fact we recompile a script that can't change.
+                Script script = groovy.parse(source);
+                new GroovyClientConnection(script, autoOutput, serverSocket.accept());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    static class GroovyClientConnection implements Runnable {
+        private Script script;
+        private Socket socket;
+        private BufferedReader reader;
+        private PrintWriter writer;
+        private boolean autoOutputFlag;
+    
+        GroovyClientConnection(Script script, boolean autoOutput,Socket socket) throws IOException {
+            this.script = script;
+            this.autoOutputFlag = autoOutput;
+            this.socket = socket;
+            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+            writer = new PrintWriter(socket.getOutputStream());
+            new Thread(this, "Groovy client connection - " + socket.getInetAddress().getHostAddress()).start();
+        }
+        public void run() {
+            try {
+                String line = null;
+                script.setProperty("out", writer);
+                script.setProperty("socket", socket);
+                script.setProperty("init", Boolean.TRUE);
+                while ((line = reader.readLine()) != null) {
+                    // System.out.println(line);
+                    script.setProperty("line", line);
+                    Object o = script.run();
+                    script.setProperty("init", Boolean.FALSE);
+                    if (o != null) {
+                        if ("success".equals(o)) {
+                            break; // to close sockets gracefully etc...
+                        } else {
+                            if (autoOutputFlag) {
+                                writer.println(o);
+                            }
+                        }
+                    }
+                    writer.flush();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    writer.flush();
+                    writer.close();
+                } finally {
+                    try {
+                        socket.close();
+                    } catch (IOException e3) {
+                        e3.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/AbstractFactory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/AbstractFactory.java b/src/main/groovy/groovy/util/AbstractFactory.java
new file mode 100644
index 0000000..54e68e1
--- /dev/null
+++ b/src/main/groovy/groovy/util/AbstractFactory.java
@@ -0,0 +1,63 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
+ * @author Danno Ferrin
+ */
+public abstract class AbstractFactory implements Factory {
+    public boolean isLeaf() {
+        return false;
+    }
+
+    public boolean isHandlesNodeChildren() {
+        return false;
+    }
+
+    public void onFactoryRegistration(FactoryBuilderSupport builder, String registeredName, String group) {
+        // do nothing
+    }
+
+    public boolean onHandleNodeAttributes( FactoryBuilderSupport builder, Object node,
+            Map attributes ) {
+        return true;
+    }
+
+    public boolean onNodeChildren( FactoryBuilderSupport builder, Object node, Closure childContent) {
+        return true;
+    }
+
+    public void onNodeCompleted( FactoryBuilderSupport builder, Object parent, Object node ) {
+        // do nothing
+    }
+
+    public void setParent( FactoryBuilderSupport builder, Object parent, Object child ) {
+        // do nothing
+    }
+
+    public void setChild( FactoryBuilderSupport builder, Object parent, Object child ) {
+        // do nothing
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/BufferedIterator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/BufferedIterator.java b/src/main/groovy/groovy/util/BufferedIterator.java
new file mode 100644
index 0000000..6fa50a9
--- /dev/null
+++ b/src/main/groovy/groovy/util/BufferedIterator.java
@@ -0,0 +1,31 @@
+/*
+ *  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 groovy.util;
+
+import java.util.Iterator;
+
+/**
+ * An iterator that allows examining the next element without consuming it.
+ *
+ * @author Andrew Taylor
+ * @since 2.5.0
+ */
+public interface BufferedIterator<T> extends Iterator<T> {
+    T head();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/BuilderSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/BuilderSupport.java b/src/main/groovy/groovy/util/BuilderSupport.java
new file mode 100644
index 0000000..f634f1f
--- /dev/null
+++ b/src/main/groovy/groovy/util/BuilderSupport.java
@@ -0,0 +1,228 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.MissingMethodException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An abstract base class for creating arbitrary nested trees of objects
+ * or events
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public abstract class BuilderSupport extends GroovyObjectSupport {
+
+    private Object current;
+    private Closure nameMappingClosure;
+    private final BuilderSupport proxyBuilder;
+
+    public BuilderSupport() {
+        this.proxyBuilder = this;
+    }
+
+    public BuilderSupport(BuilderSupport proxyBuilder) {
+        this(null, proxyBuilder);
+    }
+
+    public BuilderSupport(Closure nameMappingClosure, BuilderSupport proxyBuilder) {
+        this.nameMappingClosure = nameMappingClosure;
+        this.proxyBuilder = proxyBuilder;
+    }
+
+    /**
+     * Convenience method when no arguments are required
+     *
+     * @param methodName the name of the method to invoke
+     * @return the result of the call
+     */
+    public Object invokeMethod(String methodName) {
+        return invokeMethod(methodName, null);
+    }
+
+    public Object invokeMethod(String methodName, Object args) {
+        Object name = getName(methodName);
+        return doInvokeMethod(methodName, name, args);
+    }
+
+    protected Object doInvokeMethod(String methodName, Object name, Object args) {
+        Object node = null;
+        Closure closure = null;
+        List list = InvokerHelper.asList(args);
+
+        //System.out.println("Called invokeMethod with name: " + name + " arguments: " + list);
+
+        switch (list.size()) {
+            case 0:
+                node = proxyBuilder.createNode(name);
+                break;
+            case 1: {
+                Object object = list.get(0);
+                if (object instanceof Map) {
+                    node = proxyBuilder.createNode(name, (Map) object);
+                } else if (object instanceof Closure) {
+                    closure = (Closure) object;
+                    node = proxyBuilder.createNode(name);
+                } else {
+                    node = proxyBuilder.createNode(name, object);
+                }
+            }
+            break;
+            case 2: {
+                Object object1 = list.get(0);
+                Object object2 = list.get(1);
+                if (object1 instanceof Map) {
+                    if (object2 instanceof Closure) {
+                        closure = (Closure) object2;
+                        node = proxyBuilder.createNode(name, (Map) object1);
+                    } else {
+                        node = proxyBuilder.createNode(name, (Map) object1, object2);
+                    }
+                } else {
+                    if (object2 instanceof Closure) {
+                        closure = (Closure) object2;
+                        node = proxyBuilder.createNode(name, object1);
+                    } else if (object2 instanceof Map) {
+                        node = proxyBuilder.createNode(name, (Map) object2, object1);
+                    } else {
+                        throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
+                    }
+                }
+            }
+            break;
+            case 3: {
+                Object arg0 = list.get(0);
+                Object arg1 = list.get(1);
+                Object arg2 = list.get(2);
+                if (arg0 instanceof Map && arg2 instanceof Closure) {
+                    closure = (Closure) arg2;
+                    node = proxyBuilder.createNode(name, (Map) arg0, arg1);
+                } else if (arg1 instanceof Map && arg2 instanceof Closure) {
+                    closure = (Closure) arg2;
+                    node = proxyBuilder.createNode(name, (Map) arg1, arg0);
+                } else {
+                    throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
+                }
+            }
+            break;
+            default: {
+                throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
+            }
+
+        }
+
+        if (current != null) {
+            proxyBuilder.setParent(current, node);
+        }
+
+        if (closure != null) {
+            // push new node on stack
+            Object oldCurrent = getCurrent();
+            setCurrent(node);
+            // let's register the builder as the delegate
+            setClosureDelegate(closure, node);
+            try {
+                closure.call();
+            } catch (Exception e) {
+                throw new GroovyRuntimeException(e);
+            }
+            setCurrent(oldCurrent);
+        }
+
+        proxyBuilder.nodeCompleted(current, node);
+        return proxyBuilder.postNodeCompletion(current, node);
+    }
+
+    /**
+     * A strategy method to allow derived builders to use
+     * builder-trees and switch in different kinds of builders.
+     * This method should call the setDelegate() method on the closure
+     * which by default passes in this but if node is-a builder
+     * we could pass that in instead (or do something wacky too)
+     *
+     * @param closure the closure on which to call setDelegate()
+     * @param node    the node value that we've just created, which could be
+     *                a builder
+     */
+    protected void setClosureDelegate(Closure closure, Object node) {
+        closure.setDelegate(this);
+    }
+
+    protected abstract void setParent(Object parent, Object child);
+
+    protected abstract Object createNode(Object name);
+
+    protected abstract Object createNode(Object name, Object value);
+
+    protected abstract Object createNode(Object name, Map attributes);
+
+    protected abstract Object createNode(Object name, Map attributes, Object value);
+
+    /**
+     * A hook to allow names to be converted into some other object
+     * such as a QName in XML or ObjectName in JMX.
+     *
+     * @param methodName the name of the desired method
+     * @return the object representing the name
+     */
+    protected Object getName(String methodName) {
+        if (nameMappingClosure != null) {
+            return nameMappingClosure.call(methodName);
+        }
+        return methodName;
+    }
+
+
+    /**
+     * A hook to allow nodes to be processed once they have had all of their
+     * children applied.
+     *
+     * @param node   the current node being processed
+     * @param parent the parent of the node being processed
+     */
+    protected void nodeCompleted(Object parent, Object node) {
+    }
+
+    /**
+     * A hook to allow nodes to be processed once they have had all of their
+     * children applied and allows the actual node object that represents
+     * the Markup element to be changed
+     *
+     * @param node   the current node being processed
+     * @param parent the parent of the node being processed
+     * @return the node, possibly new, that represents the markup element
+     */
+    protected Object postNodeCompletion(Object parent, Object node) {
+        return node;
+    }
+
+    protected Object getCurrent() {
+        return current;
+    }
+
+    protected void setCurrent(Object current) {
+        this.current = current;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/CharsetToolkit.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/CharsetToolkit.java b/src/main/groovy/groovy/util/CharsetToolkit.java
new file mode 100644
index 0000000..e127459
--- /dev/null
+++ b/src/main/groovy/groovy/util/CharsetToolkit.java
@@ -0,0 +1,419 @@
+/*
+ *  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 groovy.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.nio.charset.Charset;
+import java.util.Collection;
+
+/**
+ * Utility class to guess the encoding of a given text file.
+ * <p>
+ * Unicode files encoded in UTF-16 (low or big endian) or UTF-8 files
+ * with a Byte Order Marker are correctly discovered. For UTF-8 files with no BOM, if the buffer
+ * is wide enough, the charset should also be discovered.
+ * <p>
+ * A byte buffer of 4KB is used to be able to guess the encoding.
+ * <p>
+ * Usage:
+ * <pre>
+ * CharsetToolkit toolkit = new CharsetToolkit(file);
+ *
+ * // guess the encoding
+ * Charset guessedCharset = toolkit.getCharset();
+ *
+ * // create a reader with the correct charset
+ * BufferedReader reader = toolkit.getReader();
+ *
+ * // read the file content
+ * String line;
+ * while ((line = br.readLine())!= null)
+ * {
+ *     System.out.println(line);
+ * }
+ * </pre>
+ *
+ * @author Guillaume Laforge
+ */
+public class CharsetToolkit {
+    private final byte[] buffer;
+    private Charset defaultCharset;
+    private Charset charset;
+    private boolean enforce8Bit = true;
+    private final File file;
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    /**
+     * Constructor of the <code>CharsetToolkit</code> utility class.
+     *
+     * @param file of which we want to know the encoding.
+     */
+    public CharsetToolkit(File file) throws IOException {
+        this.file = file;
+        this.defaultCharset = getDefaultSystemCharset();
+        this.charset = null;
+        InputStream input = new FileInputStream(file);
+        try {
+            byte[] bytes = new byte[4096];
+            int bytesRead = input.read(bytes);
+            if (bytesRead == -1) {
+                this.buffer = EMPTY_BYTE_ARRAY;
+            }
+            else if (bytesRead < 4096) {
+                byte[] bytesToGuess = new byte[bytesRead];
+                System.arraycopy(bytes, 0, bytesToGuess, 0, bytesRead);
+                this.buffer = bytesToGuess;
+            }
+            else {
+                this.buffer = bytes;
+            }
+        } finally {
+            try {input.close();} catch (IOException e){
+                // IGNORE
+            }
+        }
+    }
+
+    /**
+     * Defines the default <code>Charset</code> used in case the buffer represents
+     * an 8-bit <code>Charset</code>.
+     *
+     * @param defaultCharset the default <code>Charset</code> to be returned
+     * if an 8-bit <code>Charset</code> is encountered.
+     */
+    public void setDefaultCharset(Charset defaultCharset) {
+        if (defaultCharset != null)
+            this.defaultCharset = defaultCharset;
+        else
+            this.defaultCharset = getDefaultSystemCharset();
+    }
+
+    public Charset getCharset() {
+        if (this.charset == null)
+            this.charset = guessEncoding();
+        return charset;
+    }
+
+    /**
+     * If US-ASCII is recognized, enforce to return the default encoding, rather than US-ASCII.
+     * It might be a file without any special character in the range 128-255, but that may be or become
+     * a file encoded with the default <code>charset</code> rather than US-ASCII.
+     *
+     * @param enforce a boolean specifying the use or not of US-ASCII.
+     */
+    public void setEnforce8Bit(boolean enforce) {
+        this.enforce8Bit = enforce;
+    }
+
+    /**
+     * Gets the enforce8Bit flag, in case we do not want to ever get a US-ASCII encoding.
+     *
+     * @return a boolean representing the flag of use of US-ASCII.
+     */
+    public boolean getEnforce8Bit() {
+        return this.enforce8Bit;
+    }
+
+    /**
+     * Retrieves the default Charset
+     */
+    public Charset getDefaultCharset() {
+        return defaultCharset;
+    }
+
+    /**
+     * Guess the encoding of the provided buffer.
+     * If Byte Order Markers are encountered at the beginning of the buffer, we immediately
+     * return the charset implied by this BOM. Otherwise, the file would not be a human
+     * readable text file.
+     * <p>
+     * If there is no BOM, this method tries to discern whether the file is UTF-8 or not.
+     * If it is not UTF-8, we assume the encoding is the default system encoding
+     * (of course, it might be any 8-bit charset, but usually, an 8-bit charset is the default one).
+     * <p>
+     * It is possible to discern UTF-8 thanks to the pattern of characters with a multi-byte sequence.
+     * <pre>
+     * UCS-4 range (hex.)        UTF-8 octet sequence (binary)
+     * 0000 0000-0000 007F       0xxxxxxx
+     * 0000 0080-0000 07FF       110xxxxx 10xxxxxx
+     * 0000 0800-0000 FFFF       1110xxxx 10xxxxxx 10xxxxxx
+     * 0001 0000-001F FFFF       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+     * 0020 0000-03FF FFFF       111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+     * 0400 0000-7FFF FFFF       1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+     * </pre>
+     * With UTF-8, 0xFE and 0xFF never appear.
+     *
+     * @return the Charset recognized.
+     */
+    private Charset guessEncoding() {
+        // if the file has a Byte Order Marker, we can assume the file is in UTF-xx
+        // otherwise, the file would not be human readable
+        if (hasUTF8Bom())
+            return Charset.forName("UTF-8");
+        if (hasUTF16LEBom())
+            return Charset.forName("UTF-16LE");
+        if (hasUTF16BEBom())
+            return Charset.forName("UTF-16BE");
+
+        // if a byte has its most significant bit set, the file is in UTF-8 or in the default encoding
+        // otherwise, the file is in US-ASCII
+        boolean highOrderBit = false;
+
+        // if the file is in UTF-8, high order bytes must have a certain value, in order to be valid
+        // if it's not the case, we can assume the encoding is the default encoding of the system
+        boolean validU8Char = true;
+
+        // TODO the buffer is not read up to the end, but up to length - 6
+
+        int length = buffer.length;
+        int i = 0;
+        while (i < length - 6) {
+            byte b0 = buffer[i];
+            byte b1 = buffer[i + 1];
+            byte b2 = buffer[i + 2];
+            byte b3 = buffer[i + 3];
+            byte b4 = buffer[i + 4];
+            byte b5 = buffer[i + 5];
+            if (b0 < 0) {
+                // a high order bit was encountered, thus the encoding is not US-ASCII
+                // it may be either an 8-bit encoding or UTF-8
+                highOrderBit = true;
+                // a two-bytes sequence was encountered
+                if (isTwoBytesSequence(b0)) {
+                    // there must be one continuation byte of the form 10xxxxxx,
+                    // otherwise the following character is is not a valid UTF-8 construct
+                    if (!isContinuationChar(b1))
+                        validU8Char = false;
+                    else
+                        i++;
+                }
+                // a three-bytes sequence was encountered
+                else if (isThreeBytesSequence(b0)) {
+                    // there must be two continuation bytes of the form 10xxxxxx,
+                    // otherwise the following character is is not a valid UTF-8 construct
+                    if (!(isContinuationChar(b1) && isContinuationChar(b2)))
+                        validU8Char = false;
+                    else
+                        i += 2;
+                }
+                // a four-bytes sequence was encountered
+                else if (isFourBytesSequence(b0)) {
+                    // there must be three continuation bytes of the form 10xxxxxx,
+                    // otherwise the following character is is not a valid UTF-8 construct
+                    if (!(isContinuationChar(b1) && isContinuationChar(b2) && isContinuationChar(b3)))
+                        validU8Char = false;
+                    else
+                        i += 3;
+                }
+                // a five-bytes sequence was encountered
+                else if (isFiveBytesSequence(b0)) {
+                    // there must be four continuation bytes of the form 10xxxxxx,
+                    // otherwise the following character is is not a valid UTF-8 construct
+                    if (!(isContinuationChar(b1)
+                        && isContinuationChar(b2)
+                        && isContinuationChar(b3)
+                        && isContinuationChar(b4)))
+                        validU8Char = false;
+                    else
+                        i += 4;
+                }
+                // a six-bytes sequence was encountered
+                else if (isSixBytesSequence(b0)) {
+                    // there must be five continuation bytes of the form 10xxxxxx,
+                    // otherwise the following character is is not a valid UTF-8 construct
+                    if (!(isContinuationChar(b1)
+                        && isContinuationChar(b2)
+                        && isContinuationChar(b3)
+                        && isContinuationChar(b4)
+                        && isContinuationChar(b5)))
+                        validU8Char = false;
+                    else
+                        i += 5;
+                }
+                else
+                    validU8Char = false;
+            }
+            if (!validU8Char)
+                break;
+            i++;
+        }
+        // if no byte with an high order bit set, the encoding is US-ASCII
+        // (it might have been UTF-7, but this encoding is usually internally used only by mail systems)
+        if (!highOrderBit) {
+            // returns the default charset rather than US-ASCII if the enforce8Bit flag is set.
+            if (this.enforce8Bit)
+                return this.defaultCharset;
+            else
+                return Charset.forName("US-ASCII");
+        }
+        // if no invalid UTF-8 were encountered, we can assume the encoding is UTF-8,
+        // otherwise the file would not be human readable
+        if (validU8Char)
+            return Charset.forName("UTF-8");
+        // finally, if it's not UTF-8 nor US-ASCII, let's assume the encoding is the default encoding
+        return this.defaultCharset;
+    }
+
+    /**
+     * If the byte has the form 10xxxxx, then it's a continuation byte of a multiple byte character;
+     *
+     * @param b a byte.
+     * @return true if it's a continuation char.
+     */
+    private static boolean isContinuationChar(byte b) {
+        return -128 <= b && b <= -65;
+    }
+
+    /**
+     * If the byte has the form 110xxxx, then it's the first byte of a two-bytes sequence character.
+     *
+     * @param b a byte.
+     * @return true if it's the first byte of a two-bytes sequence.
+     */
+    private static boolean isTwoBytesSequence(byte b) {
+        return -64 <= b && b <= -33;
+    }
+
+    /**
+     * If the byte has the form 1110xxx, then it's the first byte of a three-bytes sequence character.
+     *
+     * @param b a byte.
+     * @return true if it's the first byte of a three-bytes sequence.
+     */
+    private static boolean isThreeBytesSequence(byte b) {
+        return -32 <= b && b <= -17;
+    }
+
+    /**
+     * If the byte has the form 11110xx, then it's the first byte of a four-bytes sequence character.
+     *
+     * @param b a byte.
+     * @return true if it's the first byte of a four-bytes sequence.
+     */
+    private static boolean isFourBytesSequence(byte b) {
+        return -16 <= b && b <= -9;
+    }
+
+    /**
+     * If the byte has the form 11110xx, then it's the first byte of a five-bytes sequence character.
+     *
+     * @param b a byte.
+     * @return true if it's the first byte of a five-bytes sequence.
+     */
+    private static boolean isFiveBytesSequence(byte b) {
+        return -8 <= b && b <= -5;
+    }
+
+    /**
+     * If the byte has the form 1110xxx, then it's the first byte of a six-bytes sequence character.
+     *
+     * @param b a byte.
+     * @return true if it's the first byte of a six-bytes sequence.
+     */
+    private static boolean isSixBytesSequence(byte b) {
+        return -4 <= b && b <= -3;
+    }
+
+    /**
+     * Retrieve the default charset of the system.
+     *
+     * @return the default <code>Charset</code>.
+     */
+    public static Charset getDefaultSystemCharset() {
+        return Charset.forName(System.getProperty("file.encoding"));
+    }
+
+    /**
+     * Has a Byte Order Marker for UTF-8 (Used by Microsoft's Notepad and other editors).
+     *
+     * @return true if the buffer has a BOM for UTF8.
+     */
+    public boolean hasUTF8Bom() {
+        if (buffer.length >= 3)
+            return (buffer[0] == -17 && buffer[1] == -69 && buffer[2] == -65);
+        else
+            return false;
+    }
+
+    /**
+     * Has a Byte Order Marker for UTF-16 Low Endian
+     * (ucs-2le, ucs-4le, and ucs-16le).
+     *
+     * @return true if the buffer has a BOM for UTF-16 Low Endian.
+     */
+    public boolean hasUTF16LEBom() {
+        if (buffer.length >= 2)
+            return (buffer[0] == -1 && buffer[1] == -2);
+        else
+            return false;
+    }
+
+    /**
+     * Has a Byte Order Marker for UTF-16 Big Endian
+     * (utf-16 and ucs-2).
+     *
+     * @return true if the buffer has a BOM for UTF-16 Big Endian.
+     */
+    public boolean hasUTF16BEBom() {
+        if (buffer.length >= 2)
+            return (buffer[0] == -2 && buffer[1] == -1);
+        else
+            return false;
+    }
+
+    /**
+     * Gets a <code>BufferedReader</code> (indeed a <code>LineNumberReader</code>) from the <code>File</code>
+     * specified in the constructor of <code>CharsetToolkit</code> using the charset discovered or the default
+     * charset if an 8-bit <code>Charset</code> is encountered.
+     *
+     * @return a <code>BufferedReader</code>
+     * @throws FileNotFoundException if the file is not found.
+     */
+    public BufferedReader getReader() throws FileNotFoundException {
+        LineNumberReader reader = new LineNumberReader(new InputStreamReader(new FileInputStream(file), getCharset()));
+        if (hasUTF8Bom() || hasUTF16LEBom() || hasUTF16BEBom()) {
+            try {
+                reader.read();
+            }
+            catch (IOException e) {
+                // should never happen, as a file with no content
+                // but with a BOM has at least one char
+            }
+        }
+        return reader;
+    }
+
+    /**
+     * Retrieves all the available <code>Charset</code>s on the platform,
+     * among which the default <code>charset</code>.
+     *
+     * @return an array of <code>Charset</code>s.
+     */
+    public static Charset[] getAvailableCharsets() {
+        Collection collection = Charset.availableCharsets().values();
+        return (Charset[]) collection.toArray(new Charset[collection.size()]);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/CliBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/CliBuilder.groovy b/src/main/groovy/groovy/util/CliBuilder.groovy
new file mode 100644
index 0000000..bc7d44a
--- /dev/null
+++ b/src/main/groovy/groovy/util/CliBuilder.groovy
@@ -0,0 +1,798 @@
+/*
+ *  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 groovy.util
+
+import groovy.cli.CliBuilderException
+import groovy.cli.Option
+import groovy.cli.TypedOption
+import groovy.cli.Unparsed
+import groovy.transform.Undefined
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.CommandLineParser
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.GnuParser
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Option as CliOption
+import org.apache.commons.cli.Options
+import org.apache.commons.cli.ParseException
+import org.codehaus.groovy.runtime.InvokerHelper
+import org.codehaus.groovy.runtime.MetaClassHelper
+import org.codehaus.groovy.runtime.StringGroovyMethods
+
+import java.lang.annotation.Annotation
+import java.lang.reflect.Array
+import java.lang.reflect.Field
+import java.lang.reflect.Method
+
+/**
+ * Provides a builder to assist the processing of command line arguments.
+ * Two styles are supported: dynamic api style (declarative method calls provide a mini DSL for describing options)
+ * and annotation style (annotations on an interface or class describe options).
+ * <p>
+ * <b>Dynamic api style</b>
+ * <p>
+ * Typical usage (emulate partial arg processing of unix command: ls -alt *.groovy):
+ * <pre>
+ * def cli = new CliBuilder(usage:'ls')
+ * cli.a('display all files')
+ * cli.l('use a long listing format')
+ * cli.t('sort by modification time')
+ * def options = cli.parse(args)
+ * assert options // would be null (false) on failure
+ * assert options.arguments() == ['*.groovy']
+ * assert options.a && options.l && options.t
+ * </pre>
+ * The usage message for this example (obtained using <code>cli.usage()</code>) is shown below:
+ * <pre>
+ * usage: ls
+ *  -a   display all files
+ *  -l   use a long listing format
+ *  -t   sort by modification time
+ * </pre>
+ * An underlying parser that supports what is called argument 'bursting' is used
+ * by default. Bursting would convert '-alt' into '-a -l -t' provided no long
+ * option exists with value 'alt' and provided that none of 'a', 'l' or 't'
+ * takes an argument (in fact the last one is allowed to take an argument).
+ * The bursting behavior can be turned off by using an
+ * alternate underlying parser. The simplest way to achieve this is by using
+ * the deprecated GnuParser from Commons CLI with the parser property on the CliBuilder,
+ * i.e. include <code>parser: new GnuParser()</code> in the constructor call.
+ * <p>
+ * Another example (partial emulation of arg processing for 'ant' command line):
+ * <pre>
+ * def cli = new CliBuilder(usage:'ant [options] [targets]',
+ *                          header:'Options:')
+ * cli.help('print this message')
+ * cli.logfile(args:1, argName:'file', 'use given file for log')
+ * cli.D(args:2, valueSeparator:'=', argName:'property=value',
+ *       'use value for given property')
+ * def options = cli.parse(args)
+ * ...
+ * </pre>
+ * Usage message would be:
+ * <pre>
+ * usage: ant [options] [targets]
+ * Options:
+ *  -D &lt;property=value>   use value for given property
+ *  -help                 print this message
+ *  -logfile &lt;file>       use given file for log
+ * </pre>
+ * And if called with the following arguments '-logfile foo -Dbar=baz target'
+ * then the following assertions would be true:
+ * <pre>
+ * assert options // would be null (false) on failure
+ * assert options.arguments() == ['target']
+ * assert options.Ds == ['bar', 'baz']
+ * assert options.logfile == 'foo'
+ * </pre>
+ * Note the use of some special notation. By adding 's' onto an option
+ * that may appear multiple times and has an argument or as in this case
+ * uses a valueSeparator to separate multiple argument values
+ * causes the list of associated argument values to be returned.
+ * <p>
+ * Another example showing long options (partial emulation of arg processing for 'curl' command line):
+ * <pre>
+ * def cli = new CliBuilder(usage:'curl [options] &lt;url&gt;')
+ * cli._(longOpt:'basic', 'Use HTTP Basic Authentication')
+ * cli.d(longOpt:'data', args:1, argName:'data', 'HTTP POST data')
+ * cli.G(longOpt:'get', 'Send the -d data with a HTTP GET')
+ * cli.q('If used as the first parameter disables .curlrc')
+ * cli._(longOpt:'url', args:1, argName:'URL', 'Set URL to work with')
+ * </pre>
+ * Which has the following usage message:
+ * <pre>
+ * usage: curl [options] &lt;url>
+ *     --basic         Use HTTP Basic Authentication
+ *  -d,--data &lt;data>   HTTP POST data
+ *  -G,--get           Send the -d data with a HTTP GET
+ *  -q                 If used as the first parameter disables .curlrc
+ *     --url &lt;URL>     Set URL to work with
+ * </pre>
+ * This example shows a common convention. When mixing short and long names, the
+ * short names are often one character in size. One character options with
+ * arguments don't require a space between the option and the argument, e.g.
+ * <code>-Ddebug=true</code>. The example also shows
+ * the use of '_' when no short option is applicable.
+ * <p>
+ * Also note that '_' was used multiple times. This is supported but if
+ * any other shortOpt or any longOpt is repeated, then the behavior is undefined.
+ * <p>
+ * Short option names may not contain a hyphen. If a long option name contains a hyphen, e.g. '--max-wait' then you can either
+ * use the long hand method call <code>options.hasOption('max-wait')</code> or surround
+ * the option name in quotes, e.g. <code>options.'max-wait'</code>.
+ * <p>
+ * Although CliBuilder on the whole hides away the underlying library used
+ * for processing the arguments, it does provide some hooks which let you
+ * make use of the underlying library directly should the need arise. For
+ * example, the last two lines of the 'curl' example above could be replaced
+ * with the following:
+ * <pre>
+ * import org.apache.commons.cli.*
+ * ... as before ...
+ * cli << new Option('q', false, 'If used as the first parameter disables .curlrc')
+ * cli << Option.builder().longOpt('url').hasArg().argName('URL').
+ *                      desc('Set URL to work with').build()
+ * ...
+ * </pre>
+ *
+ * CliBuilder also supports Argument File processing. If an argument starts with
+ * an '@' character followed by a filename, then the contents of the file with name
+ * filename are placed into the command line. The feature can be turned off by
+ * setting expandArgumentFiles to false. If turned on, you can still pass a real
+ * parameter with an initial '@' character by escaping it with an additional '@'
+ * symbol, e.g. '@@foo' will become '@foo' and not be subject to expansion. As an
+ * example, if the file temp.args contains the content:
+ * <pre>
+ * -arg1
+ * paramA
+ * paramB paramC
+ * </pre>
+ * Then calling the command line with:
+ * <pre>
+ * someCommand @temp.args -arg2 paramD
+ * </pre>
+ * Is the same as calling this:
+ * <pre>
+ * someCommand -arg1 paramA paramB paramC -arg2 paramD
+ * </pre>
+ * This feature is particularly useful on operating systems which place limitations
+ * on the size of the command line (e.g. Windows). The feature is similar to
+ * the 'Command Line Argument File' processing supported by javadoc and javac.
+ * Consult the corresponding documentation for those tools if you wish to see further examples.
+ * <p>
+ * <b>Supported Option Properties</b>:
+ * <pre>
+ *   argName:        String
+ *   longOpt:        String
+ *   args:           int or String
+ *   optionalArg:    boolean
+ *   required:       boolean
+ *   type:           Class
+ *   valueSeparator: char
+ *   convert:        Closure
+ *   defaultValue:   String
+ * </pre>
+ * See {@link org.apache.commons.cli.Option} for the meaning of most of these properties
+ * and {@link CliBuilderTest} for further examples.
+ * <p>
+ * <b>Annotation style with an interface</b>
+ * <p>
+ * With this style an interface is defined containing an annotated method for each option.
+ * It might look like this (following roughly the earlier 'ls' example):
+ * <pre>
+ * import groovy.cli.Option
+ * import groovy.cli.Unparsed
+ *
+ * interface OptionInterface {
+ *     @{@link groovy.cli.Option}(shortName='a', description='display all files') boolean all()
+ *     @{@link groovy.cli.Option}(shortName='l', description='use a long listing format') boolean longFormat()
+ *     @{@link groovy.cli.Option}(shortName='t', description='sort by modification time') boolean time()
+ *     @{@link groovy.cli.Unparsed} List remaining()
+ * }
+ * </pre>
+ * Then this description is supplied to CliBuilder during parsing, e.g.:
+ * <pre>
+ * def args = '-alt *.groovy'.split() // normally from commandline itself
+ * def cli = new CliBuilder(usage:'ls')
+ * def options = cli.parseFromSpec(OptionInterface, args)
+ * assert options.remaining() == ['*.groovy']
+ * assert options.all() && options.longFormat() && options.time()
+ * </pre>
+ * <p>
+ * <b>Annotation style with a class</b>
+ * <p>
+ * With this style a user-supplied instance is used. Annotations on that instance's class
+ * members (properties and setter methods) indicate how to set options and provide the option details
+ * using annotation attributes.
+ * It might look like this (again using the earlier 'ls' example):
+ * <pre>
+ * import groovy.cli.Option
+ * import groovy.cli.Unparsed
+ *
+ * class OptionClass {
+ *     @{@link groovy.cli.Option}(shortName='a', description='display all files') boolean all
+ *     @{@link groovy.cli.Option}(shortName='l', description='use a long listing format') boolean longFormat
+ *     @{@link groovy.cli.Option}(shortName='t', description='sort by modification time') boolean time
+ *     @{@link groovy.cli.Unparsed} List remaining
+ * }
+ * </pre>
+ * Then this description is supplied to CliBuilder during parsing, e.g.:
+ * <pre>
+ * def args = '-alt *.groovy'.split() // normally from commandline itself
+ * def cli = new CliBuilder(usage:'ls')
+ * def options = new OptionClass()
+ * cli.parseFromInstance(options, args)
+ * assert options.remaining == ['*.groovy']
+ * assert options.all && options.longFormat && options.time
+ * </pre>
+ */
+class CliBuilder {
+
+    /**
+     * Usage summary displayed as the first line when <code>cli.usage()</code> is called.
+     */
+    String usage = 'groovy'
+
+    /**
+     * Normally set internally but allows you full customisation of the underlying processing engine.
+     */
+    CommandLineParser parser = null
+
+    /**
+     * To change from the default PosixParser to the GnuParser, set this to false. Ignored if the parser is explicitly set.
+     * @deprecated use the parser option instead with an instance of your preferred parser
+     */
+    @Deprecated
+    Boolean posix = null
+
+    /**
+     * Whether arguments of the form '{@code @}<i>filename</i>' will be expanded into the arguments contained within the file named <i>filename</i> (default true).
+     */
+    boolean expandArgumentFiles = true
+
+    /**
+     * Normally set internally but can be overridden if you want to customise how the usage message is displayed.
+     */
+    HelpFormatter formatter = new HelpFormatter()
+
+    /**
+     * Defaults to stdout but you can provide your own PrintWriter if desired.
+     */
+    PrintWriter writer = new PrintWriter(System.out)
+
+    /**
+     * Optional additional message for usage; displayed after the usage summary but before the options are displayed.
+     */
+    String header = ''
+
+    /**
+     * Optional additional message for usage; displayed after the options are displayed.
+     */
+    String footer = ''
+
+    /**
+     * Indicates that option processing should continue for all arguments even
+     * if arguments not recognized as options are encountered (default true).
+     */
+    boolean stopAtNonOption = true
+
+    /**
+     * Allows customisation of the usage message width.
+     */
+    int width = HelpFormatter.DEFAULT_WIDTH
+
+    /**
+     * Not normally accessed directly but full access to underlying options if needed.
+     */
+    Options options = new Options()
+
+    Map<String, TypedOption> savedTypeOptions = new HashMap<String, TypedOption>()
+
+    public <T> TypedOption<T> option(Map args, Class<T> type, String description) {
+        def name = args.opt ?: '_'
+        args.type = type
+        args.remove('opt')
+        "$name"(args, description)
+    }
+
+    /**
+     * Internal method: Detect option specification method calls.
+     */
+    def invokeMethod(String name, Object args) {
+        if (args instanceof Object[]) {
+            if (args.size() == 1 && (args[0] instanceof String || args[0] instanceof GString)) {
+                def option = option(name, [:], args[0])
+                options.addOption(option)
+
+                return create(option, null, null, null)
+            }
+            if (args.size() == 1 && args[0] instanceof CliOption && name == 'leftShift') {
+                CliOption option = args[0]
+                options.addOption(option)
+                return create(option, null, null, null)
+            }
+            if (args.size() == 2 && args[0] instanceof Map) {
+                def convert = args[0].remove('convert')
+                def type = args[0].remove('type')
+                def defaultValue = args[0].remove('defaultValue')
+                if (type && !(type instanceof Class)) {
+                    throw new CliBuilderException("'type' must be a Class")
+                }
+                if ((convert || type) && !args[0].containsKey('args') &&
+                        type?.simpleName?.toLowerCase() != 'boolean') {
+                    args[0].args = 1
+                }
+                def option = option(name, args[0], args[1])
+                options.addOption(option)
+                return create(option, type, defaultValue, convert)
+            }
+        }
+        return InvokerHelper.getMetaClass(this).invokeMethod(this, name, args)
+    }
+
+    /**
+     * Make options accessible from command line args with parser.
+     * Returns null on bad command lines after displaying usage message.
+     */
+    OptionAccessor parse(args) {
+        if (expandArgumentFiles) args = expandArgumentFiles(args)
+        if (!parser) {
+            parser = posix != null && posix == false ? new GnuParser() : new DefaultParser()
+        }
+        try {
+            def accessor = new OptionAccessor(
+                    parser.parse(options, args as String[], stopAtNonOption))
+            accessor.savedTypeOptions = savedTypeOptions
+            return accessor
+        } catch (ParseException pe) {
+            writer.println("error: " + pe.message)
+            usage()
+            return null
+        }
+    }
+
+    /**
+     * Print the usage message with writer (default: System.out) and formatter (default: HelpFormatter)
+     */
+    void usage() {
+        formatter.printHelp(writer, width, usage, header, options, HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD, footer)
+        writer.flush()
+    }
+
+    /**
+     * Given an interface containing members with annotations, derive
+     * the options specification.
+     *
+     * @param optionsClass
+     * @param args
+     * @return an instance containing the processed options
+     */
+    public <T> T parseFromSpec(Class<T> optionsClass, String[] args) {
+        addOptionsFromAnnotations(optionsClass, false)
+        def cli = parse(args)
+        def cliOptions = [:]
+        setOptionsFromAnnotations(cli, optionsClass, cliOptions, false)
+        cliOptions as T
+    }
+
+    /**
+     * Given an instance containing members with annotations, derive
+     * the options specification.
+     *
+     * @param optionInstance
+     * @param args
+     * @return the options instance populated with the processed options
+     */
+    public <T> T parseFromInstance(T optionInstance, args) {
+        addOptionsFromAnnotations(optionInstance.getClass(), true)
+        def cli = parse(args)
+        setOptionsFromAnnotations(cli, optionInstance.getClass(), optionInstance, true)
+        optionInstance
+    }
+
+    void addOptionsFromAnnotations(Class optionClass, boolean namesAreSetters) {
+        optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
+            Annotation annotation = m.getAnnotation(Option)
+            def typedOption = processAddAnnotation(annotation, m, namesAreSetters)
+            options.addOption(typedOption.cliOption)
+        }
+
+        def optionFields = optionClass.declaredFields.findAll { it.getAnnotation(Option) }
+        if (optionClass.isInterface() && !optionFields.isEmpty()) {
+            throw new CliBuilderException("@Option only allowed on methods in interface " + optionClass.simpleName)
+        }
+        optionFields.each { Field f ->
+            Annotation annotation = f.getAnnotation(Option)
+            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
+            Method m = optionClass.getMethod(setterName, f.getType())
+            def typedOption = processAddAnnotation(annotation, m, true)
+            options.addOption(typedOption.cliOption)
+        }
+    }
+
+    private TypedOption processAddAnnotation(Option annotation, Method m, boolean namesAreSetters) {
+        String shortName = annotation.shortName()
+        String description = annotation.description()
+        String defaultValue = annotation.defaultValue()
+        char valueSeparator = 0
+        if (annotation.valueSeparator()) valueSeparator = annotation.valueSeparator() as char
+        boolean optionalArg = annotation.optionalArg()
+        Integer numberOfArguments = annotation.numberOfArguments()
+        String numberOfArgumentsString = annotation.numberOfArgumentsString()
+        Class convert = annotation.convert()
+        if (convert == Undefined.CLASS) {
+            convert = null
+        }
+        Map names = calculateNames(annotation.longName(), shortName, m, namesAreSetters)
+        def builder = names.short ? CliOption.builder(names.short) : CliOption.builder()
+        if (names.long) {
+            builder.longOpt(names.long)
+        }
+        if (numberOfArguments != 1) {
+            if (numberOfArgumentsString) {
+                throw new CliBuilderException("You can't specify both 'numberOfArguments' and 'numberOfArgumentsString'")
+            }
+        }
+        def details = [:]
+        Class type = namesAreSetters ? (m.parameterTypes.size() > 0 ? m.parameterTypes[0] : null) : m.returnType
+        if (optionalArg && (!type || !type.isArray())) {
+            throw new CliBuilderException("Attempted to set optional argument for non array type")
+        }
+        def isFlag = type.simpleName.toLowerCase() == 'boolean'
+        if (numberOfArgumentsString) {
+            details.args = numberOfArgumentsString
+            details = adjustDetails(details)
+            if (details.optionalArg) optionalArg = true
+        } else {
+            details.args = isFlag ? 0 : numberOfArguments
+        }
+        if (details?.args == 0 && !(isFlag || type.name == 'java.lang.Object')) {
+            throw new CliBuilderException("Flag '${names.long ?: names.short}' must be Boolean or Object")
+        }
+        if (description) builder.desc(description)
+        if (valueSeparator) builder.valueSeparator(valueSeparator)
+        if (type) {
+            if (isFlag && details.args == 1) {
+                // special flag: treat like normal not boolean expecting explicit 'true' or 'false' param
+                isFlag = false
+            }
+            if (!isFlag) {
+                builder.hasArg(true)
+                if (details.containsKey('args')) builder.numberOfArgs(details.args)
+            }
+            if (type.isArray()) {
+                builder.optionalArg(optionalArg)
+            }
+        }
+        def typedOption = create(builder.build(), convert ? null : type, defaultValue, convert)
+        typedOption
+    }
+
+    private TypedOption create(CliOption o, Class theType, defaultValue, convert) {
+        Map<String, Object> result = new TypedOption<Object>()
+        o.with {
+            if (opt != null) result.put("opt", opt)
+            result.put("longOpt", longOpt)
+            result.put("cliOption", o)
+            if (defaultValue) {
+                result.put("defaultValue", defaultValue)
+            }
+            if (convert) {
+                if (theType) {
+                    throw new CliBuilderException("You can't specify 'type' when using 'convert'")
+                }
+                result.put("convert", convert)
+                result.put("type", convert instanceof Class ? convert : convert.getClass())
+            } else {
+                result.put("type", theType)
+            }
+        }
+        savedTypeOptions[o.longOpt ?: o.opt] = result
+        result
+    }
+
+    def setOptionsFromAnnotations(def cli, Class optionClass, Object t, boolean namesAreSetters) {
+        optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
+            Annotation annotation = m.getAnnotation(Option)
+            Map names = calculateNames(annotation.longName(), annotation.shortName(), m, namesAreSetters)
+            processSetAnnotation(m, t, names.long ?: names.short, cli, namesAreSetters)
+        }
+        optionClass.declaredFields.findAll { it.getAnnotation(Option) }.each { Field f ->
+            Annotation annotation = f.getAnnotation(Option)
+            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
+            Method m = optionClass.getMethod(setterName, f.getType())
+            Map names = calculateNames(annotation.longName(), annotation.shortName(), m, true)
+            processSetAnnotation(m, t, names.long ?: names.short, cli, true)
+        }
+        def remaining = cli.arguments()
+        optionClass.methods.findAll{ it.getAnnotation(Unparsed) }.each { Method m ->
+            processSetRemaining(m, remaining, t, cli, namesAreSetters)
+        }
+        optionClass.declaredFields.findAll{ it.getAnnotation(Unparsed) }.each { Field f ->
+            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
+            Method m = optionClass.getMethod(setterName, f.getType())
+            processSetRemaining(m, remaining, t, cli, namesAreSetters)
+        }
+    }
+
+    private void processSetRemaining(Method m, remaining, Object t, cli, boolean namesAreSetters) {
+        def resultType = namesAreSetters ? m.parameterTypes[0] : m.returnType
+        def isTyped = resultType?.isArray()
+        def result
+        def type = null
+        if (isTyped) {
+            type = resultType.componentType
+            result = remaining.collect{ cli.getValue(type, it, null) }
+        } else {
+            result = remaining.toList()
+        }
+        if (namesAreSetters) {
+            m.invoke(t, isTyped ? [result.toArray(Array.newInstance(type, result.size()))] as Object[] : result)
+        } else {
+            Map names = calculateNames("", "", m, namesAreSetters)
+            t.put(names.long, { -> result })
+        }
+    }
+
+    private void processSetAnnotation(Method m, Object t, String name, cli, boolean namesAreSetters) {
+        def conv = savedTypeOptions[name]?.convert
+        if (conv && conv instanceof Class) {
+            savedTypeOptions[name].convert = conv.newInstance(t, t)
+        }
+        boolean hasArg = savedTypeOptions[name]?.cliOption?.numberOfArgs == 1
+        boolean noArg = savedTypeOptions[name]?.cliOption?.numberOfArgs == 0
+        if (namesAreSetters) {
+            def isBoolArg = m.parameterTypes.size() > 0 && m.parameterTypes[0].simpleName.toLowerCase() == 'boolean'
+            boolean isFlag = (isBoolArg && !hasArg) || noArg
+            if (cli.hasOption(name) || isFlag || cli.defaultValue(name)) {
+                m.invoke(t, [isFlag ? cli.hasOption(name) :
+                                     cli.hasOption(name) ? optionValue(cli, name) : cli.defaultValue(name)] as Object[])
+            }
+        } else {
+            def isBoolRetType = m.returnType.simpleName.toLowerCase() == 'boolean'
+            boolean isFlag = (isBoolRetType && !hasArg) || noArg
+            t.put(m.getName(), cli.hasOption(name) ?
+                    { -> isFlag ? true : optionValue(cli, name) } :
+                    { -> isFlag ? false : cli.defaultValue(name) })
+        }
+    }
+
+    private optionValue(cli, String name) {
+        if (savedTypeOptions.containsKey(name)) {
+            return cli.getOptionValue(savedTypeOptions[name])
+        }
+        cli[name]
+    }
+
+    private Map calculateNames(String longName, String shortName, Method m, boolean namesAreSetters) {
+        boolean useShort = longName == '_'
+        if (longName == '_') longName = ""
+        def result = longName
+        if (!longName) {
+            result = m.getName()
+            if (namesAreSetters && result.startsWith("set")) {
+                result = MetaClassHelper.convertPropertyName(result.substring(3))
+            }
+        }
+        [long: useShort ? "" : result, short: (useShort && !shortName) ? result : shortName]
+    }
+
+    // implementation details -------------------------------------
+
+    /**
+     * Internal method: How to create an option from the specification.
+     */
+    CliOption option(shortname, Map details, info) {
+        CliOption option
+        if (shortname == '_') {
+            option = CliOption.builder().desc(info).longOpt(details.longOpt).build()
+            details.remove('longOpt')
+        } else {
+            option = new CliOption(shortname, info)
+        }
+        adjustDetails(details).each { key, value ->
+            option[key] = value
+        }
+        return option
+    }
+
+    static Map adjustDetails(Map m) {
+        m.collectMany { k, v ->
+            if (k == 'args' && v == '+') {
+                [[args: org.apache.commons.cli.Option.UNLIMITED_VALUES]]
+            } else if (k == 'args' && v == '*') {
+                [[args: org.apache.commons.cli.Option.UNLIMITED_VALUES,
+                  optionalArg: true]]
+            } else if (k == 'args' && v instanceof String) {
+                [[args: Integer.parseInt(v)]]
+            } else {
+                [[(k): v]]
+            }
+        }.sum()
+    }
+
+    static expandArgumentFiles(args) throws IOException {
+        def result = []
+        for (arg in args) {
+            if (arg && arg != '@' && arg[0] == '@') {
+                arg = arg.substring(1)
+                if (arg[0] != '@') {
+                    expandArgumentFile(arg, result)
+                    continue
+                }
+            }
+            result << arg
+        }
+        return result
+    }
+
+    private static expandArgumentFile(name, args) throws IOException {
+        def charAsInt = { String s -> s.toCharacter() as int }
+        new File(name).withReader { r ->
+            new StreamTokenizer(r).with {
+                resetSyntax()
+                wordChars(charAsInt(' '), 255)
+                whitespaceChars(0, charAsInt(' '))
+                commentChar(charAsInt('#'))
+                quoteChar(charAsInt('"'))
+                quoteChar(charAsInt('\''))
+                while (nextToken() != StreamTokenizer.TT_EOF) {
+                    args << sval
+                }
+            }
+        }
+    }
+
+}
+
+class OptionAccessor {
+    CommandLine commandLine
+    Map<String, TypedOption> savedTypeOptions
+
+    OptionAccessor(CommandLine commandLine) {
+        this.commandLine = commandLine
+    }
+
+    boolean hasOption(TypedOption typedOption) {
+        commandLine.hasOption(typedOption.longOpt ?: typedOption.opt)
+    }
+
+    public <T> T defaultValue(String name) {
+        Class<T> type = savedTypeOptions[name]?.type
+        String value = savedTypeOptions[name]?.defaultValue() ? savedTypeOptions[name].defaultValue() : null
+        return (T) value ? getTypedValue(type, name, value) : null
+    }
+
+    public <T> T getOptionValue(TypedOption<T> typedOption) {
+        getOptionValue(typedOption, null)
+    }
+
+    public <T> T getOptionValue(TypedOption<T> typedOption, T defaultValue) {
+        String optionName = (String) typedOption.longOpt ?: typedOption.opt
+        if (commandLine.hasOption(optionName)) {
+            if (typedOption.containsKey('type') && typedOption.type.isArray()) {
+                def compType = typedOption.type.componentType
+                return (T) getTypedValuesFromName(optionName, compType)
+            }
+            return getTypedValueFromName(optionName)
+        }
+        return defaultValue
+    }
+
+    private <T> T[] getTypedValuesFromName(String optionName, Class<T> compType) {
+        CliOption option = commandLine.options.find{ it.longOpt == optionName }
+        T[] result = null
+        if (option) {
+            int count = 0
+            def optionValues = commandLine.getOptionValues(optionName)
+            for (String optionValue : optionValues) {
+                if (result == null) {
+                    result = (T[]) Array.newInstance(compType, optionValues.length)
+                }
+                result[count++] = (T) getTypedValue(compType, optionName, optionValue)
+            }
+        }
+        if (result == null) {
+            result = (T[]) Array.newInstance(compType, 0)
+        }
+        return result
+    }
+
+    public <T> T getAt(TypedOption<T> typedOption) {
+        getAt(typedOption, null)
+    }
+
+    public <T> T getAt(TypedOption<T> typedOption, T defaultValue) {
+        String optionName = (String) typedOption.longOpt ?: typedOption.opt
+        if (savedTypeOptions.containsKey(optionName)) {
+            return getTypedValueFromName(optionName)
+        }
+        return defaultValue
+    }
+
+    private <T> T getTypedValueFromName(String optionName) {
+        Class type = savedTypeOptions[optionName].type
+        String optionValue = commandLine.getOptionValue(optionName)
+        return (T) getTypedValue(type, optionName, optionValue)
+    }
+
+    private <T> T getTypedValue(Class<T> type, String optionName, String optionValue) {
+        if (savedTypeOptions[optionName]?.cliOption?.numberOfArgs == 0) {
+            return (T) commandLine.hasOption(optionName)
+        }
+        def convert = savedTypeOptions[optionName]?.convert
+        return getValue(type, optionValue, convert)
+    }
+
+    private <T> T getValue(Class<T> type, String optionValue, Closure convert) {
+        if (!type) {
+            return (T) optionValue
+        }
+        if (Closure.isAssignableFrom(type) && convert) {
+            return (T) convert(optionValue)
+        }
+        if (type?.simpleName?.toLowerCase() == 'boolean') {
+            return (T) Boolean.parseBoolean(optionValue)
+        }
+        StringGroovyMethods.asType(optionValue, (Class<T>) type)
+    }
+
+    def invokeMethod(String name, Object args) {
+        return InvokerHelper.getMetaClass(commandLine).invokeMethod(commandLine, name, args)
+    }
+
+    def getProperty(String name) {
+        if (!savedTypeOptions.containsKey(name)) {
+            def alt = savedTypeOptions.find{ it.value.opt == name }
+            if (alt) name = alt.key
+        }
+        def methodname = 'getOptionValue'
+        Class type = savedTypeOptions[name]?.type
+        def foundArray = type?.isArray()
+        if (name.size() > 1 && name.endsWith('s')) {
+            def singularName = name[0..-2]
+            if (commandLine.hasOption(singularName) || foundArray) {
+                name = singularName
+                methodname += 's'
+                type = savedTypeOptions[name]?.type
+            }
+        }
+        if (type?.isArray()) {
+            methodname = 'getOptionValues'
+        }
+        if (name.size() == 1) name = name as char
+        def result = InvokerHelper.getMetaClass(commandLine).invokeMethod(commandLine, methodname, name)
+        if (result != null) {
+            if (result instanceof String[]) {
+                result = result.collect{ type ? getTypedValue(type.isArray() ? type.componentType : type, name, it) : it }
+            } else {
+                if (type) result = getTypedValue(type, name, result)
+            }
+        } else if (type?.simpleName != 'boolean' && savedTypeOptions[name]?.defaultValue) {
+            result = getTypedValue(type, name, savedTypeOptions[name].defaultValue)
+        } else {
+            result = commandLine.hasOption(name)
+        }
+        return result
+    }
+
+    List<String> arguments() {
+        commandLine.args.toList()
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ClosureComparator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ClosureComparator.java b/src/main/groovy/groovy/util/ClosureComparator.java
new file mode 100644
index 0000000..dc70ea6
--- /dev/null
+++ b/src/main/groovy/groovy/util/ClosureComparator.java
@@ -0,0 +1,45 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * A Comparator which uses a closure to compare 2 values being equal
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ClosureComparator<T> implements Comparator<T>, Serializable {
+
+    private static final long serialVersionUID = -4593521535656429522L;
+    Closure closure;
+
+    public ClosureComparator(Closure closure) {
+        this.closure = closure;
+    }
+
+    public int compare(T object1, T object2) {
+        Object value = closure.call(object1, object2);
+        return DefaultTypeTransformation.intUnbox(value);
+    }
+}


[23/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ObjectGraphBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ObjectGraphBuilder.java b/src/main/groovy/groovy/util/ObjectGraphBuilder.java
new file mode 100644
index 0000000..7ba0089
--- /dev/null
+++ b/src/main/groovy/groovy/util/ObjectGraphBuilder.java
@@ -0,0 +1,857 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.GString;
+import groovy.lang.MetaProperty;
+import groovy.lang.MissingPropertyException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * A builder for creating object graphs.<br>
+ * Each node defines the class to be created and the property on its parent (if
+ * any) at the same time.
+ *
+ * @author Scott Vlaminck (http://refactr.com)
+ * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
+ */
+public class ObjectGraphBuilder extends FactoryBuilderSupport {
+    public static final String NODE_CLASS = "_NODE_CLASS_";
+    public static final String NODE_NAME = "_NODE_NAME_";
+    public static final String OBJECT_ID = "_OBJECT_ID_";
+    public static final String LAZY_REF = "_LAZY_REF_";
+
+    public static final String CLASSNAME_RESOLVER_KEY = "name";
+    public static final String CLASSNAME_RESOLVER_REFLECTION = "reflection";
+    public static final String CLASSNAME_RESOLVER_REFLECTION_ROOT = "root";
+
+    // Regular expression pattern used to identify words ending in 'y' preceded by a consonant
+    private static final Pattern PLURAL_IES_PATTERN = Pattern.compile(".*[^aeiouy]y", Pattern.CASE_INSENSITIVE);
+
+    private ChildPropertySetter childPropertySetter;
+    private ClassNameResolver classNameResolver;
+    private IdentifierResolver identifierResolver;
+    private NewInstanceResolver newInstanceResolver;
+    private final ObjectFactory objectFactory = new ObjectFactory();
+    private final ObjectBeanFactory objectBeanFactory = new ObjectBeanFactory();
+    private final ObjectRefFactory objectRefFactory = new ObjectRefFactory();
+    private ReferenceResolver referenceResolver;
+    private RelationNameResolver relationNameResolver;
+    private final Map<String, Class> resolvedClasses = new HashMap<String, Class>();
+    private ClassLoader classLoader;
+    private boolean lazyReferencesAllowed = true;
+    private final List<NodeReference> lazyReferences = new ArrayList<NodeReference>();
+    private String beanFactoryName = "bean";
+
+    public ObjectGraphBuilder() {
+        classNameResolver = new DefaultClassNameResolver();
+        newInstanceResolver = new DefaultNewInstanceResolver();
+        relationNameResolver = new DefaultRelationNameResolver();
+        childPropertySetter = new DefaultChildPropertySetter();
+        identifierResolver = new DefaultIdentifierResolver();
+        referenceResolver = new DefaultReferenceResolver();
+
+        addPostNodeCompletionDelegate(new Closure(this, this) {
+            public void doCall(ObjectGraphBuilder builder, Object parent, Object node) {
+                if (parent == null) {
+                    builder.resolveLazyReferences();
+                    builder.dispose();
+                }
+            }
+        });
+    }
+
+    /**
+     * Returns the current name of the 'bean' node.
+     */
+    public String getBeanFactoryName() {
+        return beanFactoryName; 
+    }
+
+    /**
+     * Returns the current ChildPropertySetter.
+     */
+    public ChildPropertySetter getChildPropertySetter() {
+        return childPropertySetter;
+    }
+
+    /**
+     * Returns the classLoader used to load a node's class.
+     */
+    public ClassLoader getClassLoader() {
+        return classLoader;
+    }
+
+    /**
+     * Returns the current ClassNameResolver.
+     */
+    public ClassNameResolver getClassNameResolver() {
+        return classNameResolver;
+    }
+
+    /**
+     * Returns the current NewInstanceResolver.
+     */
+    public NewInstanceResolver getNewInstanceResolver() {
+        return newInstanceResolver;
+    }
+
+    /**
+     * Returns the current RelationNameResolver.
+     */
+    public RelationNameResolver getRelationNameResolver() {
+        return relationNameResolver;
+    }
+
+    /**
+     * Returns true if references can be resolved lazily
+     */
+    public boolean isLazyReferencesAllowed() {
+        return lazyReferencesAllowed;
+    }
+
+    /**
+     * Sets the name for the 'bean' node.
+     */
+    public void setBeanFactoryName(String beanFactoryName) {
+        this.beanFactoryName = beanFactoryName;
+    }
+
+    /**
+     * Sets the current ChildPropertySetter.<br>
+     * It will assign DefaultChildPropertySetter if null.<br>
+     * It accepts a ChildPropertySetter instance or a Closure.
+     */
+    public void setChildPropertySetter(final Object childPropertySetter) {
+        if (childPropertySetter instanceof ChildPropertySetter) {
+            this.childPropertySetter = (ChildPropertySetter) childPropertySetter;
+        } else if (childPropertySetter instanceof Closure) {
+            final ObjectGraphBuilder self = this;
+            this.childPropertySetter = new ChildPropertySetter() {
+                public void setChild(Object parent, Object child, String parentName,
+                                     String propertyName) {
+                    Closure cls = (Closure) childPropertySetter;
+                    cls.setDelegate(self);
+                    cls.call(new Object[]{parent, child, parentName, propertyName});
+                }
+            };
+        } else {
+            this.childPropertySetter = new DefaultChildPropertySetter();
+        }
+    }
+
+    /**
+     * Sets the classLoader used to load a node's class.
+     */
+    public void setClassLoader(ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Sets the current ClassNameResolver.<br>
+     * It will assign DefaultClassNameResolver if null.<br>
+     * It accepts a ClassNameResolver instance, a String, a Closure or a Map.
+     */
+    public void setClassNameResolver(final Object classNameResolver) {
+        if (classNameResolver instanceof ClassNameResolver) {
+            this.classNameResolver = (ClassNameResolver) classNameResolver;
+        } else if (classNameResolver instanceof String) {
+            this.classNameResolver = new ClassNameResolver() {
+                public String resolveClassname(String classname) {
+                    return makeClassName((String) classNameResolver, classname);
+                }
+            };
+        } else if (classNameResolver instanceof Closure) {
+            final ObjectGraphBuilder self = this;
+            this.classNameResolver = new ClassNameResolver() {
+                public String resolveClassname(String classname) {
+                    Closure cls = (Closure) classNameResolver;
+                    cls.setDelegate(self);
+                    return (String) cls.call(new Object[]{classname});
+                }
+            };
+        } else if (classNameResolver instanceof Map) {
+            Map classNameResolverOptions = (Map) classNameResolver;
+
+            String resolverName = (String) classNameResolverOptions.get(CLASSNAME_RESOLVER_KEY);
+
+            if (resolverName == null) {
+                throw new RuntimeException("key '" + CLASSNAME_RESOLVER_KEY + "' not defined");
+            }
+
+            if (CLASSNAME_RESOLVER_REFLECTION.equals(resolverName)) {
+                String root = (String) classNameResolverOptions.get(CLASSNAME_RESOLVER_REFLECTION_ROOT);
+
+                if (root == null) {
+                    throw new RuntimeException("key '" + CLASSNAME_RESOLVER_REFLECTION_ROOT + "' not defined");
+                }
+
+                this.classNameResolver = new ReflectionClassNameResolver(root);
+            } else {
+                throw new RuntimeException("unknown class name resolver " + resolverName);
+            }
+        } else {
+            this.classNameResolver = new DefaultClassNameResolver();
+        }
+    }
+
+    /**
+     * Sets the current IdentifierResolver.<br>
+     * It will assign DefaultIdentifierResolver if null.<br>
+     * It accepts a IdentifierResolver instance, a String or a Closure.
+     */
+    public void setIdentifierResolver(final Object identifierResolver) {
+        if (identifierResolver instanceof IdentifierResolver) {
+            this.identifierResolver = (IdentifierResolver) identifierResolver;
+        } else if (identifierResolver instanceof String) {
+            this.identifierResolver = new IdentifierResolver() {
+                public String getIdentifierFor(String nodeName) {
+                    return (String) identifierResolver;
+                }
+            };
+        } else if (identifierResolver instanceof Closure) {
+            final ObjectGraphBuilder self = this;
+            this.identifierResolver = new IdentifierResolver() {
+                public String getIdentifierFor(String nodeName) {
+                    Closure cls = (Closure) identifierResolver;
+                    cls.setDelegate(self);
+                    return (String) cls.call(new Object[]{nodeName});
+                }
+            };
+        } else {
+            this.identifierResolver = new DefaultIdentifierResolver();
+        }
+    }
+
+    /**
+     * Sets whether references can be resolved lazily or not.
+     */
+    public void setLazyReferencesAllowed(boolean lazyReferencesAllowed) {
+        this.lazyReferencesAllowed = lazyReferencesAllowed;
+    }
+
+    /**
+     * Sets the current NewInstanceResolver.<br>
+     * It will assign DefaultNewInstanceResolver if null.<br>
+     * It accepts a NewInstanceResolver instance or a Closure.
+     */
+    public void setNewInstanceResolver(final Object newInstanceResolver) {
+        if (newInstanceResolver instanceof NewInstanceResolver) {
+            this.newInstanceResolver = (NewInstanceResolver) newInstanceResolver;
+        } else if (newInstanceResolver instanceof Closure) {
+            final ObjectGraphBuilder self = this;
+            this.newInstanceResolver = new NewInstanceResolver() {
+                public Object newInstance(Class klass, Map attributes)
+                        throws InstantiationException, IllegalAccessException {
+                    Closure cls = (Closure) newInstanceResolver;
+                    cls.setDelegate(self);
+                    return cls.call(new Object[]{klass, attributes});
+                }
+            };
+        } else {
+            this.newInstanceResolver = new DefaultNewInstanceResolver();
+        }
+    }
+
+    /**
+     * Sets the current ReferenceResolver.<br>
+     * It will assign DefaultReferenceResolver if null.<br>
+     * It accepts a ReferenceResolver instance, a String or a Closure.
+     */
+    public void setReferenceResolver(final Object referenceResolver) {
+        if (referenceResolver instanceof ReferenceResolver) {
+            this.referenceResolver = (ReferenceResolver) referenceResolver;
+        } else if (referenceResolver instanceof String) {
+            this.referenceResolver = new ReferenceResolver() {
+                public String getReferenceFor(String nodeName) {
+                    return (String) referenceResolver;
+                }
+            };
+        } else if (referenceResolver instanceof Closure) {
+            final ObjectGraphBuilder self = this;
+            this.referenceResolver = new ReferenceResolver() {
+                public String getReferenceFor(String nodeName) {
+                    Closure cls = (Closure) referenceResolver;
+                    cls.setDelegate(self);
+                    return (String) cls.call(new Object[]{nodeName});
+                }
+            };
+        } else {
+            this.referenceResolver = new DefaultReferenceResolver();
+        }
+    }
+
+    /**
+     * Sets the current RelationNameResolver.<br>
+     * It will assign DefaultRelationNameResolver if null.
+     */
+    public void setRelationNameResolver(RelationNameResolver relationNameResolver) {
+        this.relationNameResolver = relationNameResolver != null ? relationNameResolver
+                : new DefaultRelationNameResolver();
+    }
+
+    protected void postInstantiate(Object name, Map attributes, Object node) {
+        super.postInstantiate(name, attributes, node);
+        Map context = getContext();
+        String objectId = (String) context.get(OBJECT_ID);
+        if (objectId != null && node != null) {
+            setVariable(objectId, node);
+        }
+    }
+
+    protected void preInstantiate(Object name, Map attributes, Object value) {
+        super.preInstantiate(name, attributes, value);
+        Map context = getContext();
+        context.put(OBJECT_ID,
+                attributes.remove(identifierResolver.getIdentifierFor((String) name)));
+    }
+
+    protected Factory resolveFactory(Object name, Map attributes, Object value) {
+        // let custom factories be resolved first
+        Factory factory = super.resolveFactory(name, attributes, value);
+        if (factory != null) {
+            return factory;
+        }
+        if (attributes.get(referenceResolver.getReferenceFor((String) name)) != null) {
+            return objectRefFactory;
+        }
+        if (beanFactoryName != null && beanFactoryName.equals((String) name)) {
+            return objectBeanFactory;
+        }
+        return objectFactory;
+    }
+
+    /**
+     * Strategy for setting a child node on its parent.<br>
+     * Useful for handling Lists/Arrays vs normal properties.
+     */
+    public interface ChildPropertySetter {
+        /**
+         * @param parent       the parent's node value
+         * @param child        the child's node value
+         * @param parentName   the name of the parent node
+         * @param propertyName the resolved relation name of the child
+         */
+        void setChild(Object parent, Object child, String parentName, String propertyName);
+    }
+
+    /**
+     * Strategy for resolving a classname.
+     */
+    public interface ClassNameResolver {
+        /**
+         * @param classname the node name as written on the building code
+         */
+        String resolveClassname(String classname);
+    }
+
+    /**
+     * Default impl that calls parent.propertyName = child<br>
+     * If parent.propertyName is a Collection it will try to add child to the
+     * collection.
+     */
+    public static class DefaultChildPropertySetter implements ChildPropertySetter {
+        public void setChild(Object parent, Object child, String parentName, String propertyName) {
+            try {
+                Object property = InvokerHelper.getProperty(parent, propertyName);
+                if (property != null && Collection.class.isAssignableFrom(property.getClass())) {
+                    ((Collection) property).add(child);
+                } else {
+                    InvokerHelper.setProperty(parent, propertyName, child);
+                }
+            } catch (MissingPropertyException mpe) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Default impl that capitalizes the classname.
+     */
+    public static class DefaultClassNameResolver implements ClassNameResolver {
+        public String resolveClassname(String classname) {
+            if (classname.length() == 1) {
+                return classname.toUpperCase();
+            }
+            return classname.substring(0, 1)
+                    .toUpperCase() + classname.substring(1);
+        }
+    }
+
+    /**
+     * Build objects using reflection to resolve class names.
+     */
+    public class ReflectionClassNameResolver implements ClassNameResolver {
+        private final String root;
+
+        /**
+         * @param root package where the graph root class is located
+         */
+        public ReflectionClassNameResolver(String root) {
+            this.root = root;
+        }
+
+        public String resolveClassname(String classname) {
+            Object currentNode = getContext().get(CURRENT_NODE);
+
+            if (currentNode == null) {
+                return makeClassName(root, classname);
+            } else {
+                try {
+                    Class klass = currentNode.getClass().getDeclaredField(classname).getType();
+
+                    if (Collection.class.isAssignableFrom(klass)) {
+                        Type type = currentNode.getClass().getDeclaredField(classname).getGenericType();
+                        if (type instanceof ParameterizedType) {
+                            ParameterizedType ptype = (ParameterizedType) type;
+                            Type[] actualTypeArguments = ptype.getActualTypeArguments();
+                            if (actualTypeArguments.length != 1) {
+                                throw new RuntimeException("can't determine class name for collection field " + classname + " with multiple generics");
+                            }
+
+                            Type typeArgument = actualTypeArguments[0];
+                            if (typeArgument instanceof Class) {
+                                klass = (Class) actualTypeArguments[0];
+                            } else {
+                                throw new RuntimeException("can't instantiate collection field " + classname + " elements as they aren't a class");
+                            }
+                        } else {
+                            throw new RuntimeException("collection field " + classname + " must be genericised");
+                        }
+                    }
+
+                    return klass.getName();
+                } catch (NoSuchFieldException e) {
+                    throw new RuntimeException("can't find field " + classname + " for node class " + currentNode.getClass().getName(), e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Default impl, always returns 'id'
+     */
+    public static class DefaultIdentifierResolver implements IdentifierResolver {
+        public String getIdentifierFor(String nodeName) {
+            return "id";
+        }
+    }
+
+    /**
+     * Default impl that calls Class.newInstance()
+     */
+    public static class DefaultNewInstanceResolver implements NewInstanceResolver {
+        public Object newInstance(Class klass, Map attributes) throws InstantiationException,
+                IllegalAccessException {
+            return klass.newInstance();
+        }
+    }
+
+    /**
+     * Default impl, always returns 'refId'
+     */
+    public static class DefaultReferenceResolver implements ReferenceResolver {
+        public String getReferenceFor(String nodeName) {
+            return "refId";
+        }
+    }
+
+    /**
+     * Default impl that returns parentName and childName accordingly.
+     */
+    public static class DefaultRelationNameResolver implements RelationNameResolver {
+        /**
+         * Handles the common English regular plurals with the following rules.
+         * <ul>
+         * <li>If childName ends in {consonant}y, replace 'y' with "ies". For example, allergy to allergies.</li>
+         * <li>Otherwise, append 's'. For example, monkey to monkeys; employee to employees.</li>
+         * </ul>
+         * If the property does not exist then it will return childName unchanged.
+         *
+         * @see <a href="http://en.wikipedia.org/wiki/English_plural">English_plural</a>
+         */
+        public String resolveChildRelationName(String parentName, Object parent, String childName,
+                                               Object child) {
+            boolean matchesIESRule = PLURAL_IES_PATTERN.matcher(childName).matches();
+            String childNamePlural = matchesIESRule ? childName.substring(0, childName.length() - 1) + "ies" : childName + "s";
+
+            MetaProperty metaProperty = InvokerHelper.getMetaClass(parent)
+                    .hasProperty(parent, childNamePlural);
+
+            return metaProperty != null ? childNamePlural : childName;
+        }
+
+        /**
+         * Follow the most conventional pattern, returns the parentName
+         * unchanged.
+         */
+        public String resolveParentRelationName(String parentName, Object parent,
+                                                String childName, Object child) {
+            return parentName;
+        }
+    }
+
+    /**
+     * Strategy for picking the correct synthetic identifier.
+     */
+    public interface IdentifierResolver {
+        /**
+         * Returns the name of the property that will identify the node.<br>
+         *
+         * @param nodeName the name of the node
+         */
+        String getIdentifierFor(String nodeName);
+    }
+
+    /**
+     * Strategy for creating new instances of a class.<br>
+     * Useful for plug-in calls to non-default constructors.
+     */
+    public interface NewInstanceResolver {
+        /**
+         * Create a new instance of Class klass.
+         *
+         * @param klass      the resolved class name
+         * @param attributes the attribute Map available for the node
+         */
+        Object newInstance(Class klass, Map attributes) throws InstantiationException,
+                IllegalAccessException;
+    }
+
+    /**
+     * Strategy for picking the correct synthetic reference identifier.
+     */
+    public interface ReferenceResolver {
+        /**
+         * Returns the name of the property that references another node.<br>
+         *
+         * @param nodeName the name of the node
+         */
+        String getReferenceFor(String nodeName);
+    }
+
+    /**
+     * Strategy for resolving a relationship property name.
+     */
+    public interface RelationNameResolver {
+        /**
+         * Returns the mapping name of child -&gt; parent
+         *
+         * @param parentName the name of the parent node
+         * @param parent     the parent node
+         * @param childName  the name of the child node
+         * @param child      the child node
+         */
+        String resolveChildRelationName(String parentName, Object parent, String childName,
+                                        Object child);
+
+        /**
+         * Returns the mapping name of parent -&gt; child
+         *
+         * @param parentName the name of the parent node
+         * @param parent     the parent node
+         * @param childName  the name of the child node
+         * @param child      the child node
+         */
+        String resolveParentRelationName(String parentName, Object parent, String childName,
+                                         Object child);
+    }
+
+    private void resolveLazyReferences() {
+        if (!lazyReferencesAllowed) return;
+        for (NodeReference ref : lazyReferences) {
+            if (ref.parent == null) continue;
+
+            Object child = null;
+            try {
+                child = getProperty(ref.refId);
+            } catch (MissingPropertyException mpe) {
+                // ignore
+            }
+            if (child == null) {
+                throw new IllegalArgumentException("There is no valid node for reference "
+                        + ref.parentName + "." + ref.childName + "=" + ref.refId);
+            }
+
+            // set child first
+            childPropertySetter.setChild(ref.parent, child, ref.parentName,
+                    relationNameResolver.resolveChildRelationName(ref.parentName,
+                            ref.parent, ref.childName, child));
+
+            // set parent afterwards
+            String propertyName = relationNameResolver.resolveParentRelationName(ref.parentName,
+                    ref.parent, ref.childName, child);
+            MetaProperty metaProperty = InvokerHelper.getMetaClass(child)
+                    .hasProperty(child, propertyName);
+            if (metaProperty != null) {
+                metaProperty.setProperty(child, ref.parent);
+            }
+        }
+    }
+
+    private static String makeClassName(String root, String name) {
+        return root + "." + name.substring(0, 1).toUpperCase() + name.substring(1);
+    }
+
+    private static class ObjectFactory extends AbstractFactory {
+        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
+                                  Map properties) throws InstantiationException, IllegalAccessException {
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            String classname = ogbuilder.classNameResolver.resolveClassname((String) name);
+            Class klass = resolveClass(builder, classname, name, value, properties);
+            Map context = builder.getContext();
+            context.put(ObjectGraphBuilder.NODE_NAME, name);
+            context.put(ObjectGraphBuilder.NODE_CLASS, klass);
+            return resolveInstance(builder, name, value, klass, properties);
+        }
+
+        protected Class resolveClass(FactoryBuilderSupport builder, String classname, Object name, Object value,
+                                  Map properties) {
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            Class klass = ogbuilder.resolvedClasses.get(classname);
+            if (klass == null) {
+                klass = loadClass(ogbuilder.classLoader, classname);
+                if (klass == null) {
+                    klass = loadClass(ogbuilder.getClass().getClassLoader(), classname);
+                }
+                if (klass == null) {
+                    try {
+                        klass = Class.forName(classname);
+                    } catch (ClassNotFoundException e) {
+                        // ignore
+                    }
+                }
+                if (klass == null) {
+                    klass = loadClass(Thread.currentThread().getContextClassLoader(), classname);
+                }
+                if (klass == null) {
+                    throw new RuntimeException(new ClassNotFoundException(classname));
+                }
+                ogbuilder.resolvedClasses.put(classname, klass);
+            }
+
+            return klass;
+        }
+
+        protected Object resolveInstance(FactoryBuilderSupport builder, Object name, Object value, Class klass,
+                                  Map properties) throws InstantiationException, IllegalAccessException {
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            if (value != null && klass.isAssignableFrom(value.getClass())) {
+                return value;
+            }
+
+            return ogbuilder.newInstanceResolver.newInstance(klass, properties);
+        }
+
+        public void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
+            if (child == null) return;
+
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            if (parent != null) {
+                Map context = ogbuilder.getContext();
+                Map parentContext = ogbuilder.getParentContext();
+
+                String parentName = null;
+                String childName = (String) context.get(NODE_NAME);
+                if (parentContext != null) {
+                    parentName = (String) parentContext.get(NODE_NAME);
+                }
+
+                String propertyName = ogbuilder.relationNameResolver.resolveParentRelationName(
+                        parentName, parent, childName, child);
+                MetaProperty metaProperty = InvokerHelper.getMetaClass(child)
+                        .hasProperty(child, propertyName);
+                if (metaProperty != null) {
+                    metaProperty.setProperty(child, parent);
+                }
+            }
+        }
+
+        public void setParent(FactoryBuilderSupport builder, Object parent, Object child) {
+            if (child == null) return;
+
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            if (parent != null) {
+                Map context = ogbuilder.getContext();
+                Map parentContext = ogbuilder.getParentContext();
+
+                String parentName = null;
+                String childName = (String) context.get(NODE_NAME);
+                if (parentContext != null) {
+                    parentName = (String) parentContext.get(NODE_NAME);
+                }
+
+                ogbuilder.childPropertySetter.setChild(parent, child, parentName,
+                        ogbuilder.relationNameResolver.resolveChildRelationName(parentName,
+                                parent, childName, child));
+            }
+        }
+
+        protected Class loadClass(ClassLoader classLoader, String classname) {
+            if (classLoader == null || classname == null) {
+                return null;
+            }
+            try {
+                return classLoader.loadClass(classname);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+    }
+
+    private static class ObjectBeanFactory extends ObjectFactory {
+        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
+                                  Map properties) throws InstantiationException, IllegalAccessException {
+            if(value == null) return super.newInstance(builder, name, value, properties);
+
+            Object bean = null;
+            Class klass = null;
+            Map context = builder.getContext();
+            if(value instanceof String || value instanceof GString) {
+                /*
+                String classname = value.toString();
+                klass = resolveClass(builder, classname, name, value, properties);
+                bean = resolveInstance(builder, name, value, klass, properties);
+                */
+                throw new IllegalArgumentException("ObjectGraphBuilder."+((ObjectGraphBuilder)builder).getBeanFactoryName()+"() does not accept String nor GString as value.");
+            } else if(value instanceof Class) {
+                klass = (Class) value;
+                bean = resolveInstance(builder, name, value, klass, properties);
+            } else {
+                klass = value.getClass();
+                bean = value;
+            }
+
+            String nodename = klass.getSimpleName();
+            if(nodename.length() > 1) {
+                nodename = nodename.substring(0, 1).toLowerCase() + nodename.substring(1);
+            } else {
+                nodename = nodename.toLowerCase();
+            }
+            context.put(ObjectGraphBuilder.NODE_NAME, nodename);
+            context.put(ObjectGraphBuilder.NODE_CLASS, klass);
+            return bean;
+        }
+    }
+
+    private static class ObjectRefFactory extends ObjectFactory {
+        public boolean isLeaf() {
+            return true;
+        }
+
+        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
+                                  Map properties) throws InstantiationException, IllegalAccessException {
+            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
+            String refProperty = ogbuilder.referenceResolver.getReferenceFor((String) name);
+            Object refId = properties.remove(refProperty);
+
+            Object object = null;
+            Boolean lazy = Boolean.FALSE;
+            if (refId instanceof String) {
+                try {
+                    object = ogbuilder.getProperty((String) refId);
+                } catch (MissingPropertyException mpe) {
+                    // ignore, will try lazy reference
+                }
+                if (object == null) {
+                    if (ogbuilder.isLazyReferencesAllowed()) {
+                        lazy = Boolean.TRUE;
+                    } else {
+                        throw new IllegalArgumentException("There is no previous node with "
+                                + ogbuilder.identifierResolver.getIdentifierFor((String) name) + "="
+                                + refId);
+                    }
+                }
+            } else {
+                // assume we got a true reference to the object
+                object = refId;
+            }
+
+            if (!properties.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "You can not modify the properties of a referenced object.");
+            }
+
+            Map context = ogbuilder.getContext();
+            context.put(ObjectGraphBuilder.NODE_NAME, name);
+            context.put(ObjectGraphBuilder.LAZY_REF, lazy);
+
+            if (lazy.booleanValue()) {
+                Map parentContext = ogbuilder.getParentContext();
+
+                Object parent = null;
+                String parentName = null;
+                String childName = (String) name;
+                if (parentContext != null) {
+                    parent = context.get(CURRENT_NODE);
+                    parentName = (String) parentContext.get(NODE_NAME);
+                }
+                ogbuilder.lazyReferences.add(new NodeReference(parent,
+                        parentName,
+                        childName,
+                        (String) refId));
+            } else {
+                context.put(ObjectGraphBuilder.NODE_CLASS, object.getClass());
+            }
+
+            return object;
+        }
+
+        public void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
+            Boolean lazy = (Boolean) builder.getContext().get(ObjectGraphBuilder.LAZY_REF);
+            if (!lazy.booleanValue()) super.setChild(builder, parent, child);
+        }
+
+        public void setParent(FactoryBuilderSupport builder, Object parent, Object child) {
+            Boolean lazy = (Boolean) builder.getContext().get(ObjectGraphBuilder.LAZY_REF);
+            if (!lazy.booleanValue()) super.setParent(builder, parent, child);
+        }
+    }
+
+    private static final class NodeReference {
+        private final Object parent;
+        private final String parentName;
+        private final String childName;
+        private final String refId;
+
+        private NodeReference(Object parent, String parentName, String childName, String refId) {
+            this.parent = parent;
+            this.parentName = parentName;
+            this.childName = childName;
+            this.refId = refId;
+        }
+
+        public String toString() {
+            return new StringBuilder().append("[parentName=").append(parentName)
+                    .append(", childName=").append(childName)
+                    .append(", refId=").append(refId)
+                    .append("]").toString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ObservableList.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ObservableList.java b/src/main/groovy/groovy/util/ObservableList.java
new file mode 100644
index 0000000..31b5745
--- /dev/null
+++ b/src/main/groovy/groovy/util/ObservableList.java
@@ -0,0 +1,570 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+/**
+ * List decorator that will trigger PropertyChangeEvents when a value changes.<br>
+ * An optional Closure may be specified and will work as a filter, if it returns true the property
+ * will trigger an event (if the value indeed changed), otherwise it won't. The Closure may receive
+ * 1 or 2 parameters, the single one being the value, the other one both the key and value, for
+ * example:
+ * <pre>
+ * // skip all properties whose value is a closure
+ * def map = new ObservableList( {!(it instanceof Closure)} )
+ *
+ * // skip all properties whose name matches a regex
+ * def map = new ObservableList( { name, value -&gt; !(name =&tilde; /[A-Z+]/) } )
+ * </pre>
+ * The current implementation will trigger specialized events in the following scenarios, you need
+ * not register a different listener as those events extend from PropertyChangeEvent
+ * <ul>
+ * <li>ObservableList.ElementAddedEvent - a new element is added to the list</li>
+ * <li>ObservableList.ElementRemovedEvent - an element is removed from the list</li>
+ * <li>ObservableList.ElementUpdatedEvent - an element changes value (same as regular
+ * PropertyChangeEvent)</li>
+ * <li>ObservableList.ElementClearedEvent - all elements have been removed from the list</li>
+ * <li>ObservableList.MultiElementAddedEvent - triggered by calling list.addAll()</li>
+ * <li>ObservableList.MultiElementRemovedEvent - triggered by calling
+ * list.removeAll()/list.retainAll()</li>
+ * </ul>
+ * <p>
+ * <strong>Bound properties</strong>
+ * <ul>
+ * <li><tt>content</tt> - read-only.</li>
+ * <li><tt>size</tt> - read-only.</li>
+ * </ul>
+ *
+ * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
+ */
+public class ObservableList implements List {
+    private final List delegate;
+    private final PropertyChangeSupport pcs;
+    private final Closure test;
+
+    public static final String SIZE_PROPERTY = "size";
+    public static final String CONTENT_PROPERTY = "content";
+
+    public ObservableList() {
+        this(new ArrayList(), null);
+    }
+
+    public ObservableList(List delegate) {
+        this(delegate, null);
+    }
+
+    public ObservableList(Closure test) {
+        this(new ArrayList(), test);
+    }
+
+    public ObservableList(List delegate, Closure test) {
+        this.delegate = delegate;
+        this.test = test;
+        pcs = new PropertyChangeSupport(this);
+    }
+
+    public List getContent() {
+        return Collections.unmodifiableList(delegate);
+    }
+
+    protected List getDelegateList() {
+        return delegate;
+    }
+
+    protected Closure getTest() {
+        return test;
+    }
+
+    protected void fireElementAddedEvent(int index, Object element) {
+        fireElementEvent(new ElementAddedEvent(this, element, index));
+    }
+
+    protected void fireMultiElementAddedEvent(int index, List values) {
+        fireElementEvent(new MultiElementAddedEvent(this, index, values));
+    }
+
+    protected void fireElementClearedEvent(List values) {
+        fireElementEvent(new ElementClearedEvent(this, values));
+    }
+
+    protected void fireElementRemovedEvent(int index, Object element) {
+        fireElementEvent(new ElementRemovedEvent(this, element, index));
+    }
+
+    protected void fireMultiElementRemovedEvent(List values) {
+        fireElementEvent(new MultiElementRemovedEvent(this, values));
+    }
+
+    protected void fireElementUpdatedEvent(int index, Object oldValue, Object newValue) {
+        fireElementEvent(new ElementUpdatedEvent(this, oldValue, newValue, index));
+    }
+
+    protected void fireElementEvent(ElementEvent event) {
+        pcs.firePropertyChange(event);
+    }
+
+    protected void fireSizeChangedEvent(int oldValue, int newValue) {
+        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
+    }
+
+    public void add(int index, Object element) {
+        int oldSize = size();
+        delegate.add(index, element);
+        fireAddWithTest(element, index, oldSize);
+    }
+
+    public boolean add(Object o) {
+        int oldSize = size();
+        boolean success = delegate.add(o);
+        if (success) {
+            fireAddWithTest(o, oldSize, oldSize);
+        }
+        return success;
+    }
+
+    private void fireAddWithTest(Object element, int index, int oldSize) {
+        if (test != null) {
+            Object result = test.call(element);
+            if (result != null && result instanceof Boolean && (Boolean) result) {
+                fireElementAddedEvent(index, element);
+                fireSizeChangedEvent(oldSize, size());
+            }
+        } else {
+            fireElementAddedEvent(index, element);
+            fireSizeChangedEvent(oldSize, size());
+        }
+    }
+
+    public boolean addAll(Collection c) {
+        return addAll(size(), c);
+    }
+
+    public boolean addAll(int index, Collection c) {
+        int oldSize = size();
+        boolean success = delegate.addAll(index, c);
+
+        if (success && c != null) {
+            List values = new ArrayList();
+            for (Object element : c) {
+                if (test != null) {
+                    Object result = test.call(element);
+                    if (result != null && result instanceof Boolean && (Boolean) result) {
+                        values.add(element);
+                    }
+                } else {
+                    values.add(element);
+                }
+            }
+            if (!values.isEmpty()) {
+                fireMultiElementAddedEvent(index, values);
+                fireSizeChangedEvent(oldSize, size());
+            }
+        }
+
+        return success;
+    }
+
+    public void clear() {
+        int oldSize = size();
+        List values = new ArrayList();
+        values.addAll(delegate);
+        delegate.clear();
+        if (!values.isEmpty()) {
+            fireElementClearedEvent(values);
+        }
+        fireSizeChangedEvent(oldSize, size());
+    }
+
+    public boolean contains(Object o) {
+        return delegate.contains(o);
+    }
+
+    public boolean containsAll(Collection c) {
+        return delegate.containsAll(c);
+    }
+
+    public boolean equals(Object o) {
+        return delegate.equals(o);
+    }
+
+    public Object get(int index) {
+        return delegate.get(index);
+    }
+
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    public int indexOf(Object o) {
+        return delegate.indexOf(o);
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public Iterator iterator() {
+        return new ObservableIterator(delegate.iterator());
+    }
+
+    public int lastIndexOf(Object o) {
+        return delegate.lastIndexOf(o);
+    }
+
+    public ListIterator listIterator() {
+        return new ObservableListIterator(delegate.listIterator(), 0);
+    }
+
+    public ListIterator listIterator(int index) {
+        return new ObservableListIterator(delegate.listIterator(index), index);
+    }
+
+    public Object remove(int index) {
+        int oldSize = size();
+        Object element = delegate.remove(index);
+        fireElementRemovedEvent(index, element);
+        fireSizeChangedEvent(oldSize, size());
+        return element;
+    }
+
+    public boolean remove(Object o) {
+        int oldSize = size();
+        int index = delegate.indexOf(o);
+        boolean success = delegate.remove(o);
+        if (success) {
+            fireElementRemovedEvent(index, o);
+            fireSizeChangedEvent(oldSize, size());
+        }
+        return success;
+    }
+
+    public boolean removeAll(Collection c) {
+        if (c == null) {
+            return false;
+        }
+
+        List values = new ArrayList();
+        // GROOVY-7783 use Sets for O(1) performance for contains
+        Set delegateSet = new HashSet<Object>(delegate);
+        if (!(c instanceof Set)) {
+            c = new HashSet<Object>(c);
+        }
+        for (Object element : c) {
+            if (delegateSet.contains(element)) {
+                values.add(element);
+            }
+        }
+
+        int oldSize = size();
+        boolean success = delegate.removeAll(c);
+        if (success && !values.isEmpty()) {
+            fireMultiElementRemovedEvent(values);
+            fireSizeChangedEvent(oldSize, size());
+        }
+
+        return success;
+    }
+
+    public boolean retainAll(Collection c) {
+        if (c == null) {
+            return false;
+        }
+
+        List values = new ArrayList();
+        // GROOVY-7783 use Set for O(1) performance for contains
+        if (!(c instanceof Set)) {
+            c = new HashSet<Object>(c);
+        }
+        for (Object element : delegate) {
+            if (!c.contains(element)) {
+                values.add(element);
+            }
+        }
+
+        int oldSize = size();
+        boolean success = delegate.retainAll(c);
+        if (success && !values.isEmpty()) {
+            fireMultiElementRemovedEvent(values);
+            fireSizeChangedEvent(oldSize, size());
+        }
+
+        return success;
+    }
+
+    public Object set(int index, Object element) {
+        Object oldValue = delegate.set(index, element);
+        if (test != null) {
+            Object result = test.call(element);
+            if (result != null && result instanceof Boolean && ((Boolean) result).booleanValue()) {
+                fireElementUpdatedEvent(index, oldValue, element);
+            }
+        } else {
+            fireElementUpdatedEvent(index, oldValue, element);
+        }
+        return oldValue;
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public int getSize() {
+        return size();
+    }
+
+    public List subList(int fromIndex, int toIndex) {
+        return delegate.subList(fromIndex, toIndex);
+    }
+
+    public Object[] toArray() {
+        return delegate.toArray();
+    }
+
+    public Object[] toArray(Object[] a) {
+        return delegate.toArray(a);
+    }
+
+    protected class ObservableIterator implements Iterator {
+        private final Iterator iterDelegate;
+        protected int cursor = -1 ;
+
+        public ObservableIterator(Iterator iterDelegate) {
+            this.iterDelegate = iterDelegate;
+        }
+
+        public Iterator getDelegate() {
+            return iterDelegate;
+        }
+
+        public boolean hasNext() {
+            return iterDelegate.hasNext();
+        }
+
+        public Object next() {
+            cursor++;
+            return iterDelegate.next();
+        }
+
+        public void remove() {
+            int oldSize = ObservableList.this.size();
+            Object element = ObservableList.this.get(cursor);
+            iterDelegate.remove();
+            fireElementRemovedEvent(cursor, element);
+            fireSizeChangedEvent(oldSize, size());
+            cursor--;
+        }
+    }
+
+    protected class ObservableListIterator extends ObservableIterator implements ListIterator {
+        public ObservableListIterator(ListIterator iterDelegate, int index) {
+            super(iterDelegate);
+            cursor = index - 1;
+        }
+
+        public ListIterator getListIterator() {
+            return (ListIterator) getDelegate();
+        }
+
+        public void add(Object o) {
+            ObservableList.this.add(o);
+            cursor++;
+        }
+
+        public boolean hasPrevious() {
+            return getListIterator().hasPrevious();
+        }
+
+        public int nextIndex() {
+            return getListIterator().nextIndex();
+        }
+
+        public Object previous() {
+            return getListIterator().previous();
+        }
+
+        public int previousIndex() {
+            return getListIterator().previousIndex();
+        }
+
+        public void set(Object o) {
+            ObservableList.this.set(cursor, o);
+        }
+    }
+
+    // observable interface
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(listener);
+    }
+
+    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(propertyName, listener);
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners() {
+        return pcs.getPropertyChangeListeners();
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
+        return pcs.getPropertyChangeListeners(propertyName);
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(listener);
+    }
+
+    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(propertyName, listener);
+    }
+
+    public boolean hasListeners(String propertyName) {
+        return pcs.hasListeners(propertyName);
+    }
+
+    public enum ChangeType {
+        ADDED, UPDATED, REMOVED, CLEARED, MULTI_ADD, MULTI_REMOVE, NONE;
+
+        public static final Object oldValue = new Object();
+        public static final Object newValue = new Object();
+
+        public static ChangeType resolve(int ordinal) {
+            switch (ordinal) {
+                case 0:
+                    return ADDED;
+                case 2:
+                    return REMOVED;
+                case 3:
+                    return CLEARED;
+                case 4:
+                    return MULTI_ADD;
+                case 5:
+                    return MULTI_REMOVE;
+                case 6:
+                    return NONE;
+                case 1:
+                default:
+                    return UPDATED;
+            }
+        }
+    }
+
+    public abstract static class ElementEvent extends PropertyChangeEvent {
+
+        private final ChangeType type;
+        private final int index;
+
+        public ElementEvent(Object source, Object oldValue, Object newValue, int index, ChangeType type) {
+            super(source, ObservableList.CONTENT_PROPERTY, oldValue, newValue);
+            this.type = type;
+            this.index = index;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public int getType() {
+            return type.ordinal();
+        }
+
+        public ChangeType getChangeType() {
+            return type;
+        }
+
+        public String getTypeAsString() {
+            return type.name().toUpperCase();
+        }
+    }
+
+    public static class ElementAddedEvent extends ElementEvent {
+        public ElementAddedEvent(Object source, Object newValue, int index) {
+            super(source, null, newValue, index, ChangeType.ADDED);
+        }
+    }
+
+    public static class ElementUpdatedEvent extends ElementEvent {
+        public ElementUpdatedEvent(Object source, Object oldValue, Object newValue, int index) {
+            super(source, oldValue, newValue, index, ChangeType.UPDATED);
+        }
+    }
+
+    public static class ElementRemovedEvent extends ElementEvent {
+        public ElementRemovedEvent(Object source, Object value, int index) {
+            super(source, value, null, index, ChangeType.REMOVED);
+        }
+    }
+
+    public static class ElementClearedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public ElementClearedEvent(Object source, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, 0, ChangeType.CLEARED);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+
+    public static class MultiElementAddedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public MultiElementAddedEvent(Object source, int index, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, index, ChangeType.MULTI_ADD);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+
+    public static class MultiElementRemovedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public MultiElementRemovedEvent(Object source, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, 0, ChangeType.MULTI_REMOVE);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ObservableMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ObservableMap.java b/src/main/groovy/groovy/util/ObservableMap.java
new file mode 100644
index 0000000..94b9816
--- /dev/null
+++ b/src/main/groovy/groovy/util/ObservableMap.java
@@ -0,0 +1,410 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Map decorator that will trigger PropertyChangeEvents when a value changes.<br>
+ * An optional Closure may be specified and will work as a filter, if it returns
+ * true the property will trigger an event (if the value indeed changed),
+ * otherwise it won't. The Closure may receive 1 or 2 parameters, the single one
+ * being the value, the other one both the key and value, for example:
+ * <pre>
+ * // skip all properties whose value is a closure
+ * def map = new ObservableMap( {!(it instanceof Closure)} )
+ *
+ * // skip all properties whose name matches a regex
+ * def map = new ObservableMap( { name, value -&gt; !(name =~ /[A-Z+]/) } )
+ * </pre>
+ * The current implementation will trigger specialized events in the following scenarios,
+ * you need not register a different listener as those events extend from PropertyChangeEvent
+ * <ul>
+ * <li>ObservableMap.PropertyAddedEvent - a new property is added to the map</li>
+ * <li>ObservableMap.PropertyRemovedEvent - a property is removed from the map</li>
+ * <li>ObservableMap.PropertyUpdatedEvent - a property changes value (same as regular PropertyChangeEvent)</li>
+ * <li>ObservableMap.PropertyClearedEvent - all properties have been removed from the map</li>
+ * <li>ObservableMap.MultiPropertyEvent - triggered by calling map.putAll(), contains Added|Updated events</li>
+ * </ul>
+ * <p>
+ * <strong>Bound properties</strong>
+ * <ul>
+ * <li><tt>content</tt> - read-only.</li>
+ * <li><tt>size</tt> - read-only.</li>
+ * </ul>
+ *
+ * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
+ */
+public class ObservableMap implements Map {
+    private final Map delegate;
+    private final PropertyChangeSupport pcs;
+    private final Closure test;
+
+    public static final String SIZE_PROPERTY = "size";
+    public static final String CONTENT_PROPERTY = "content";
+    public static final String CLEARED_PROPERTY = "cleared";
+
+    public ObservableMap() {
+        this(new LinkedHashMap(), null);
+    }
+
+    public ObservableMap(Closure test) {
+        this(new LinkedHashMap(), test);
+    }
+
+    public ObservableMap(Map delegate) {
+        this(delegate, null);
+    }
+
+    public ObservableMap(Map delegate, Closure test) {
+        this.delegate = delegate;
+        this.test = test;
+        pcs = new PropertyChangeSupport(this);
+    }
+
+    protected Map getMapDelegate() {
+        return delegate;
+    }
+
+    protected Closure getTest() {
+        return test;
+    }
+
+    public Map getContent() {
+        return Collections.unmodifiableMap(delegate);
+    }
+
+    protected void firePropertyClearedEvent(Map values) {
+        firePropertyEvent(new PropertyClearedEvent(this, values));
+    }
+
+    protected void firePropertyAddedEvent(Object key, Object value) {
+        firePropertyEvent(new PropertyAddedEvent(this, String.valueOf(key), value));
+    }
+
+    protected void firePropertyUpdatedEvent(Object key, Object oldValue, Object newValue) {
+        firePropertyEvent(new PropertyUpdatedEvent(this, String.valueOf(key), oldValue, newValue));
+    }
+
+    protected void fireMultiPropertyEvent(List<PropertyEvent> events) {
+        firePropertyEvent(new MultiPropertyEvent(this, (PropertyEvent[]) events.toArray(new PropertyEvent[events.size()])));
+    }
+
+    protected void fireMultiPropertyEvent(PropertyEvent[] events) {
+        firePropertyEvent(new MultiPropertyEvent(this, events));
+    }
+
+    protected void firePropertyRemovedEvent(Object key, Object value) {
+        firePropertyEvent(new PropertyRemovedEvent(this, String.valueOf(key), value));
+    }
+
+    protected void firePropertyEvent(PropertyEvent event) {
+        pcs.firePropertyChange(event);
+    }
+
+    protected void fireSizeChangedEvent(int oldValue, int newValue) {
+        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
+    }
+
+    // Map interface
+
+    public void clear() {
+        int oldSize = size();
+        Map values = new HashMap();
+        if (!delegate.isEmpty()) {
+            values.putAll(delegate);
+        }
+        delegate.clear();
+        firePropertyClearedEvent(values);
+        fireSizeChangedEvent(oldSize, size());
+    }
+
+    public boolean containsKey(Object key) {
+        return delegate.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return delegate.containsValue(value);
+    }
+
+    public Set entrySet() {
+        return delegate.entrySet();
+    }
+
+    public boolean equals(Object o) {
+        return delegate.equals(o);
+    }
+
+    public Object get(Object key) {
+        return delegate.get(key);
+    }
+
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public Set keySet() {
+        return delegate.keySet();
+    }
+
+    public Object put(Object key, Object value) {
+        int oldSize = size();
+        Object oldValue = null;
+        boolean newKey = !delegate.containsKey(key);
+        if (test != null) {
+            oldValue = delegate.put(key, value);
+            Object result = null;
+            if (test.getMaximumNumberOfParameters() == 2) {
+                result = test.call(new Object[]{key, value});
+            } else {
+                result = test.call(value);
+            }
+            if (result != null && result instanceof Boolean && (Boolean) result) {
+                if (newKey) {
+                    firePropertyAddedEvent(key, value);
+                    fireSizeChangedEvent(oldSize, size());
+                } else if (oldValue != value) {
+                    firePropertyUpdatedEvent(key, oldValue, value);
+                }
+            }
+        } else {
+            oldValue = delegate.put(key, value);
+            if (newKey) {
+                firePropertyAddedEvent(key, value);
+                fireSizeChangedEvent(oldSize, size());
+            } else if (oldValue != value) {
+                firePropertyUpdatedEvent(key, oldValue, value);
+            }
+        }
+        return oldValue;
+    }
+
+    public void putAll(Map map) {
+        int oldSize = size();
+        if (map != null) {
+            List<PropertyEvent> events = new ArrayList<PropertyEvent>();
+            for (Object o : map.entrySet()) {
+                Entry entry = (Entry) o;
+
+                String key = String.valueOf(entry.getKey());
+                Object newValue = entry.getValue();
+                Object oldValue = null;
+
+                boolean newKey = !delegate.containsKey(key);
+                if (test != null) {
+                    oldValue = delegate.put(key, newValue);
+                    Object result = null;
+                    if (test.getMaximumNumberOfParameters() == 2) {
+                        result = test.call(new Object[]{key, newValue});
+                    } else {
+                        result = test.call(newValue);
+                    }
+                    if (result != null && result instanceof Boolean && (Boolean) result) {
+                        if (newKey) {
+                            events.add(new PropertyAddedEvent(this, key, newValue));
+                        } else if (oldValue != newValue) {
+                            events.add(new PropertyUpdatedEvent(this, key, oldValue, newValue));
+                        }
+                    }
+                } else {
+                    oldValue = delegate.put(key, newValue);
+                    if (newKey) {
+                        events.add(new PropertyAddedEvent(this, key, newValue));
+                    } else if (oldValue != newValue) {
+                        events.add(new PropertyUpdatedEvent(this, key, oldValue, newValue));
+                    }
+                }
+            }
+            if (!events.isEmpty()) {
+                fireMultiPropertyEvent(events);
+                fireSizeChangedEvent(oldSize, size());
+            }
+        }
+    }
+
+    public Object remove(Object key) {
+        int oldSize = size();
+        Object result = delegate.remove(key);
+        if (key != null) {
+            firePropertyRemovedEvent(key, result);
+            fireSizeChangedEvent(oldSize, size());
+        }
+        return result;
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public int getSize() {
+        return size();
+    }
+
+    public Collection values() {
+        return delegate.values();
+    }
+
+    // observable interface
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(listener);
+    }
+
+    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(propertyName, listener);
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners() {
+        return pcs.getPropertyChangeListeners();
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
+        return pcs.getPropertyChangeListeners(propertyName);
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(listener);
+    }
+
+    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(propertyName, listener);
+    }
+
+    public boolean hasListeners(String propertyName) {
+        return pcs.hasListeners(propertyName);
+    }
+
+    public enum ChangeType {
+        ADDED, UPDATED, REMOVED, CLEARED, MULTI, NONE;
+
+        public static final Object oldValue = new Object();
+        public static final Object newValue = new Object();
+
+        public static ChangeType resolve(int ordinal) {
+            switch (ordinal) {
+                case 0:
+                    return ADDED;
+                case 2:
+                    return REMOVED;
+                case 3:
+                    return CLEARED;
+                case 4:
+                    return MULTI;
+                case 5:
+                    return NONE;
+                case 1:
+                default:
+                    return UPDATED;
+            }
+        }
+    }
+
+    public abstract static class PropertyEvent extends PropertyChangeEvent {
+        private final ChangeType type;
+
+        public PropertyEvent(Object source, String propertyName, Object oldValue, Object newValue, ChangeType type) {
+            super(source, propertyName, oldValue, newValue);
+            this.type = type;
+        }
+
+        public int getType() {
+            return type.ordinal();
+        }
+
+        public ChangeType getChangeType() {
+            return type;
+        }
+
+        public String getTypeAsString() {
+            return type.name().toUpperCase();
+        }
+    }
+
+    public static class PropertyAddedEvent extends PropertyEvent {
+        public PropertyAddedEvent(Object source, String propertyName, Object newValue) {
+            super(source, propertyName, null, newValue, ChangeType.ADDED);
+        }
+    }
+
+    public static class PropertyUpdatedEvent extends PropertyEvent {
+        public PropertyUpdatedEvent(Object source, String propertyName, Object oldValue, Object newValue) {
+            super(source, propertyName, oldValue, newValue, ChangeType.UPDATED);
+        }
+    }
+
+    public static class PropertyRemovedEvent extends PropertyEvent {
+        public PropertyRemovedEvent(Object source, String propertyName, Object oldValue) {
+            super(source, propertyName, oldValue, null, ChangeType.REMOVED);
+        }
+    }
+
+    public static class PropertyClearedEvent extends PropertyEvent {
+        private final Map values = new HashMap();
+
+        public PropertyClearedEvent(Object source, Map values) {
+            super(source, ObservableMap.CLEARED_PROPERTY, values, null, ChangeType.CLEARED);
+            if (values != null) {
+                this.values.putAll(values);
+            }
+        }
+
+        public Map getValues() {
+            return Collections.unmodifiableMap(values);
+        }
+    }
+
+    public static class MultiPropertyEvent extends PropertyEvent {
+        public static final String MULTI_PROPERTY = "groovy_util_ObservableMap_MultiPropertyEvent_MULTI";
+        private static final PropertyEvent[] EMPTY_PROPERTY_EVENTS = new PropertyEvent[0];
+
+        private final PropertyEvent[] events;
+
+        public MultiPropertyEvent(Object source, PropertyEvent[] events) {
+            super(source, MULTI_PROPERTY, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI);
+            if (events != null && events.length > 0) {
+                this.events = new PropertyEvent[events.length];
+                System.arraycopy(events, 0, this.events, 0, events.length);
+            } else {
+            	this.events = EMPTY_PROPERTY_EVENTS;
+            }
+        }
+
+        public PropertyEvent[] getEvents() {
+            PropertyEvent[] copy = new PropertyEvent[events.length];
+            System.arraycopy(events, 0, copy, 0, events.length);
+            return copy;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ObservableSet.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ObservableSet.java b/src/main/groovy/groovy/util/ObservableSet.java
new file mode 100644
index 0000000..b794436
--- /dev/null
+++ b/src/main/groovy/groovy/util/ObservableSet.java
@@ -0,0 +1,427 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+
+/**
+ * Set decorator that will trigger PropertyChangeEvents when a value changes.<br>
+ * An optional Closure may be specified and will work as a filter, if it returns true the property
+ * will trigger an event (if the value indeed changed), otherwise it won't. The Closure may receive
+ * 1 or 2 parameters, the single one being the value, the other one both the key and value, for
+ * example:
+ * <pre>
+ * // skip all properties whose value is a closure
+ * def set = new ObservableSet( {!(it instanceof Closure)} )
+ * &lt;p/&gt;
+ * // skip all properties whose name matches a regex
+ * def set = new ObservableSet( { name, value -&gt; !(name =&tilde; /[A-Z+]/) } )
+ * </pre>
+ * The current implementation will trigger specialized events in the following scenarios, you need
+ * not register a different listener as those events extend from PropertyChangeEvent
+ * <ul>
+ * <li>ObservableSet.ElementAddedEvent - a new element is added to the set</li>
+ * <li>ObservableSet.ElementRemovedEvent - an element is removed from the set</li>
+ * <li>ObservableSet.ElementUpdatedEvent - an element changes value (same as regular
+ * PropertyChangeEvent)</li>
+ * <li>ObservableSet.ElementClearedEvent - all elements have been removed from the list</li>
+ * <li>ObservableSet.MultiElementAddedEvent - triggered by calling set.addAll()</li>
+ * <li>ObservableSet.MultiElementRemovedEvent - triggered by calling
+ * set.removeAll()/set.retainAll()</li>
+ * </ul>
+ *
+ * <p>
+ * <strong>Bound properties</strong>
+ * <ul>
+ * <li><tt>content</tt> - read-only.</li>
+ * <li><tt>size</tt> - read-only.</li>
+ * </ul>
+ *
+ * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
+ */
+public class ObservableSet<E> implements Set<E> {
+    private final Set<E> delegate;
+    private final PropertyChangeSupport pcs;
+    private final Closure test;
+
+    public static final String SIZE_PROPERTY = "size";
+    public static final String CONTENT_PROPERTY = "content";
+
+    public ObservableSet() {
+        this(new HashSet<E>(), null);
+    }
+
+    public ObservableSet(Set<E> delegate) {
+        this(delegate, null);
+    }
+
+    public ObservableSet(Closure test) {
+        this(new HashSet<E>(), test);
+    }
+
+    public ObservableSet(Set<E> delegate, Closure test) {
+        this.delegate = delegate;
+        this.test = test;
+        this.pcs = new PropertyChangeSupport(this);
+    }
+
+    public Set<E> getContent() {
+        return Collections.unmodifiableSet(delegate);
+    }
+
+    protected Set<E> getDelegateSet() {
+        return delegate;
+    }
+
+    protected Closure getTest() {
+        return test;
+    }
+
+    protected void fireElementAddedEvent(Object element) {
+        fireElementEvent(new ElementAddedEvent(this, element));
+    }
+
+    protected void fireMultiElementAddedEvent(List values) {
+        fireElementEvent(new MultiElementAddedEvent(this, values));
+    }
+
+    protected void fireElementClearedEvent(List values) {
+        fireElementEvent(new ElementClearedEvent(this, values));
+    }
+
+    protected void fireElementRemovedEvent(Object element) {
+        fireElementEvent(new ElementRemovedEvent(this, element));
+    }
+
+    protected void fireMultiElementRemovedEvent(List values) {
+        fireElementEvent(new MultiElementRemovedEvent(this, values));
+    }
+
+    protected void fireElementEvent(ElementEvent event) {
+        pcs.firePropertyChange(event);
+    }
+
+    protected void fireSizeChangedEvent(int oldValue, int newValue) {
+        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
+    }
+
+    // observable interface
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(listener);
+    }
+
+    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.addPropertyChangeListener(propertyName, listener);
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners() {
+        return pcs.getPropertyChangeListeners();
+    }
+
+    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
+        return pcs.getPropertyChangeListeners(propertyName);
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(listener);
+    }
+
+    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        pcs.removePropertyChangeListener(propertyName, listener);
+    }
+
+    public boolean hasListeners(String propertyName) {
+        return pcs.hasListeners(propertyName);
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public boolean contains(Object o) {
+        return delegate.contains(o);
+    }
+
+    public Iterator<E> iterator() {
+        return new ObservableIterator<E>(delegate.iterator());
+    }
+
+    public Object[] toArray() {
+        return delegate.toArray();
+    }
+
+    public <T> T[] toArray(T[] ts) {
+        return (T[]) delegate.toArray(ts);
+    }
+
+    public boolean add(E e) {
+        int oldSize = size();
+        boolean success = delegate.add(e);
+        if (success) {
+            if (test != null) {
+                Object result = test.call(e);
+                if (result != null && result instanceof Boolean && (Boolean) result) {
+                    fireElementAddedEvent(e);
+                    fireSizeChangedEvent(oldSize, size());
+                }
+            } else {
+                fireElementAddedEvent(e);
+                fireSizeChangedEvent(oldSize, size());
+            }
+        }
+        return success;
+    }
+
+    public boolean remove(Object o) {
+        int oldSize = size();
+        boolean success = delegate.remove(o);
+        if (success) {
+            fireElementRemovedEvent(o);
+            fireSizeChangedEvent(oldSize, size());
+        }
+        return success;
+    }
+
+    public boolean containsAll(Collection<?> objects) {
+        return delegate.containsAll(objects);
+    }
+
+    public boolean addAll(Collection<? extends E> c) {
+        Set<E> duplicates = new HashSet<E>();
+        if (null != c) {
+            for (E e : c) {
+                if (!delegate.contains(e)) continue;
+                duplicates.add(e);
+            }
+        }
+
+        int oldSize = size();
+        boolean success = delegate.addAll(c);
+
+        if (success && c != null) {
+            List<E> values = new ArrayList<E>();
+            for (E element : c) {
+                if (test != null) {
+                    Object result = test.call(element);
+                    if (result != null && result instanceof Boolean && (Boolean) result && !duplicates.contains(element)) {
+                        values.add(element);
+                    }
+                } else if (!duplicates.contains(element)) {
+                    values.add(element);
+                }
+            }
+            if (!values.isEmpty()) {
+                fireMultiElementAddedEvent(values);
+                fireSizeChangedEvent(oldSize, size());
+            }
+        }
+
+        return success;
+    }
+
+    public boolean retainAll(Collection<?> c) {
+        if (c == null) {
+            return false;
+        }
+
+        List values = new ArrayList();
+        // GROOVY-7822 use Set for O(1) performance for contains
+        if (!(c instanceof Set)) {
+            c = new HashSet<Object>(c);
+        }
+        for (Object element : delegate) {
+            if (!c.contains(element)) {
+                values.add(element);
+            }
+        }
+
+        int oldSize = size();
+        boolean success = delegate.retainAll(c);
+        if (success && !values.isEmpty()) {
+            fireMultiElementRemovedEvent(values);
+            fireSizeChangedEvent(oldSize, size());
+        }
+
+        return success;
+    }
+
+    public boolean removeAll(Collection<?> c) {
+        if (c == null) {
+            return false;
+        }
+
+        List values = new ArrayList();
+        for (Object element : c) {
+            if (delegate.contains(element)) {
+                values.add(element);
+            }
+        }
+
+        int oldSize = size();
+        boolean success = delegate.removeAll(c);
+        if (success && !values.isEmpty()) {
+            fireMultiElementRemovedEvent(values);
+            fireSizeChangedEvent(oldSize, size());
+        }
+
+        return success;
+    }
+
+    public void clear() {
+        int oldSize = size();
+        List<E> values = new ArrayList<E>();
+        values.addAll(delegate);
+        delegate.clear();
+        if (!values.isEmpty()) {
+            fireElementClearedEvent(values);
+        }
+        fireSizeChangedEvent(oldSize, size());
+    }
+
+    protected class ObservableIterator<E> implements Iterator<E> {
+        private final Iterator<E> iterDelegate;
+        private final Stack<E> stack = new Stack<E>();
+
+        public ObservableIterator(Iterator<E> iterDelegate) {
+            this.iterDelegate = iterDelegate;
+        }
+
+        public Iterator<E> getDelegate() {
+            return iterDelegate;
+        }
+
+        public boolean hasNext() {
+            return iterDelegate.hasNext();
+        }
+
+        public E next() {
+            stack.push(iterDelegate.next());
+            return stack.peek();
+        }
+
+        public void remove() {
+            int oldSize = ObservableSet.this.size();
+            iterDelegate.remove();
+            fireElementRemovedEvent(stack.pop());
+            fireSizeChangedEvent(oldSize, size());
+        }
+    }
+
+    public enum ChangeType {
+        ADDED, REMOVED, CLEARED, MULTI_ADD, MULTI_REMOVE, NONE;
+
+        public static final Object oldValue = new Object();
+        public static final Object newValue = new Object();
+    }
+
+    public abstract static class ElementEvent extends PropertyChangeEvent {
+        private final ChangeType type;
+
+        public ElementEvent(Object source, Object oldValue, Object newValue, ChangeType type) {
+            super(source, ObservableSet.CONTENT_PROPERTY, oldValue, newValue);
+            this.type = type;
+        }
+
+        public int getType() {
+            return type.ordinal();
+        }
+
+        public ChangeType getChangeType() {
+            return type;
+        }
+
+        public String getTypeAsString() {
+            return type.name().toUpperCase();
+        }
+    }
+
+    public static class ElementAddedEvent extends ElementEvent {
+        public ElementAddedEvent(Object source, Object newValue) {
+            super(source, null, newValue, ChangeType.ADDED);
+        }
+    }
+
+    public static class ElementRemovedEvent extends ElementEvent {
+        public ElementRemovedEvent(Object source, Object value) {
+            super(source, value, null, ChangeType.REMOVED);
+        }
+    }
+
+    public static class ElementClearedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public ElementClearedEvent(Object source, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.CLEARED);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+
+    public static class MultiElementAddedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public MultiElementAddedEvent(Object source, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI_ADD);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+
+    public static class MultiElementRemovedEvent extends ElementEvent {
+        private final List values = new ArrayList();
+
+        public MultiElementRemovedEvent(Object source, List values) {
+            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI_REMOVE);
+            if (values != null) {
+                this.values.addAll(values);
+            }
+        }
+
+        public List getValues() {
+            return Collections.unmodifiableList(values);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/OrderBy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/OrderBy.java b/src/main/groovy/groovy/util/OrderBy.java
new file mode 100644
index 0000000..703c9bc
--- /dev/null
+++ b/src/main/groovy/groovy/util/OrderBy.java
@@ -0,0 +1,96 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import org.codehaus.groovy.runtime.NumberAwareComparator;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * A helper class for sorting objects via a closure to return the field
+ * or operation on which to sort.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class OrderBy<T> implements Comparator<T>, Serializable {
+
+    private static final long serialVersionUID = 8385130064804116654L;
+    private final List<Closure> closures;
+    private boolean equalityCheck;
+    private final NumberAwareComparator<Object> numberAwareComparator = new NumberAwareComparator<Object>();
+
+    public OrderBy() {
+        this(new ArrayList<Closure>(), false);
+    }
+
+    public OrderBy(boolean equalityCheck) {
+        this(new ArrayList<Closure>(), equalityCheck);
+    }
+
+    public OrderBy(Closure closure) {
+        this(closure, false);
+    }
+
+    public OrderBy(Closure closure, boolean equalityCheck) {
+        this(new ArrayList<Closure>(), equalityCheck);
+        closures.add(closure);
+    }
+
+    public OrderBy(List<Closure> closures) {
+        this(closures, false);
+    }
+
+    public OrderBy(List<Closure> closures, boolean equalityCheck) {
+        this.equalityCheck = equalityCheck;
+        this.closures = closures;
+    }
+
+    public void add(Closure closure) {
+        closures.add(closure);
+    }
+
+    public int compare(T object1, T object2) {
+        for (Closure closure : closures) {
+            Object value1 = closure.call(object1);
+            Object value2 = closure.call(object2);
+            int result;
+            if (!equalityCheck || (value1 instanceof Comparable && value2 instanceof Comparable)) {
+                result = numberAwareComparator.compare(value1, value2);
+            } else {
+                result = DefaultTypeTransformation.compareEqual(value1, value2) ? 0 : -1;
+            }
+            if (result == 0) continue;
+            return result;
+        }
+        return 0;
+    }
+
+    public boolean isEqualityCheck() {
+        return equalityCheck;
+    }
+
+    public void setEqualityCheck(boolean equalityCheck) {
+        this.equalityCheck = equalityCheck;
+    }
+}


[14/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/NumberRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/NumberRange.java b/src/main/groovy/lang/NumberRange.java
deleted file mode 100644
index 92c6195..0000000
--- a/src/main/groovy/lang/NumberRange.java
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * 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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.IteratorClosureAdapter;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.AbstractList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEqual;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareGreaterThan;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareGreaterThanEqual;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThan;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThanEqual;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareNotEqual;
-import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareTo;
-import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberMinus.minus;
-import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberMultiply.multiply;
-import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus.plus;
-
-/**
- * Represents an immutable list of Numbers from a value to a value with a particular step size.
- *
- * In general, it isn't recommended using a NumberRange as a key to a map. The range
- * 0..3 is deemed to be equal to 0.0..3.0 but they have different hashCode values,
- * so storing a value using one of these ranges couldn't be retrieved using the other.
- *
- * @since 2.5
- */
-public class NumberRange extends AbstractList<Comparable> implements Range<Comparable> {
-
-    /**
-     * The first value in the range.
-     */
-    private final Comparable from;
-
-    /**
-     * The last value in the range.
-     */
-    private final Comparable to;
-
-    /**
-     * The step size in the range.
-     */
-    private final Number stepSize;
-
-    /**
-     * The cached size, or -1 if not yet computed
-     */
-    private int size = -1;
-
-    /**
-     * The cached hashCode (once calculated)
-     */
-    private Integer hashCodeCache = null;
-
-    /**
-     * <code>true</code> if the range counts backwards from <code>to</code> to <code>from</code>.
-     */
-    private final boolean reverse;
-
-    /**
-     * <code>true</code> if the range includes the upper bound.
-     */
-    private final boolean inclusive;
-
-    /**
-     * Creates an inclusive {@link NumberRange} with step size 1.
-     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
-     *
-     * @param from the first value in the range
-     * @param to   the last value in the range
-     */
-    public <T extends Number & Comparable, U extends Number & Comparable>
-    NumberRange(T from, U to) {
-        this(from, to, null, true);
-    }
-
-    /**
-     * Creates a new {@link NumberRange} with step size 1.
-     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
-     *
-     * @param from start of the range
-     * @param to   end of the range
-     * @param inclusive whether the range is inclusive
-     */
-    public <T extends Number & Comparable, U extends Number & Comparable>
-    NumberRange(T from, U to, boolean inclusive) {
-        this(from, to, null, inclusive);
-    }
-
-    /**
-     * Creates an inclusive {@link NumberRange}.
-     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
-     *
-     * @param from start of the range
-     * @param to   end of the range
-     * @param stepSize the gap between discrete elements in the range
-     */
-    public <T extends Number & Comparable, U extends Number & Comparable, V extends
-            Number & Comparable<? super Number>>
-    NumberRange(T from, U to, V stepSize) {
-        this(from, to, stepSize, true);
-    }
-
-    /**
-     * Creates a {@link NumberRange}.
-     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
-     *
-     * @param from start of the range
-     * @param to   end of the range
-     * @param stepSize the gap between discrete elements in the range
-     * @param inclusive whether the range is inclusive
-     */
-    public <T extends Number & Comparable, U extends Number & Comparable, V extends
-            Number & Comparable>
-    NumberRange(T from, U to, V stepSize, boolean inclusive) {
-        if (from == null) {
-            throw new IllegalArgumentException("Must specify a non-null value for the 'from' index in a Range");
-        }
-        if (to == null) {
-            throw new IllegalArgumentException("Must specify a non-null value for the 'to' index in a Range");
-        }
-        reverse = areReversed(from, to);
-        Number tempFrom;
-        Number tempTo;
-        if (reverse) {
-            tempFrom = to;
-            tempTo = from;
-        } else {
-            tempFrom = from;
-            tempTo = to;
-        }
-        if (tempFrom instanceof Short) {
-            tempFrom = tempFrom.intValue();
-        } else if (tempFrom instanceof Float) {
-            tempFrom = tempFrom.doubleValue();
-        }
-        if (tempTo instanceof Short) {
-            tempTo = tempTo.intValue();
-        } else if (tempTo instanceof Float) {
-            tempTo = tempTo.doubleValue();
-        }
-
-        if (tempFrom instanceof Integer && tempTo instanceof Long) {
-            tempFrom = tempFrom.longValue();
-        } else if (tempTo instanceof Integer && tempFrom instanceof Long) {
-            tempTo = tempTo.longValue();
-        }
-
-        this.from = (Comparable) tempFrom;
-        this.to = (Comparable) tempTo;
-        this.stepSize = stepSize == null ? 1 : stepSize;
-        this.inclusive = inclusive;
-    }
-
-    /**
-     * For a NumberRange with step size 1, creates a new NumberRange with the same
-     * <code>from</code> and <code>to</code> as this NumberRange
-     * but with a step size of <code>stepSize</code>.
-     *
-     * @param stepSize the desired step size
-     * @return a new NumberRange
-     */
-    public <T extends Number & Comparable> NumberRange by(T stepSize) {
-        if (!Integer.valueOf(1).equals(this.stepSize)) {
-            throw new IllegalStateException("by only allowed on ranges with original stepSize = 1 but found " + this.stepSize);
-        }
-        return new NumberRange(comparableNumber(from), comparableNumber(to), stepSize, inclusive);
-    }
-
-    @SuppressWarnings("unchecked")
-    /* package private */ static <T extends Number & Comparable> T comparableNumber(Comparable c) {
-        return (T) c;
-    }
-
-    @SuppressWarnings("unchecked")
-    /* package private */ static <T extends Number & Comparable> T comparableNumber(Number n) {
-        return (T) n;
-    }
-
-    private static boolean areReversed(Number from, Number to) {
-        try {
-            return compareGreaterThan(from, to);
-        } catch (ClassCastException cce) {
-            throw new IllegalArgumentException("Unable to create range due to incompatible types: " + from.getClass().getSimpleName() + ".." + to.getClass().getSimpleName() + " (possible missing brackets around range?)", cce);
-        }
-    }
-
-    /**
-     * An object is deemed equal to this NumberRange if it represents a List of items and
-     * those items equal the list of discrete items represented by this NumberRange.
-     *
-     * @param that the object to be compared for equality with this NumberRange
-     * @return {@code true} if the specified object is equal to this NumberRange
-     * @see #fastEquals(NumberRange)
-     */
-    @Override
-    public boolean equals(Object that) {
-        return super.equals(that);
-    }
-
-    /**
-     * A NumberRange's hashCode is based on hashCode values of the discrete items it represents.
-     *
-     * @return the hashCode value
-     */
-    @Override
-    public int hashCode() {
-        if (hashCodeCache == null) {
-            hashCodeCache = super.hashCode();
-        }
-        return hashCodeCache;
-    }
-
-    /*
-     * NOTE: as per the class javadoc, this class doesn't obey the normal equals/hashCode contract.
-     * The following field and method could assist some scenarios which required a similar sort of contract
-     * (but between equals and the custom canonicalHashCode). Currently commented out since we haven't
-     * found a real need. We will likely remove this commented out code if no usage is identified soon.
-     */
-
-    /*
-     * The cached canonical hashCode (once calculated)
-     */
-//    private Integer canonicalHashCodeCache = null;
-
-    /*
-     * A NumberRange's canonicalHashCode is based on hashCode values of the discrete items it represents.
-     * When two NumberRange's are equal they will have the same canonicalHashCode value.
-     * Numerical values which Groovy deems equal have the same hashCode during this calculation.
-     * So currently (0..3).equals(0.0..3.0) yet they have different hashCode values. This breaks
-     * the normal equals/hashCode contract which is a weakness in Groovy's '==' operator. However
-     * the contract isn't broken between equals and canonicalHashCode.
-     *
-     * @return the hashCode value
-     */
-//    public int canonicalHashCode() {
-//        if (canonicalHashCodeCache == null) {
-//            int hashCode = 1;
-//            for (Comparable e : this) {
-//                int value;
-//                if (e == null) {
-//                    value = 0;
-//                } else {
-//                    BigDecimal next = new BigDecimal(e.toString());
-//                    if (next.compareTo(BigDecimal.ZERO) == 0) {
-//                        // workaround on pre-Java8 for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6480539
-//                        value = BigDecimal.ZERO.hashCode();
-//                    } else {
-//                        value = next.stripTrailingZeros().hashCode();
-//                    }
-//                }
-//                hashCode = 31 * hashCode + value;
-//            }
-//            canonicalHashCodeCache = hashCode;
-//        }
-//        return canonicalHashCodeCache;
-//    }
-
-    /**
-     * Compares a {@link NumberRange} to another {@link NumberRange} using only a strict comparison
-     * of the NumberRange properties. This won't return true for some ranges which represent the same
-     * discrete items, use equals instead for that but will be much faster for large lists.
-     *
-     * @param that the NumberRange to check equality with
-     * @return <code>true</code> if the ranges are equal
-     */
-    public boolean fastEquals(NumberRange that) {
-        return that != null
-                && reverse == that.reverse
-                && inclusive == that.inclusive
-                && compareEqual(from, that.from)
-                && compareEqual(to, that.to)
-                && compareEqual(stepSize, that.stepSize);
-    }
-
-    /*
-     * NOTE: as per the class javadoc, this class doesn't obey the normal equals/hashCode contract.
-     * The following field and method could assist some scenarios which required a similar sort of contract
-     * (but between fastEquals and the custom fastHashCode). Currently commented out since we haven't
-     * found a real need. We will likely remove this commented out code if no usage is identified soon.
-     */
-
-    /*
-     * The cached fast hashCode (once calculated)
-     */
-//    private Integer fastHashCodeCache = null;
-
-    /*
-     * A hashCode function that pairs with fastEquals, following the normal equals/hashCode contract.
-     *
-     * @return the calculated hash code
-     */
-//    public int fastHashCode() {
-//        if (fastHashCodeCache == null) {
-//            int result = 17;
-//            result = result * 31 + (reverse ? 1 : 0);
-//            result = result * 31 + (inclusive ? 1 : 0);
-//            result = result * 31 + new BigDecimal(from.toString()).stripTrailingZeros().hashCode();
-//            result = result * 31 + new BigDecimal(to.toString()).stripTrailingZeros().hashCode();
-//            result = result * 31 + new BigDecimal(stepSize.toString()).stripTrailingZeros().hashCode();
-//            fastHashCodeCache = result;
-//        }
-//        return fastHashCodeCache;
-//    }
-
-    @Override
-    public Comparable getFrom() {
-        return from;
-    }
-
-    @Override
-    public Comparable getTo() {
-        return to;
-    }
-
-    public Comparable getStepSize() {
-        return (Comparable) stepSize;
-    }
-
-    @Override
-    public boolean isReverse() {
-        return reverse;
-    }
-
-    @Override
-    public Comparable get(int index) {
-        if (index < 0) {
-            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
-        }
-        final Iterator<Comparable> iter = new StepIterator(this, stepSize);
-
-        Comparable value = iter.next();
-        for (int i = 0; i < index; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + index + " is too big for range: " + this);
-            }
-            value = iter.next();
-        }
-        return value;
-    }
-
-    /**
-     * Checks whether a value is between the from and to values of a Range
-     *
-     * @param value the value of interest
-     * @return true if the value is within the bounds
-     */
-    @Override
-    public boolean containsWithinBounds(Object value) {
-        final int result = compareTo(from, value);
-        return result == 0 || result < 0 && compareTo(to, value) >= 0;
-    }
-
-    /**
-     * protection against calls from Groovy
-     */
-    @SuppressWarnings("unused")
-    private void setSize(int size) {
-        throw new UnsupportedOperationException("size must not be changed");
-    }
-
-    @Override
-    public int size() {
-        if (size == -1) {
-            calcSize(from, to, stepSize);
-        }
-        return size;
-    }
-
-    void calcSize(Comparable from, Comparable to, Number stepSize) {
-        int tempsize = 0;
-        boolean shortcut = false;
-        if (isIntegral(stepSize)) {
-            if ((from instanceof Integer || from instanceof Long)
-                    && (to instanceof Integer || to instanceof Long)) {
-                // let's fast calculate the size
-                final BigInteger fromNum = new BigInteger(from.toString());
-                final BigInteger toTemp = new BigInteger(to.toString());
-                final BigInteger toNum = inclusive ? toTemp : toTemp.subtract(BigInteger.ONE);
-                final BigInteger sizeNum = new BigDecimal(toNum.subtract(fromNum)).divide(new BigDecimal(stepSize.longValue()), BigDecimal.ROUND_DOWN).toBigInteger().add(BigInteger.ONE);
-                tempsize = sizeNum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == -1 ? sizeNum.intValue() : Integer.MAX_VALUE;
-                shortcut = true;
-            } else if (((from instanceof BigDecimal || from instanceof BigInteger) && to instanceof Number) ||
-                    ((to instanceof BigDecimal || to instanceof BigInteger) && from instanceof Number)) {
-                // let's fast calculate the size
-                final BigDecimal fromNum = new BigDecimal(from.toString());
-                final BigDecimal toTemp = new BigDecimal(to.toString());
-                final BigDecimal toNum = inclusive ? toTemp : toTemp.subtract(new BigDecimal("1.0"));
-                final BigInteger sizeNum = toNum.subtract(fromNum).divide(new BigDecimal(stepSize.longValue()), BigDecimal.ROUND_DOWN).toBigInteger().add(BigInteger.ONE);
-                tempsize = sizeNum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == -1 ? sizeNum.intValue() : Integer.MAX_VALUE;
-                shortcut = true;
-            }
-        }
-        if (!shortcut) {
-            // let's brute-force calculate the size by iterating start to end
-            final Iterator iter = new StepIterator(this, stepSize);
-            while (iter.hasNext()) {
-                tempsize++;
-                // integer overflow
-                if (tempsize < 0) {
-                    break;
-                }
-                iter.next();
-            }
-            // integer overflow
-            if (tempsize < 0) {
-                tempsize = Integer.MAX_VALUE;
-            }
-        }
-        size = tempsize;
-    }
-
-    private boolean isIntegral(Number stepSize) {
-        BigDecimal tempStepSize = new BigDecimal(stepSize.toString());
-        return tempStepSize.equals(new BigDecimal(tempStepSize.toBigInteger()));
-    }
-
-    @Override
-    public List<Comparable> subList(int fromIndex, int toIndex) {
-        if (fromIndex < 0) {
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-        }
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-        if (fromIndex == toIndex) {
-            return new EmptyRange<Comparable>(from);
-        }
-
-        // Performance detail:
-        // not using get(fromIndex), get(toIndex) in the following to avoid stepping over elements twice
-        final Iterator<Comparable> iter = new StepIterator(this, stepSize);
-
-        Comparable value = iter.next();
-        int i = 0;
-        for (; i < fromIndex; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
-            }
-            value = iter.next();
-        }
-        final Comparable fromValue = value;
-        for (; i < toIndex - 1; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
-            }
-            value = iter.next();
-        }
-        final Comparable toValue = value;
-
-        return new NumberRange(comparableNumber(fromValue), comparableNumber(toValue), comparableNumber(stepSize), true);
-    }
-
-    @Override
-    public String toString() {
-        return getToString(to.toString(), from.toString());
-    }
-
-    @Override
-    public String inspect() {
-        return getToString(InvokerHelper.inspect(to), InvokerHelper.inspect(from));
-    }
-
-    private String getToString(String toText, String fromText) {
-        String sep = inclusive ? ".." : "..<";
-        String base = reverse ? "" + toText + sep + fromText : "" + fromText + sep + toText;
-        return Integer.valueOf(1).equals(stepSize) ? base : base + ".by(" + stepSize + ")";
-    }
-
-    /**
-     * iterates over all values and returns true if one value matches.
-     * Also see containsWithinBounds.
-     */
-    @Override
-    public boolean contains(Object value) {
-        if (value == null) {
-            return false;
-        }
-        final Iterator it = new StepIterator(this, stepSize);
-        while (it.hasNext()) {
-            if (compareEqual(value, it.next())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void step(int numSteps, Closure closure) {
-        if (numSteps == 0 && compareTo(from, to) == 0) {
-            return; // from == to and step == 0, nothing to do, so return
-        }
-        final StepIterator iter = new StepIterator(this, multiply(numSteps, stepSize));
-        while (iter.hasNext()) {
-            closure.call(iter.next());
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Iterator<Comparable> iterator() {
-        return new StepIterator(this, stepSize);
-    }
-
-    /**
-     * convenience class to serve in other methods.
-     * It's not thread-safe, and lazily produces the next element only on calls of hasNext() or next()
-     */
-    private class StepIterator implements Iterator<Comparable> {
-        private final NumberRange range;
-        private final Number step;
-        private final boolean isAscending;
-
-        private boolean isNextFetched = false;
-        private Comparable next = null;
-
-        StepIterator(NumberRange range, Number step) {
-            if (compareEqual(step, 0) && compareNotEqual(range.getFrom(), range.getTo())) {
-                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
-            }
-
-            this.range = range;
-            if (compareLessThan(step, 0)) {
-                this.step = multiply(step, -1);
-                isAscending = range.isReverse();
-            } else {
-                this.step = step;
-                isAscending = !range.isReverse();
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            fetchNextIfNeeded();
-            return (next != null) && (isAscending
-                    ? (range.inclusive ? compareLessThanEqual(next, range.getTo()) : compareLessThan(next, range.getTo()))
-                    : (range.inclusive ? compareGreaterThanEqual(next, range.getFrom()) : compareGreaterThan(next, range.getFrom())));
-        }
-
-        @Override
-        public Comparable next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-
-            fetchNextIfNeeded();
-            isNextFetched = false;
-            return next;
-        }
-
-        private void fetchNextIfNeeded() {
-            if (!isNextFetched) {
-                isNextFetched = true;
-
-                if (next == null) {
-                    // make the first fetch lazy too
-                    next = isAscending ? range.getFrom() : range.getTo();
-                } else {
-                    next = isAscending ? increment(next, step) : decrement(next, step);
-                }
-            }
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public List<Comparable> step(int numSteps) {
-        final IteratorClosureAdapter<Comparable> adapter = new IteratorClosureAdapter<Comparable>(this);
-        step(numSteps, adapter);
-        return adapter.asList();
-    }
-
-    /**
-     * Increments by given step
-     *
-     * @param value the value to increment
-     * @param step the amount to increment
-     * @return the incremented value
-     */
-    @SuppressWarnings("unchecked")
-    private Comparable increment(Object value, Number step) {
-        return (Comparable) plus((Number) value, step);
-    }
-
-    /**
-     * Decrements by given step
-     *
-     * @param value the value to decrement
-     * @param step the amount to decrement
-     * @return the decremented value
-     */
-    @SuppressWarnings("unchecked")
-    private Comparable decrement(Object value, Number step) {
-        return (Comparable) minus((Number) value, step);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ObjectRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ObjectRange.java b/src/main/groovy/lang/ObjectRange.java
deleted file mode 100644
index a7e2b05..0000000
--- a/src/main/groovy/lang/ObjectRange.java
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.IteratorClosureAdapter;
-import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.AbstractList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-/**
- * Represents an inclusive list of objects from a value to a value using
- * comparators.
- * <p>
- * Note: This class is similar to {@link IntRange}. If you make any changes to this
- * class, you might consider making parallel changes to {@link IntRange}.
- */
-public class ObjectRange extends AbstractList<Comparable> implements Range<Comparable> {
-    /**
-     * The first value in the range.
-     */
-    private final Comparable from;
-
-    /**
-     * The last value in the range.
-     */
-    private final Comparable to;
-
-    /**
-     * The cached size, or -1 if not yet computed
-     */
-    private int size = -1;
-
-    /**
-     * <code>true</code> if the range counts backwards from <code>to</code> to <code>from</code>.
-     */
-    private final boolean reverse;
-
-    /**
-     * Creates a new {@link ObjectRange}. Creates a reversed range if
-     * <code>from</code> &lt; <code>to</code>.
-     *
-     * @param from the first value in the range.
-     * @param to   the last value in the range.
-     */
-    public ObjectRange(Comparable from, Comparable to) {
-        this(from, to, null);
-    }
-
-    /**
-     * Creates a new {@link ObjectRange} assumes smaller &lt;&#61; larger, else behavior is undefined.
-     * Caution: Prefer the other constructor when in doubt.
-     * <p>
-     * Optimized Constructor avoiding initial computation of comparison.
-     */
-    public ObjectRange(Comparable smaller, Comparable larger, boolean reverse) {
-        this(smaller, larger, (Boolean) reverse);
-    }
-
-    /**
-     * Constructs a Range, computing reverse if not provided. When providing reverse,
-     * 'smaller' must not be larger than 'larger'.
-     *
-     * @param smaller start of the range, must no be larger than to when reverse != null
-     * @param larger  end of the range, must be larger than from when reverse != null
-     * @param reverse direction of the range. If null, causes direction to be computed (can be expensive).
-     */
-    private ObjectRange(Comparable smaller, Comparable larger, Boolean reverse) {
-        if (smaller == null) {
-            throw new IllegalArgumentException("Must specify a non-null value for the 'from' index in a Range");
-        }
-        if (larger == null) {
-            throw new IllegalArgumentException("Must specify a non-null value for the 'to' index in a Range");
-        }
-        if (reverse == null) {
-            final boolean computedReverse = areReversed(smaller, larger);
-            // ensure invariant from <= to
-            if (computedReverse) {
-                final Comparable temp = larger;
-                larger = smaller;
-                smaller = temp;
-            }
-            this.reverse = computedReverse;
-        } else {
-            this.reverse = reverse;
-        }
-
-        if (smaller instanceof Short) {
-            smaller = ((Short) smaller).intValue();
-        } else if (smaller instanceof Float) {
-            smaller = ((Float) smaller).doubleValue();
-        }
-        if (larger instanceof Short) {
-            larger = ((Short) larger).intValue();
-        } else if (larger instanceof Float) {
-            larger = ((Float) larger).doubleValue();
-        }
-
-        if (smaller instanceof Integer && larger instanceof Long) {
-            smaller = ((Integer) smaller).longValue();
-        } else if (larger instanceof Integer && smaller instanceof Long) {
-            larger = ((Integer) larger).longValue();
-        }
-
-        /*
-            areReversed() already does an implicit type compatibility check
-            based on DefaultTypeTransformation.compareToWithEqualityCheck() for mixed classes
-            but it is only invoked if reverse == null.
-            So Object Range has to perform those type checks for consistency even when not calling
-            compareToWithEqualityCheck(), and ObjectRange has
-            to use the normalized value used in a successful comparison in
-            compareToWithEqualityCheck(). Currently that means Chars and single-char Strings
-            are evaluated as the char's charValue (an integer) when compared to numbers.
-            So '7'..'9' should produce ['7', '8', '9'], whereas ['7'..9] and [7..'9'] should produce [55, 56, 57].
-            if classes match, or both numerical, no checks possible / necessary
-        */
-        if (smaller.getClass() == larger.getClass() ||
-                (smaller instanceof Number && larger instanceof Number)) {
-            this.from = smaller;
-            this.to = larger;
-        } else {
-            // Convenience hack: try convert single-char strings to ints
-            final Comparable tempfrom = normaliseStringType(smaller);
-            final Comparable tempto = normaliseStringType(larger);
-            // if after normalizing both are numbers, assume intended range was numbers
-            if (tempfrom instanceof Number && tempto instanceof Number) {
-                this.from = tempfrom;
-                this.to = tempto;
-            } else {
-                // if convenience hack did not make classes match,
-                // throw exception when starting with known class, and thus "from" cannot be advanced over "to".
-                // Note if start is an unusual Object, it could have a next() method
-                // that yields a Number or String to close the range
-                final Comparable start = this.reverse ? larger : smaller;
-                if (start instanceof String || start instanceof Number) {
-                    // starting with number will never reach a non-number, same for string
-                    throw new IllegalArgumentException("Incompatible Argument classes for ObjectRange " + smaller.getClass() + ", " + larger.getClass());
-                }
-                // Since normalizing did not help, use original values at user's risk
-                this.from = smaller;
-                this.to = larger;
-            }
-        }
-        checkBoundaryCompatibility();
-    }
-
-    /**
-     * throws IllegalArgumentException if to and from are incompatible, meaning they e.g. (likely) produce infinite sequences.
-     * Called at construction time, subclasses may override cautiously (using only members to and from).
-     */
-    protected void checkBoundaryCompatibility() {
-        if (from instanceof String && to instanceof String) {
-            // this test depends deeply on the String.next implementation
-            // 009.next is 00:, not 010
-            final String start = from.toString();
-            final String end = to.toString();
-            if (start.length() != end.length()) {
-                throw new IllegalArgumentException("Incompatible Strings for Range: different length");
-            }
-            final int length = start.length();
-            int i;
-            for (i = 0; i < length; i++) {
-                if (start.charAt(i) != end.charAt(i)) {
-                    break;
-                }
-            }
-            // strings must be equal except for the last character
-            if (i < length - 1) {
-                throw new IllegalArgumentException("Incompatible Strings for Range: String#next() will not reach the expected value");
-            }
-        }
-    }
-
-    private static boolean areReversed(Comparable from, Comparable to) {
-        try {
-            return ScriptBytecodeAdapter.compareGreaterThan(from, to);
-        } catch (IllegalArgumentException iae) {
-            throw new IllegalArgumentException("Unable to create range due to incompatible types: " + from.getClass().getSimpleName() + ".." + to.getClass().getSimpleName() + " (possible missing brackets around range?)", iae);
-        }
-    }
-
-    public boolean equals(Object that) {
-        return (that instanceof ObjectRange) ? equals((ObjectRange) that) : super.equals(that);
-    }
-
-    /**
-     * Compares an {@link ObjectRange} to another {@link ObjectRange}.
-     *
-     * @param that the object to check equality with
-     * @return <code>true</code> if the ranges are equal
-     */
-    public boolean equals(ObjectRange that) {
-        return that != null
-                && reverse == that.reverse
-                && DefaultTypeTransformation.compareEqual(from, that.from)
-                && DefaultTypeTransformation.compareEqual(to, that.to);
-    }
-
-    @Override
-    public Comparable getFrom() {
-        return from;
-    }
-
-    @Override
-    public Comparable getTo() {
-        return to;
-    }
-
-    @Override
-    public boolean isReverse() {
-        return reverse;
-    }
-
-    @Override
-    public Comparable get(int index) {
-        if (index < 0) {
-            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
-        }
-        final StepIterator iter = new StepIterator(this, 1);
-
-        Comparable value = iter.next();
-        for (int i = 0; i < index; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + index + " is too big for range: " + this);
-            }
-            value = iter.next();
-        }
-        return value;
-    }
-
-    /**
-     * Checks whether a value is between the from and to values of a Range
-     *
-     * @param value the value of interest
-     * @return true if the value is within the bounds
-     */
-    @Override
-    public boolean containsWithinBounds(Object value) {
-        if (value instanceof Comparable) {
-            final int result = compareTo(from, (Comparable) value);
-            return result == 0 || result < 0 && compareTo(to, (Comparable) value) >= 0;
-        }
-        return contains(value);
-    }
-
-    protected int compareTo(Comparable first, Comparable second) {
-        return DefaultGroovyMethods.numberAwareCompareTo(first, second);
-    }
-
-    /**
-     * protection against calls from Groovy
-     */
-    @SuppressWarnings("unused")
-    private void setSize(int size) {
-        throw new UnsupportedOperationException("size must not be changed");
-    }
-
-    @Override
-    public int size() {
-        if (size == -1) {
-            int tempsize = 0;
-            if ((from instanceof Integer || from instanceof Long)
-                    && (to instanceof Integer || to instanceof Long)) {
-                // let's fast calculate the size
-                final BigInteger fromNum = new BigInteger(from.toString());
-                final BigInteger toNum = new BigInteger(to.toString());
-                final BigInteger sizeNum = toNum.subtract(fromNum).add(new BigInteger("1"));
-                tempsize = sizeNum.intValue();
-                if (!BigInteger.valueOf(tempsize).equals(sizeNum)) {
-                    tempsize = Integer.MAX_VALUE;
-                }
-            } else if (from instanceof Character && to instanceof Character) {
-                // let's fast calculate the size
-                final char fromNum = (Character) from;
-                final char toNum = (Character) to;
-                tempsize = toNum - fromNum + 1;
-            } else if (((from instanceof BigDecimal || from instanceof BigInteger) && to instanceof Number) ||
-                    ((to instanceof BigDecimal || to instanceof BigInteger) && from instanceof Number)) {
-                // let's fast calculate the size
-                final BigDecimal fromNum = new BigDecimal(from.toString());
-                final BigDecimal toNum = new BigDecimal(to.toString());
-                final BigInteger sizeNum = toNum.subtract(fromNum).add(new BigDecimal(1.0)).toBigInteger();
-                tempsize = sizeNum.intValue();
-                if (!BigInteger.valueOf(tempsize).equals(sizeNum)) {
-                    tempsize = Integer.MAX_VALUE;
-                }
-            } else {
-                // let's brute-force calculate the size by iterating start to end
-                final Iterator<Comparable> iter = new StepIterator(this, 1);
-                while (iter.hasNext()) {
-                    tempsize++;
-                    // integer overflow
-                    if (tempsize < 0) {
-                        break;
-                    }
-                    iter.next();
-                }
-            }
-            // integer overflow
-            if (tempsize < 0) {
-                tempsize = Integer.MAX_VALUE;
-            }
-            size = tempsize;
-        }
-        return size;
-    }
-
-    @Override
-    public List<Comparable> subList(int fromIndex, int toIndex) {
-        if (fromIndex < 0) {
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-        }
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-        if (fromIndex == toIndex) {
-            return new EmptyRange<Comparable>(from);
-        }
-
-        // Performance detail:
-        // not using get(fromIndex), get(toIndex) in the following to avoid stepping over elements twice
-        final Iterator<Comparable> iter = new StepIterator(this, 1);
-
-        Comparable toValue = iter.next();
-        int i = 0;
-        for (; i < fromIndex; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
-            }
-            toValue = iter.next();
-        }
-        final Comparable fromValue = toValue;
-        for (; i < toIndex - 1; i++) {
-            if (!iter.hasNext()) {
-                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
-            }
-            toValue = iter.next();
-        }
-
-        return new ObjectRange(fromValue, toValue, reverse);
-    }
-
-    public String toString() {
-        return reverse ? "" + to + ".." + from : "" + from + ".." + to;
-    }
-
-    @Override
-    public String inspect() {
-        final String toText = InvokerHelper.inspect(to);
-        final String fromText = InvokerHelper.inspect(from);
-        return reverse ? "" + toText + ".." + fromText : "" + fromText + ".." + toText;
-    }
-
-    /**
-     * Iterates over all values and returns true if one value matches.
-     *
-     * @see #containsWithinBounds(Object)
-     */
-    @Override
-    public boolean contains(Object value) {
-        final Iterator<Comparable> iter = new StepIterator(this, 1);
-        if (value == null) {
-            return false;
-        }
-        while (iter.hasNext()) {
-            if (DefaultTypeTransformation.compareEqual(value, iter.next())) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void step(int step, Closure closure) {
-        if (step == 0 && compareTo(from, to) == 0) {
-            return; // from == to and step == 0, nothing to do, so return
-        }
-        final Iterator<Comparable> iter = new StepIterator(this, step);
-        while (iter.hasNext()) {
-            closure.call(iter.next());
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Iterator<Comparable> iterator() {
-        // non thread-safe iterator
-        return new StepIterator(this, 1);
-    }
-
-    /**
-     * Non-thread-safe iterator which lazily produces the next element only on calls of hasNext() or next()
-     */
-    private static final class StepIterator implements Iterator<Comparable> {
-        // actual step, can be +1 when desired step is -1 and direction is from high to low
-        private final int step;
-        private final ObjectRange range;
-        private int index = -1;
-        private Comparable value;
-        private boolean nextFetched = true;
-
-        private StepIterator(ObjectRange range, final int desiredStep) {
-            if (desiredStep == 0 && range.compareTo(range.getFrom(), range.getTo()) != 0) {
-                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
-            }
-            this.range = range;
-            if (range.isReverse()) {
-                step = -desiredStep;
-            } else {
-                step = desiredStep;
-            }
-            if (step > 0) {
-                value = range.getFrom();
-            } else {
-                value = range.getTo();
-            }
-        }
-
-        @Override
-        public void remove() {
-            range.remove(index);
-        }
-
-        @Override
-        public Comparable next() {
-            // not thread safe
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            nextFetched = false;
-            index++;
-            return value;
-        }
-
-        @Override
-        public boolean hasNext() {
-            // not thread safe
-            if (!nextFetched) {
-                value = peek();
-                nextFetched = true;
-            }
-            return value != null;
-        }
-
-        private Comparable peek() {
-            if (step > 0) {
-                Comparable peekValue = value;
-                for (int i = 0; i < step; i++) {
-                    peekValue = (Comparable) range.increment(peekValue);
-                    // handle back to beginning due to modulo incrementing
-                    if (range.compareTo(peekValue, range.from) <= 0) return null;
-                }
-                if (range.compareTo(peekValue, range.to) <= 0) {
-                    return peekValue;
-                }
-            } else {
-                final int positiveStep = -step;
-                Comparable peekValue = value;
-                for (int i = 0; i < positiveStep; i++) {
-                    peekValue = (Comparable) range.decrement(peekValue);
-                    // handle back to beginning due to modulo decrementing
-                    if (range.compareTo(peekValue, range.to) >= 0) return null;
-                }
-                if (range.compareTo(peekValue, range.from) >= 0) {
-                    return peekValue;
-                }
-            }
-            return null;
-        }
-    }
-
-    @Override
-    public List<Comparable> step(int step) {
-        final IteratorClosureAdapter<Comparable> adapter = new IteratorClosureAdapter<Comparable>(this);
-        step(step, adapter);
-        return adapter.asList();
-    }
-
-    /**
-     * Increments by one
-     *
-     * @param value the value to increment
-     * @return the incremented value
-     */
-    protected Object increment(Object value) {
-        return InvokerHelper.invokeMethod(value, "next", null);
-    }
-
-    /**
-     * Decrements by one
-     *
-     * @param value the value to decrement
-     * @return the decremented value
-     */
-    protected Object decrement(Object value) {
-        return InvokerHelper.invokeMethod(value, "previous", null);
-    }
-
-    /**
-     * if operand is a Character or a String with one character, return that character's int value.
-     */
-    private static Comparable normaliseStringType(final Comparable operand) {
-        if (operand instanceof Character) {
-            return (int) (Character) operand;
-        }
-        if (operand instanceof String) {
-            final String string = (String) operand;
-
-            if (string.length() == 1) {
-                return (int) string.charAt(0);
-            }
-            return string;
-        }
-        return operand;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ParameterArray.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ParameterArray.java b/src/main/groovy/lang/ParameterArray.java
deleted file mode 100644
index d3a4163..0000000
--- a/src/main/groovy/lang/ParameterArray.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Distinguish a parameter array from Object[].
- *
- * @author Pilho Kim
- */
-public class ParameterArray {
-
-    private final Object parameters;
-
-    public ParameterArray(Object data) {
-        parameters = packArray(data);
-    }
-
-    private static Object packArray(Object object) {
-        if (object instanceof Object[])
-            return (Object[]) object;
-        else
-            return object;
-    }
-
-    public Object get() {
-        return parameters;
-    }
-
-    public String toString() {
-        if (parameters == null)
-            return "<null parameter>";
-        return parameters.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/PropertyAccessInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/PropertyAccessInterceptor.java b/src/main/groovy/lang/PropertyAccessInterceptor.java
deleted file mode 100644
index 6d2906e..0000000
--- a/src/main/groovy/lang/PropertyAccessInterceptor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * <p>An interface that adds the ability to intercept
- * property getters/setters
- *
- * @author Graeme Rocher
- * @since Oct 24, 2005
- */
-public interface PropertyAccessInterceptor extends Interceptor {
-
-    /**
-     * Intercepts a getXXX call and returns a result. The result is replaced by the
-     * real value if doGet() return false
-     *
-     * @param object   The target object
-     * @param property The property to get
-     * @return A value supplied by the interceptor
-     */
-    Object beforeGet(Object object, String property);
-
-    /**
-     * Intercepts a setXXX call
-     *
-     * @param object   The target object
-     * @param property The property to set
-     * @param newValue The new value
-     */
-    void beforeSet(Object object, String property, Object newValue);
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/PropertyValue.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/PropertyValue.java b/src/main/groovy/lang/PropertyValue.java
deleted file mode 100644
index ac77b54..0000000
--- a/src/main/groovy/lang/PropertyValue.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  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 groovy.lang;
-
-public class PropertyValue {
-    // the owner of the property
-    private final Object bean;
-
-    // the description of the property
-    private final MetaProperty mp;
-
-    public PropertyValue(Object bean, MetaProperty mp) {
-        this.bean = bean;
-        this.mp = mp;
-    }
-
-    public String getName() {
-        return mp.getName();
-    }
-
-    public Class getType() {
-        return mp.getType();
-    }
-
-    public Object getValue() {
-        return mp.getProperty(bean);
-    }
-
-    public void setValue(Object value) {
-        mp.setProperty(bean, value);
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ProxyMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ProxyMetaClass.java b/src/main/groovy/lang/ProxyMetaClass.java
deleted file mode 100644
index 8c41f7d..0000000
--- a/src/main/groovy/lang/ProxyMetaClass.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * As subclass of MetaClass, ProxyMetaClass manages calls from Groovy Objects to POJOs.
- * It enriches MetaClass with the feature of making method invocations interceptable by
- * an Interceptor. To this end, it acts as a decorator (decorator pattern) allowing
- * to add or withdraw this feature at runtime.
- * See groovy/lang/InterceptorTest.groovy for details.
- * <p>
- * WARNING: This implementation of ProxyMetaClass is NOT thread-safe and hence should only be used for
- * as a per-instance MetaClass running in a single thread. Do not place this MetaClass in the MetaClassRegistry
- * as it will result in unpredictable behaviour
- *
- * @author Dierk Koenig
- * @author Graeme Rocher
- * @see groovy.lang.MetaClassRegistry
- */
-public class ProxyMetaClass extends MetaClassImpl implements AdaptingMetaClass {
-
-    protected MetaClass adaptee = null;
-    protected Interceptor interceptor = null;
-
-
-    /**
-     * convenience factory method for the most usual case.
-     */
-    public static ProxyMetaClass getInstance(Class theClass) {
-        MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry();
-        MetaClass meta = metaRegistry.getMetaClass(theClass);
-        return new ProxyMetaClass(metaRegistry, theClass, meta);
-    }
-
-    /**
-     * @param adaptee the MetaClass to decorate with interceptability
-     */
-    public ProxyMetaClass(MetaClassRegistry registry, Class theClass, MetaClass adaptee) {
-        super(registry, theClass);
-        this.adaptee = adaptee;
-        if (null == adaptee) throw new IllegalArgumentException("adaptee must not be null");
-        super.initialize();
-    }
-
-    public synchronized void initialize() {
-        this.adaptee.initialize();
-    }
-
-    /**
-     * Use the ProxyMetaClass for the given Closure.
-     * Cares for balanced register/unregister.
-     *
-     * @param closure piece of code to be executed with registered ProxyMetaClass
-     */
-    public Object use(Closure closure) {
-        // grab existing meta (usually adaptee but we may have nested use calls)
-        MetaClass origMetaClass = registry.getMetaClass(theClass);
-        registry.setMetaClass(theClass, this);
-        try {
-            return closure.call();
-        } finally {
-            registry.setMetaClass(theClass, origMetaClass);
-        }
-    }
-
-    /**
-     * Use the ProxyMetaClass for the given Closure.
-     * Cares for balanced setting/unsetting ProxyMetaClass.
-     *
-     * @param closure piece of code to be executed with ProxyMetaClass
-     */
-    public Object use(GroovyObject object, Closure closure) {
-        // grab existing meta (usually adaptee but we may have nested use calls)
-        MetaClass origMetaClass = object.getMetaClass();
-        object.setMetaClass(this);
-        try {
-            return closure.call();
-        } finally {
-            object.setMetaClass(origMetaClass);
-        }
-    }
-
-    /**
-     * @return the interceptor in use or null if no interceptor is used
-     */
-    public Interceptor getInterceptor() {
-        return interceptor;
-    }
-
-    /**
-     * @param interceptor may be null to reset any interception
-     */
-    public void setInterceptor(Interceptor interceptor) {
-        this.interceptor = interceptor;
-    }
-
-    /**
-     * Call invokeMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
-     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
-     * The method call is suppressed if Interceptor.doInvoke() returns false.
-     * See Interceptor for details.
-     */
-    public Object invokeMethod(final Object object, final String methodName, final Object[] arguments) {
-        return doCall(object, methodName, arguments, interceptor, new Callable() {
-            public Object call() {
-                return adaptee.invokeMethod(object, methodName, arguments);
-            }
-        });
-    }
-
-    /**
-     * Call invokeMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
-     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
-     * The method call is suppressed if Interceptor.doInvoke() returns false.
-     * See Interceptor for details.
-     */
-    @Override
-    public Object invokeMethod(final Class sender, final Object object, final String methodName, final Object[] arguments, final boolean isCallToSuper, final boolean fromInsideClass) {
-        return doCall(object, methodName, arguments, interceptor, new Callable() {
-            public Object call() {
-                return adaptee.invokeMethod(sender, object, methodName, arguments, isCallToSuper, fromInsideClass);
-            }
-        });
-    }
-
-    /**
-     * Call invokeStaticMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
-     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
-     * The method call is suppressed if Interceptor.doInvoke() returns false.
-     * See Interceptor for details.
-     */
-    public Object invokeStaticMethod(final Object object, final String methodName, final Object[] arguments) {
-        return doCall(object, methodName, arguments, interceptor, new Callable() {
-            public Object call() {
-                return adaptee.invokeStaticMethod(object, methodName, arguments);
-            }
-        });
-    }
-
-    /**
-     * Call invokeConstructor on adaptee with logic like in MetaClass unless we have an Interceptor.
-     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
-     * The method call is suppressed if Interceptor.doInvoke() returns false.
-     * See Interceptor for details.
-     */
-    public Object invokeConstructor(final Object[] arguments) {
-        return doCall(theClass, "ctor", arguments, interceptor, new Callable() {
-            public Object call() {
-                return adaptee.invokeConstructor(arguments);
-            }
-        });
-    }
-
-    /**
-     * Interceptors the call to getProperty if a PropertyAccessInterceptor is
-     * available
-     *
-     * @param object   the object to invoke the getter on
-     * @param property the property name
-     * @return the value of the property
-     */
-    public Object getProperty(Class aClass, Object object, String property, boolean b, boolean b1) {
-        if (null == interceptor) {
-            return super.getProperty(aClass, object, property, b, b1);
-        }
-        if (interceptor instanceof PropertyAccessInterceptor) {
-            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;
-
-            Object result = pae.beforeGet(object, property);
-            if (interceptor.doInvoke()) {
-                result = super.getProperty(aClass, object, property, b, b1);
-            }
-            return result;
-        }
-        return super.getProperty(aClass, object, property, b, b1);
-    }
-
-    /**
-     * Interceptors the call to a property setter if a PropertyAccessInterceptor
-     * is available
-     *
-     * @param object   The object to invoke the setter on
-     * @param property The property name to set
-     * @param newValue The new value of the property
-     */
-    public void setProperty(Class aClass, Object object, String property, Object newValue, boolean b, boolean b1) {
-        if (null == interceptor) {
-            super.setProperty(aClass, object, property, newValue, b, b1);
-        }
-        if (interceptor instanceof PropertyAccessInterceptor) {
-            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;
-
-            pae.beforeSet(object, property, newValue);
-            if (interceptor.doInvoke()) {
-                super.setProperty(aClass, object, property, newValue, b, b1);
-            }
-        } else {
-            super.setProperty(aClass, object, property, newValue, b, b1);
-        }
-    }
-
-    public MetaClass getAdaptee() {
-        return this.adaptee;
-    }
-
-    public void setAdaptee(MetaClass metaClass) {
-        this.adaptee = metaClass;
-    }
-
-    // since Java has no Closures...
-    private interface Callable {
-        Object call();
-    }
-
-    private Object doCall(Object object, String methodName, Object[] arguments, Interceptor interceptor, Callable howToInvoke) {
-        if (null == interceptor) {
-            return howToInvoke.call();
-        }
-        Object result = interceptor.beforeInvoke(object, methodName, arguments);
-        if (interceptor.doInvoke()) {
-            result = howToInvoke.call();
-        }
-        result = interceptor.afterInvoke(object, methodName, arguments, result);
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Range.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Range.java b/src/main/groovy/lang/Range.java
deleted file mode 100644
index 99f30de..0000000
--- a/src/main/groovy/lang/Range.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.List;
-
-/**
- * A Range represents the list of discrete items between some starting (or <code>from</code>)
- * value and <em>working up</em> towards some ending (or <code>to</code>) value.
- * For a reverse range, the list is obtained by starting at the <code>to</code> value and
- * <em>working down</em> towards the <code>from</code> value.
- *
- * The concept of <em>working up</em> and <em>working down</em> is dependent on the range implementation.
- * In the general case, working up involves successive calls to the first item's <code>next()</code>
- * method while working down involves calling the <code>previous()</code> method. Optimized
- * numerical ranges may apply numeric addition or subtraction of some numerical step size.
- *
- * Particular range implementations may also support the notion of inclusivity
- * and exclusivity with respect to the ending value in the range.
- * E.g. <code>1..3 == [1, 2, 3]</code>; but <code>1..<3 == [1, 2]</code>.
- *
- * In general, the second boundary may not be contained in the range,
- * and <code>a..b</code> may produce a different set of elements than <code>(b..a).reversed()</code>.
- * E.g.  <code>1..2.5 == [1, 2]</code>; but <code>2.5..1 == [2.5, 1.5]</code>.
- *
- * Implementations can be memory efficient by storing just the <code>from</code> and <code>to</code> boundary
- * values rather than eagerly creating all discrete items in the conceptual list. The actual discrete items
- * can be lazily calculated on an as needed basis (e.g. when calling methods from the <code>java.util.List</code>
- * interface or the additional <code>step</code> methods in the <code>Range</code> interface).
- *
- * In addition to the methods related to a Range's "discrete items" abstraction, there is a method,
- * <code>containsWithinBounds</code> which, for numerical ranges, allows checking within the continuous
- * interval between the Range's boundary values.
- */
-public interface Range<T extends Comparable> extends List<T> {
-    /**
-     * The lower value in the range.
-     *
-     * @return the lower value in the range.
-     */
-    T getFrom();
-
-    /**
-     * The upper value in the range.
-     *
-     * @return the upper value in the range
-     */
-    T getTo();
-
-    /**
-     * Indicates whether this is a reverse range which iterates backwards
-     * starting from the to value and ending on the from value
-     *
-     * @return <code>true</code> if this is a reverse range
-     */
-    boolean isReverse();
-
-    /**
-     * Indicates whether an object is greater than or equal to the <code>from</code>
-     * value for the range and less than or equal to the <code>to</code> value.
-     * <p>
-     * This may be true even for values not contained in the range.
-     *
-     * Example: from = 1.5, to = 3, next() increments by 1
-     * containsWithinBounds(2) == true
-     * contains(2) == false
-     *
-     * @param o the object to check against the boundaries of the range
-     * @return <code>true</code> if the object is between the from and to values
-     */
-    boolean containsWithinBounds(Object o);
-
-    /**
-     * Steps through the range, calling a closure for each item.
-     *
-     * @param step    the amount by which to step. If negative, steps through the range backwards.
-     * @param closure the {@link Closure} to call
-     */
-    void step(int step, Closure closure);
-
-    /**
-     * Forms a list by stepping through the range by the indicated interval.
-     *
-     * @param step the amount by which to step. If negative, steps through the range backwards.
-     * @return the list formed by stepping through the range by the indicated interval.
-     */
-    List<T> step(int step);
-
-    /**
-     * @return the verbose {@link String} representation of this {@link Range} as would be typed into a console to create the {@link Range} instance
-     */
-    String inspect();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ReadOnlyPropertyException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ReadOnlyPropertyException.java b/src/main/groovy/lang/ReadOnlyPropertyException.java
deleted file mode 100644
index 342a182..0000000
--- a/src/main/groovy/lang/ReadOnlyPropertyException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  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 groovy.lang;
-
-
-/**
- * This exception is thrown if an attempt is made to set a read only property
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class ReadOnlyPropertyException extends MissingPropertyException {
-
-    public ReadOnlyPropertyException(final String property, final Class type) {
-        super("Cannot set readonly property: " + property + " for class: " + type.getName(), property, type);
-    }
-
-    public ReadOnlyPropertyException(final String property, final String classname) {
-        super("Cannot set readonly property: " + property + " for class: " + classname);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Reference.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Reference.java b/src/main/groovy/lang/Reference.java
deleted file mode 100644
index c4bf21d..0000000
--- a/src/main/groovy/lang/Reference.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.Serializable;
-
-/**
- * Represents a reference to a value
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class Reference<T> extends GroovyObjectSupport implements Serializable {
-
-    private static final long serialVersionUID = 4963704631487573488L;
-    private T value;
-
-    public Reference() {
-    }
-
-    public Reference(T value) {
-        this.value = value;
-    }
-
-    public Object getProperty(String property) {
-        Object value = get();
-        if (value != null) {
-            return InvokerHelper.getProperty(value, property);
-        }
-        return super.getProperty(property);
-    }
-
-    public void setProperty(String property, Object newValue) {
-        Object value = get();
-        if (value != null) {
-            InvokerHelper.setProperty(value, property, newValue);
-        }
-        else {
-            super.setProperty(property, newValue);
-        }
-    }
-
-    public Object invokeMethod(String name, Object args) {
-        Object value = get();
-        if (value != null) {
-            try {
-                return InvokerHelper.invokeMethod(value, name, args);
-            }
-            catch (Exception e) {
-                return super.invokeMethod(name, args);
-            }
-        }
-        else {
-            return super.invokeMethod(name, args);
-        }
-    }
-
-    public T get() {
-        return value;
-    }
-
-    public void set(T value) {
-        this.value = value;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Script.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Script.java b/src/main/groovy/lang/Script.java
deleted file mode 100644
index 196c74c..0000000
--- a/src/main/groovy/lang/Script.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * This object represents a Groovy script
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Guillaume Laforge
- */
-public abstract class Script extends GroovyObjectSupport {
-    private Binding binding;
-
-    protected Script() {
-        this(new Binding());
-    }
-
-    protected Script(Binding binding) {
-        this.binding = binding;
-    }
-
-    public Binding getBinding() {
-        return binding;
-    }
-
-    public void setBinding(Binding binding) {
-        this.binding = binding;
-    }
-
-    public Object getProperty(String property) {
-        try {
-            return binding.getVariable(property);
-        } catch (MissingPropertyException e) {
-            return super.getProperty(property);
-        }
-    }
-
-    public void setProperty(String property, Object newValue) {
-        if ("binding".equals(property))
-            setBinding((Binding) newValue);
-        else if("metaClass".equals(property))
-            setMetaClass((MetaClass)newValue);
-        else
-            binding.setVariable(property, newValue);
-    }
-
-    /**
-     * Invoke a method (or closure in the binding) defined.
-     *
-     * @param name method to call
-     * @param args arguments to pass to the method
-     * @return value
-     */
-    public Object invokeMethod(String name, Object args) {
-        try {
-            return super.invokeMethod(name, args);
-        }
-        // if the method was not found in the current scope (the script's methods)
-        // let's try to see if there's a method closure with the same name in the binding
-        catch (MissingMethodException mme) {
-            try {
-                if (name.equals(mme.getMethod())) {
-                    Object boundClosure = getProperty(name);
-                    if (boundClosure != null && boundClosure instanceof Closure) {
-                        return ((Closure) boundClosure).call((Object[])args);
-                    } else {
-                        throw mme;
-                    }
-                } else {
-                    throw mme;
-                }
-            } catch (MissingPropertyException mpe) {
-                throw mme;
-            }
-        }
-    }
-
-    /**
-     * The main instance method of a script which has variables in scope
-     * as defined by the current {@link Binding} instance.
-     */
-    public abstract Object run();
-
-    // println helper methods
-
-    /**
-     * Prints a newline to the current 'out' variable which should be a PrintWriter
-     * or at least have a println() method defined on it.
-     * If there is no 'out' property then print to standard out.
-     */
-    public void println() {
-        Object object;
-
-        try {
-            object = getProperty("out");
-        } catch (MissingPropertyException e) {
-            System.out.println();
-            return;
-        }
-
-        InvokerHelper.invokeMethod(object, "println", ArgumentListExpression.EMPTY_ARRAY);
-    }
-
-    /**
-     * Prints the value to the current 'out' variable which should be a PrintWriter
-     * or at least have a print() method defined on it.
-     * If there is no 'out' property then print to standard out.
-     */
-    public void print(Object value) {
-        Object object;
-
-        try {
-            object = getProperty("out");
-        } catch (MissingPropertyException e) {
-            DefaultGroovyMethods.print(System.out,value);
-            return;
-        }
-
-        InvokerHelper.invokeMethod(object, "print", new Object[]{value});
-    }
-
-    /**
-     * Prints the value and a newline to the current 'out' variable which should be a PrintWriter
-     * or at least have a println() method defined on it.
-     * If there is no 'out' property then print to standard out.
-     */
-    public void println(Object value) {
-        Object object;
-
-        try {
-            object = getProperty("out");
-        } catch (MissingPropertyException e) {
-            DefaultGroovyMethods.println(System.out,value);
-            return;
-        }
-
-        InvokerHelper.invokeMethod(object, "println", new Object[]{value});
-    }
-
-    /**
-     * Prints a formatted string using the specified format string and argument.
-     *
-     * @param format the format to follow
-     * @param value the value to be formatted
-     */
-    public void printf(String format, Object value) {
-        Object object;
-
-        try {
-            object = getProperty("out");
-        } catch (MissingPropertyException e) {
-            DefaultGroovyMethods.printf(System.out, format, value);
-            return;
-        }
-
-        InvokerHelper.invokeMethod(object, "printf", new Object[] { format, value });
-    }
-
-    /**
-     * Prints a formatted string using the specified format string and arguments.
-     *
-     * @param format the format to follow
-     * @param values an array of values to be formatted
-     */
-    public void printf(String format, Object[] values) {
-        Object object;
-
-        try {
-            object = getProperty("out");
-        } catch (MissingPropertyException e) {
-            DefaultGroovyMethods.printf(System.out, format, values);
-            return;
-        }
-
-        InvokerHelper.invokeMethod(object, "printf", new Object[] { format, values });
-    }
-
-    /**
-     * A helper method to allow the dynamic evaluation of groovy expressions using this
-     * scripts binding as the variable scope
-     *
-     * @param expression is the Groovy script expression to evaluate
-     */
-    public Object evaluate(String expression) throws CompilationFailedException {
-        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
-        return shell.evaluate(expression);
-    }
-
-    /**
-     * A helper method to allow the dynamic evaluation of groovy expressions using this
-     * scripts binding as the variable scope
-     *
-     * @param file is the Groovy script to evaluate
-     */
-    public Object evaluate(File file) throws CompilationFailedException, IOException {
-        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
-        return shell.evaluate(file);
-    }
-
-    /**
-     * A helper method to allow scripts to be run taking command line arguments
-     */
-    public void run(File file, String[] arguments) throws CompilationFailedException, IOException {
-        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
-        shell.run(file, arguments);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Sequence.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Sequence.java b/src/main/groovy/lang/Sequence.java
deleted file mode 100644
index 2b4316c..0000000
--- a/src/main/groovy/lang/Sequence.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Represents a sequence of objects which represents zero or many instances of
- * of objects of a given type. The type can be omitted in which case any type of
- * object can be added.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class Sequence extends ArrayList implements GroovyObject {
-
-    private MetaClass metaClass = InvokerHelper.getMetaClass(getClass());
-    private final Class type;
-    private int hashCode;
-
-    public Sequence() {
-        this(null);
-    }
-
-    public Sequence(Class type) {
-        this.type = type;
-    }
-
-    public Sequence(Class type, List content) {
-        super(content.size());
-        this.type = type;
-        addAll(content);
-    }
-
-    /**
-     * Sets the contents of this sequence to that
-     * of the given collection.
-     */
-    public void set(Collection collection) {
-        checkCollectionType(collection);
-        clear();
-        addAll(collection);
-    }
-    
-    public boolean equals(Object that) {
-        if (that instanceof Sequence) {
-            return equals((Sequence) that);
-        }
-        return false;
-    }
-
-    public boolean equals(Sequence that) {
-        if (size() == that.size()) {
-            for (int i = 0; i < size(); i++) {
-                if (!DefaultTypeTransformation.compareEqual(this.get(i), that.get(i))) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public int hashCode() {
-        if (hashCode == 0) {
-            for (int i = 0; i < size(); i++) {
-                Object value = get(i);
-                int hash = (value != null) ? value.hashCode() : 0xbabe;
-                hashCode ^= hash;
-            }
-            if (hashCode == 0) {
-                hashCode = 0xbabe;
-            }
-        }
-        return hashCode;
-    }
-
-    public int minimumSize() {
-        return 0;
-    }
-
-    /**
-     * @return the type of the elements in the sequence or null if there is no
-     * type constraint on this sequence
-     */
-    public Class type() {
-        return type;
-    }
-    
-    public void add(int index, Object element) {
-        checkType(element);
-        hashCode = 0;
-        super.add(index, element);
-    }
-
-    public boolean add(Object element) {
-        checkType(element);
-        hashCode = 0;
-        return super.add(element);
-    }
-
-    public boolean addAll(Collection c) {
-        checkCollectionType(c);
-        hashCode = 0;
-        return super.addAll(c);
-    }
-
-    public boolean addAll(int index, Collection c) {
-        checkCollectionType(c);
-        hashCode = 0;
-        return super.addAll(index, c);
-    }
-
-    public void clear() {
-        hashCode = 0;
-        super.clear();
-    }
-
-    public Object remove(int index) {
-        hashCode = 0;
-        return super.remove(index);
-    }
-
-    protected void removeRange(int fromIndex, int toIndex) {
-        hashCode = 0;
-        super.removeRange(fromIndex, toIndex);
-    }
-
-    public Object set(int index, Object element) {
-        hashCode = 0;
-        return super.set(index, element);
-    }
-
-    // GroovyObject interface
-    //-------------------------------------------------------------------------
-    public Object invokeMethod(String name, Object args) {
-        try {
-        return getMetaClass().invokeMethod(this, name, args);
-        }
-        catch (MissingMethodException e) {
-            // lets apply the method to each item in the collection
-            List answer = new ArrayList(size());
-            for (Iterator iter = iterator(); iter.hasNext(); ) {
-                Object element = iter.next();
-                Object value = InvokerHelper.invokeMethod(element, name, args);
-                answer.add(value);
-            }
-            return answer;
-        }
-    }
-
-    public Object getProperty(String property) {
-        return getMetaClass().getProperty(this, property);
-    }
-
-    public void setProperty(String property, Object newValue) {
-        getMetaClass().setProperty(this, property, newValue);
-    }
-
-    public MetaClass getMetaClass() {
-        return metaClass;
-    }
-
-    public void setMetaClass(MetaClass metaClass) {
-        this.metaClass = metaClass;
-    }
-
-    // Implementation methods
-    //-------------------------------------------------------------------------
-    
-    /**
-     * Checks that each member of the given collection are of the correct
-     * type
-     */
-    protected void checkCollectionType(Collection c) {
-        if (type != null) {
-            for (Iterator iter = c.iterator(); iter.hasNext(); ) {
-                Object element = iter.next();
-                checkType(element);
-            }
-        }
-    }
-
-
-    /** 
-     * Checks that the given object instance is of the correct type
-     * otherwise a runtime exception is thrown
-     */
-    protected void checkType(Object object) {
-        if (object == null) {
-            throw new NullPointerException("Sequences cannot contain null, use a List instead");
-        }
-        if (type != null) {
-            if (!type.isInstance(object)) {
-                throw new IllegalArgumentException(
-                    "Invalid type of argument for sequence of type: "
-                        + type.getName()
-                        + " cannot add object: "
-                        + object);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Singleton.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Singleton.java b/src/main/groovy/lang/Singleton.java
deleted file mode 100644
index c1aabf6..0000000
--- a/src/main/groovy/lang/Singleton.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation to make a singleton class. The singleton is obtained through normal property access using the singleton property (defaults to "instance").
- *
- * Such classes can be initialized during normal static initialization of the class or lazily (on first access).
- * To make the singleton lazy use {@code @Singleton(lazy=true)}.
- * Lazy singletons are implemented with double-checked locking and a volatile backing field.
- * By default, no explicit constructors are allowed. To create one or more explicit constructors
- * use {@code @Singleton(strict=false)}.
- * This could be used to:
- * <ul>
- * <li>provide your own custom initialization logic in your own no-arg constructor - you
- * will be responsible for the entire code (the {@code @Singleton} annotation becomes merely documentation)</li>
- * <li>provide one or more constructors with arguments for a quasi-singleton - these constructors will be used
- * to create instances that are independent of the singleton instance returned by the singleton property</li>
- * </ul>
- *
- * @author Alex Tkachman
- * @author Paul King
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.SingletonASTTransformation")
-public @interface Singleton {
-    /**
-     * @return if this singleton should be lazy
-     */
-    boolean lazy() default false;
-
-    /**
-     * @return if this singleton should have strict semantics
-     */
-    boolean strict() default true;
-
-    /**
-     * @return the singleton property name
-     */
-    String property() default "instance";
-}


[46/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/AstSpecificationCompiler.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/AstSpecificationCompiler.groovy b/src/main/groovy/AstSpecificationCompiler.groovy
deleted file mode 100644
index 5e607b6..0000000
--- a/src/main/groovy/AstSpecificationCompiler.groovy
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*
- *  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.ast.builder
-
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.ConstructorNode
-import org.codehaus.groovy.ast.DynamicVariable
-import org.codehaus.groovy.ast.FieldNode
-import org.codehaus.groovy.ast.GenericsType
-import org.codehaus.groovy.ast.ImportNode
-import org.codehaus.groovy.ast.InnerClassNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.MixinNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.PropertyNode
-import org.codehaus.groovy.ast.VariableScope
-import org.codehaus.groovy.ast.expr.AnnotationConstantExpression
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
-import org.codehaus.groovy.ast.expr.ArrayExpression
-import org.codehaus.groovy.ast.expr.AttributeExpression
-import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BitwiseNegationExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.expr.CastExpression
-import org.codehaus.groovy.ast.expr.ClassExpression
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.ClosureListExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.expr.ConstructorCallExpression
-import org.codehaus.groovy.ast.expr.DeclarationExpression
-import org.codehaus.groovy.ast.expr.ElvisOperatorExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.FieldExpression
-import org.codehaus.groovy.ast.expr.GStringExpression
-import org.codehaus.groovy.ast.expr.ListExpression
-import org.codehaus.groovy.ast.expr.MapEntryExpression
-import org.codehaus.groovy.ast.expr.MapExpression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.MethodPointerExpression
-import org.codehaus.groovy.ast.expr.NamedArgumentListExpression
-import org.codehaus.groovy.ast.expr.NotExpression
-import org.codehaus.groovy.ast.expr.PostfixExpression
-import org.codehaus.groovy.ast.expr.PrefixExpression
-import org.codehaus.groovy.ast.expr.PropertyExpression
-import org.codehaus.groovy.ast.expr.RangeExpression
-import org.codehaus.groovy.ast.expr.SpreadExpression
-import org.codehaus.groovy.ast.expr.SpreadMapExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
-import org.codehaus.groovy.ast.expr.TernaryExpression
-import org.codehaus.groovy.ast.expr.TupleExpression
-import org.codehaus.groovy.ast.expr.UnaryMinusExpression
-import org.codehaus.groovy.ast.expr.UnaryPlusExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.AssertStatement
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.BreakStatement
-import org.codehaus.groovy.ast.stmt.CaseStatement
-import org.codehaus.groovy.ast.stmt.CatchStatement
-import org.codehaus.groovy.ast.stmt.ContinueStatement
-import org.codehaus.groovy.ast.stmt.EmptyStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
-import org.codehaus.groovy.ast.stmt.ForStatement
-import org.codehaus.groovy.ast.stmt.IfStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.ast.stmt.SwitchStatement
-import org.codehaus.groovy.ast.stmt.SynchronizedStatement
-import org.codehaus.groovy.ast.stmt.ThrowStatement
-import org.codehaus.groovy.ast.stmt.TryCatchStatement
-import org.codehaus.groovy.ast.stmt.WhileStatement
-import org.codehaus.groovy.runtime.MethodClosure
-import org.codehaus.groovy.syntax.Token
-import org.codehaus.groovy.syntax.Types
-
-/**
- * Handles parsing the properties from the closure into values that can be referenced.
- * 
- * This object is very stateful and not threadsafe. It accumulates expressions in the 
- * 'expression' field as they are found and executed within the DSL. 
- * 
- * Note: this class consists of many one-line method calls. A better implementation
- * might be to take a declarative approach and replace the one-liners with map entries. 
- * 
- * @author Hamlet D'Arcy
- */
-class AstSpecificationCompiler implements GroovyInterceptable {
-
-    private final List<ASTNode> expression = []
-
-    /**
-     * Creates the DSL compiler.
-     */
-    AstSpecificationCompiler(@DelegatesTo(AstSpecificationCompiler) Closure spec) {
-        spec.delegate = this
-        spec()
-    }
-
-    /**
-     * Gets the current generated expression.
-     */
-    List<ASTNode> getExpression() {
-        return expression
-    }
-
-    /**
-    * This method takes a List of Classes (a "spec"), and makes sure that the expression field 
-    * contains those classes. It is a safety mechanism to enforce that the DSL is being called
-    * properly. 
-    * 
-    * @param methodName
-    *   the name of the method within the DSL that is being invoked. Used in creating error messages. 
-    * @param spec
-    *   the list of Class objects that the method expects to have in the expression field when invoked.
-    * @return 
-    *   the portions of the expression field that adhere to the spec. 
-    */ 
-    private List<ASTNode> enforceConstraints(String methodName, List<Class> spec) {
-
-        // enforce that the correct # arguments was passed
-        if (spec.size() != expression.size()) {
-            throw new IllegalArgumentException("$methodName could not be invoked. Expected to receive parameters $spec but found ${expression?.collect { it.class }}")
-        }
-
-        // enforce types and collect result
-        (0..(spec.size() - 1)).collect { int it ->
-            def actualClass = expression[it].class
-            def expectedClass = spec[it]
-            if (!expectedClass.isAssignableFrom(actualClass)) {
-                throw new IllegalArgumentException("$methodName could not be invoked. Expected to receive parameters $spec but found ${expression?.collect { it.class }}")
-            }
-            expression[it]
-        }
-    }
-
-    /**
-    * This method helps you take Closure parameters to a method and bundle them into 
-    * constructor calls to a specific ASTNode subtype. 
-    * @param name 
-    *       name of object being constructed, used to create helpful error message. 
-    * @param argBlock
-    *       the actual parameters being specified for the node
-    * @param constructorStatement
-    *       the type specific construction code that will be run
-    */ 
-    private void captureAndCreateNode(String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, Closure constructorStatement) {
-        if (!argBlock) throw new IllegalArgumentException("nodes of type $name require arguments to be specified")
-
-        def oldProps = new ArrayList(expression)
-        expression.clear()
-        new AstSpecificationCompiler(argBlock)
-        def result = constructorStatement(expression) // invoke custom constructor for node
-        expression.clear()
-        expression.addAll(oldProps)
-        expression.add(result)
-    }
-
-    /**
-    * Helper method to convert a DSL invocation into an ASTNode instance. 
-    * 
-    * @param target     
-    *       the class you are going to create
-    * @param typeAlias  
-    *       the DSL keyword that was used to invoke this type
-    * @param ctorArgs   
-    *       a specification of what arguments the constructor expects
-    * @param argBlock   
-    *       the single closure argument used during invocation
-    */ 
-    private void makeNode(Class target, String typeAlias, List<Class<? super ASTNode>> ctorArgs, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode(target.class.simpleName, argBlock) {
-            target.newInstance(*enforceConstraints(typeAlias, ctorArgs))
-        }
-    }
-
-    /**
-    * Helper method to convert a DSL invocation with a list of parameters specified 
-    * in a Closure into an ASTNode instance. 
-    * 
-    * @param target     
-    *       the class you are going to create
-    * @param argBlock   
-    *       the single closure argument used during invocation
-    */ 
-    private void makeNodeFromList(Class target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        //todo: add better error handling?
-        captureAndCreateNode(target.simpleName, argBlock) {
-            target.newInstance(new ArrayList(expression))
-        }
-    }
-
-    /**
-    * Helper method to convert a DSL invocation with a String parameter into a List of ASTNode instances. 
-    * 
-    * @param argBlock   
-    *       the single closure argument used during invocation
-    * @param input   
-    *       the single String argument used during invocation
-    */ 
-    private void makeListOfNodes(@DelegatesTo(AstSpecificationCompiler) Closure argBlock, String input) {
-        captureAndCreateNode(input, argBlock) {
-            new ArrayList(expression)
-        }
-    }
-
-    /**
-    * Helper method to convert a DSL invocation with a String parameter into an Array of ASTNode instances. 
-    * 
-    * @param argBlock   
-    *       the single closure argument used during invocation
-    * @param target   
-    *       the target type
-    */ 
-    private void makeArrayOfNodes(Object target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode(target.class.simpleName, argBlock) {
-            expression.toArray(target)
-        }
-    }
-    
-    /**
-    * Helper method to convert a DSL invocation into an ASTNode instance when a Class parameter is specified. 
-    * 
-    * @param target     
-    *       the class you are going to create
-    * @param alias  
-    *       the DSL keyword that was used to invoke this type
-    * @param spec
-    *       the list of Classes that you expect to be present as parameters
-    * @param argBlock   
-    *       the single closure argument used during invocation
-    * @param type 
-    *       a type parameter
-    */ 
-    private void makeNodeWithClassParameter(Class target, String alias, List<Class> spec, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, Class type) {
-        captureAndCreateNode(target.class.simpleName, argBlock) {
-            expression.add(0, ClassHelper.make(type))
-            target.newInstance(*enforceConstraints(alias, spec))
-        }
-    }
-
-    private void makeNodeWithStringParameter(Class target, String alias, List<Class> spec, @DelegatesTo(AstSpecificationCompiler) Closure argBlock, String text) {
-        captureAndCreateNode(target.class.simpleName, argBlock) {
-            expression.add(0, text)
-            target.newInstance(*enforceConstraints(alias, spec))
-        }
-    }
-
-    /**
-     * Creates a CastExpression.
-     */
-    void cast(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeWithClassParameter(CastExpression, 'cast', [ClassNode, Expression], argBlock, type)
-    }
-
-    /**
-     * Creates an ConstructorCallExpression.
-     */
-    void constructorCall(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeWithClassParameter(ConstructorCallExpression, 'constructorCall', [ClassNode, Expression], argBlock, type)
-    }
-
-    /**
-     * Creates a MethodCallExpression.
-     */
-    void methodCall(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(MethodCallExpression, 'methodCall', [Expression, Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates an AnnotationConstantExpression.
-     */
-    void annotationConstant(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(AnnotationConstantExpression, 'annotationConstant', [AnnotationNode], argBlock)
-    }
-
-    /**
-     * Creates a PostfixExpression.
-     */
-    void postfix(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(PostfixExpression, 'postfix', [Expression, Token], argBlock)
-    }
-
-    /**
-     * Creates a FieldExpression.
-     */
-    void field(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(FieldExpression, 'field', [FieldNode], argBlock)
-    }
-
-    /**
-     * Creates a MapExpression.
-     */
-    void map(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeFromList(MapExpression, argBlock)
-    }
-
-    /**
-     * Creates a TupleExpression.
-     */
-    void tuple(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeFromList(TupleExpression, argBlock)
-    }
-
-    /**
-     * Creates a MapEntryExpression.
-     */
-    void mapEntry(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(MapEntryExpression, 'mapEntry', [Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates a gString.
-     */
-    void gString(String verbatimText, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeWithStringParameter(GStringExpression, 'gString', [String, List, List], argBlock, verbatimText)
-    }
-
-
-    /**
-     * Creates a methodPointer.
-     */
-
-    void methodPointer(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(MethodPointerExpression, 'methodPointer', [Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates a property.
-     */
-    void property(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(PropertyExpression, 'property', [Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates a RangeExpression.
-     */
-    void range(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(RangeExpression, 'range', [Expression, Expression, Boolean], argBlock)
-    }
-
-    /**
-     * Creates EmptyStatement.
-     */
-    void empty() {
-        expression << EmptyStatement.INSTANCE
-    }
-
-    /**
-     * Creates a label.
-     */
-    void label(String label) {
-        expression << label
-    }
-
-    /**
-     * Creates an ImportNode.
-     */
-    void importNode(Class target, String alias = null) {
-        expression << new ImportNode(ClassHelper.make(target), alias)
-    }
-
-    /**
-     * Creates a CatchStatement.
-     */
-    void catchStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(CatchStatement, 'catchStatement', [Parameter, Statement], argBlock)
-    }
-
-    /**
-     * Creates a ThrowStatement.
-     */
-    void throwStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ThrowStatement, 'throwStatement', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a SynchronizedStatement.
-     */
-    void synchronizedStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(SynchronizedStatement, 'synchronizedStatement', [Expression, Statement], argBlock)
-    }
-
-    /**
-     * Creates a ReturnStatement.
-     */
-    void returnStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ReturnStatement, 'returnStatement', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a TernaryExpression.
-     */
-
-    private void ternary(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(TernaryExpression, 'ternary', [BooleanExpression, Expression, Expression], argBlock)
-    }
-
-
-    /**
-     * Creates an ElvisOperatorExpression.
-     */
-    void elvisOperator(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ElvisOperatorExpression, 'elvisOperator', [Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates a BreakStatement.
-     */
-    void breakStatement(String label = null) {
-        if (label) {
-            expression << new BreakStatement(label)
-        } else {
-            expression << new BreakStatement()
-        }
-    }
-
-    /**
-     * Creates a ContinueStatement.
-     */
-    void continueStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
-        if (!argBlock) {
-            expression << new ContinueStatement()
-        } else {
-            makeNode(ContinueStatement, 'continueStatement', [String], argBlock)
-        }
-    }
-
-    /**
-     * Create a CaseStatement.
-     */
-    void caseStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(CaseStatement, 'caseStatement', [Expression, Statement], argBlock)
-    }
-
-    /**
-     * Creates a BlockStatement.
-     */
-    void defaultCase(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        block(argBlock) // same as arg block
-    }
-
-    /**
-     * Creates a PrefixExpression.
-     */
-    void prefix(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(PrefixExpression, 'prefix', [Token, Expression], argBlock)
-    }
-
-    /**
-     * Creates a NotExpression.
-     */
-    void not(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(NotExpression, 'not', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a DynamicVariable.
-     */
-    void dynamicVariable(String variable, boolean isStatic = false) {
-        expression << new DynamicVariable(variable, isStatic)
-    }
-
-    /**
-     * Creates a ClassNode[].
-     */
-    void exceptions(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeArrayOfNodes([] as ClassNode[], argBlock)
-    }
-
-    /**
-     * Designates a list of AnnotationNodes.
-     */
-    void annotations(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<AnnotationNode>")
-    }
-
-
-    /**
-     * Designates a list of MethodNodes.
-     */
-    void methods(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<MethodNode>")
-    }
-
-    /**
-     * Designates a list of ConstructorNodes.
-     */
-    void constructors(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<ConstructorNode>")
-    }
-
-    /**
-     * Designates a list of {@code PropertyNode}s.
-     */
-    void properties(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<PropertyNode>")
-    }
-
-    /**
-     * Designates a list of {@code FieldNode}s.
-     */
-    void fields(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<FieldNode>")
-    }
-
-    /**
-     * Designates a list of ConstantExpressions.
-     */
-
-    void strings(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<ConstantExpression>")
-    }
-
-    /**
-     * Designates a list of Expressions.
-     */
-
-    void values(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<Expression>")
-    }
-
-    /**
-     * Creates a boolean value.
-     */
-    void inclusive(boolean value) {
-        expression << value
-    }
-
-    /**
-     * Creates a ConstantExpression.
-     */
-    void constant(Object value) {
-        expression << new ConstantExpression(value)
-    }
-
-    /**
-     * Creates an IfStatement.
-     */
-    void ifStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(IfStatement, 'ifStatement', [BooleanExpression, Statement, Statement], argBlock)
-    }
-
-    /**
-     * Creates a SpreadExpression.
-     */
-    void spread(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(SpreadExpression, 'spread', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a SpreadMapExpression.
-     */
-    void spreadMap(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(SpreadMapExpression, 'spreadMap', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a WhileStatement.
-     */
-    void whileStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(WhileStatement, 'whileStatement', [BooleanExpression, Statement], argBlock)
-    }
-
-    /**
-     * Create a ForStatement.
-     */
-    void forStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ForStatement, 'forStatement', [Parameter, Expression, Statement], argBlock)
-    }
-
-    /**
-     * Creates a ClosureListExpression.
-     */
-    void closureList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeFromList(ClosureListExpression, argBlock)
-    }
-
-    /**
-     * Creates a DeclarationExpression.
-     */
-    void declaration(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(DeclarationExpression, 'declaration', [Expression, Token, Expression], argBlock)
-    }
-
-    /**
-     * Creates a ListExpression.
-     */
-    void list(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeFromList(ListExpression, argBlock)
-    }
-
-    /**
-     * Creates a BitwiseNegationExpression.
-     */
-    void bitwiseNegation(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(BitwiseNegationExpression, 'bitwiseNegation', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a ClosureExpression.
-     */
-    void closure(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ClosureExpression, 'closure', [Parameter[], Statement], argBlock)
-    }
-
-    /**
-     * Creates a BooleanExpression.
-     */
-    void booleanExpression(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(BooleanExpression, 'booleanExpression', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a BinaryExpression.
-     */
-    void binary(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(BinaryExpression, 'binary', [Expression, Token, Expression], argBlock)
-    }
-
-    /**
-     * Creates a UnaryPlusExpression.
-     */
-    void unaryPlus(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(UnaryPlusExpression, 'unaryPlus', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a ClassExpression.
-     */
-    void classExpression(Class type) {
-        expression << new ClassExpression(ClassHelper.make(type))
-    }
-
-    /**
-     * Creates a UnaryMinusExpression
-     */
-    void unaryMinus(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(UnaryMinusExpression, 'unaryMinus', [Expression], argBlock)
-    }
-
-    /**
-     * Creates an AttributeExpression.
-     */
-    void attribute(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(AttributeExpression, 'attribute', [Expression, Expression], argBlock)
-    }
-
-    /**
-     * Creates an ExpressionStatement.
-     */
-    void expression(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNode(ExpressionStatement, 'expression', [Expression], argBlock)
-    }
-
-    /**
-     * Creates a NamedArgumentListExpression.
-     */
-    void namedArgumentList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeNodeFromList(NamedArgumentListExpression, argBlock)
-    }
-
-    /**
-     * Creates a ClassNode[].
-     */
-    void interfaces(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<ClassNode>")
-    }
-
-    /**
-     * Creates a MixinNode[].
-     */
-    void mixins(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<MixinNode>")
-    }
-
-    /**
-     * Creates a GenericsTypes[].
-     */
-    void genericsTypes(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, "List<GenericsTypes>")
-    }
-
-    /**
-     * Creates a ClassNode.
-     */
-    void classNode(Class target) {
-        expression << ClassHelper.make(target, false)
-    }
-
-    /**
-     * Creates a Parameter[].
-     */
-    void parameters(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeArrayOfNodes([] as Parameter[], argBlock)
-    }
-
-    /**
-     * Creates a BlockStatement.
-     */
-    void block(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("BlockStatement", argBlock) {
-            return new BlockStatement(new ArrayList(expression), new VariableScope())
-        }
-    }
-
-    /**
-     * Creates a Parameter.
-     */
-    void parameter(Map<String, Class> args, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
-        if (!args) throw new IllegalArgumentException()
-        if (args.size() > 1) throw new IllegalArgumentException()
-
-        //todo: add better error handling?
-        if (argBlock) {
-            args.each {name, type ->
-                captureAndCreateNode("Parameter", argBlock) {
-                    new Parameter(ClassHelper.make(type), name, expression[0])
-                }
-            }
-        } else {
-            args.each {name, type ->
-                expression << (new Parameter(ClassHelper.make(type), name))
-            }
-        }
-    }
-
-    /**
-     * Creates an ArrayExpression.
-     */
-    void array(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("ArrayExpression", argBlock) {
-            new ArrayExpression(ClassHelper.make(type), new ArrayList(expression))
-        }
-    }
-
-    /**
-     * Creates a GenericsType.
-     */
-    void genericsType(Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
-        if (argBlock) {
-            captureAndCreateNode("GenericsType", argBlock) {
-                new GenericsType(ClassHelper.make(type), expression[0] as ClassNode[], expression[1])
-            }
-        } else {
-            expression << new GenericsType(ClassHelper.make(type))
-        }
-    }
-
-    /**
-     * Creates a list of upperBound ClassNodes.
-     */
-    void upperBound(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        makeListOfNodes(argBlock, 'List<ClassNode>')
-    }
-
-    /**
-     * Create lowerBound ClassNode.
-     */
-    void lowerBound(Class target) {
-        expression << ClassHelper.make(target)
-    }
-
-    /**
-     * Creates a 2 element list of name and Annotation. Used with Annotation Members.
-     */
-    void member(String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("Annotation Member", argBlock) {
-            [name, expression[0]]
-        }
-    }
-
-    /**
-     * Creates an ArgumentListExpression.
-     */
-    void argumentList(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        if (!argBlock) {
-            expression << new ArgumentListExpression()
-        } else {
-            makeNodeFromList(ArgumentListExpression, argBlock)
-        }
-    }
-
-    /**
-     * Creates an AnnotationNode.
-     */
-    void annotation(Class target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) {
-        if (argBlock) {
-            //todo: add better error handling
-            captureAndCreateNode("ArgumentListExpression", argBlock) {
-                def node = new AnnotationNode(ClassHelper.make(target))
-                expression?.each {
-                    node.addMember(it[0], it[1])
-                }
-                node
-            }
-        } else {
-            expression << new AnnotationNode(ClassHelper.make(target))
-        }
-    }
-
-    /**
-     * Creates a MixinNode.
-     */
-    void mixin(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("AttributeExpression", argBlock) {
-            if (expression.size() > 1) {
-                new MixinNode(name, modifiers, expression[0], new ArrayList(expression[1]) as ClassNode[])
-            } else {
-                new MixinNode(name, modifiers, expression[0])
-            }
-        }
-    }
-
-    /**
-     * Creates a ClassNode
-     */
-    void classNode(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("ClassNode", argBlock) {
-            def result = new ClassNode(name, modifiers,
-                    expression[0],
-                    new ArrayList(expression[1]) as ClassNode[],
-                    new ArrayList(expression[2]) as MixinNode[]
-            )
-            while (expression.size() > 3) {
-                if (!List.isAssignableFrom(expression[3].getClass())) {
-                    throw new IllegalArgumentException("Expecting to find list of additional items instead found: " + expression[3].getClass())
-                }
-                if (expression[3].size() > 0) {
-                    def clazz = expression[3][0].getClass()
-                    switch(clazz) {
-                        case GenericsType:
-                            result.setGenericsTypes(new ArrayList(expression[3]) as GenericsType[])
-                            break
-                        case MethodNode:
-                            expression[3].each{ result.addMethod(it) }
-                            break
-                        case ConstructorNode:
-                            expression[3].each{ result.addConstructor(it) }
-                            break
-                        case PropertyNode:
-                            expression[3].each{
-                                it.field.owner = result
-                                result.addProperty(it)
-                            }
-                            break
-                        case FieldNode:
-                            expression[3].each{
-                                it.owner = result
-                                result.addField(it)
-                            }
-                            break
-                        case AnnotationNode:
-                            result.addAnnotations(new ArrayList(expression[3]))
-                            break
-                        default:
-                            throw new IllegalArgumentException("Unexpected item found in ClassNode spec. Expecting [Field|Method|Property|Constructor|Annotation|GenericsType] but found: $clazz.name")
-                    }
-                }
-                expression.remove(3)
-            }
-            result
-        }
-    }
-
-    /**
-     * Creates an AssertStatement.
-     */
-    void assertStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("AssertStatement", argBlock) {
-            if (expression.size() < 2) {
-                new AssertStatement(*enforceConstraints('assertStatement', [BooleanExpression]))
-            } else {
-                new AssertStatement(*enforceConstraints('assertStatement', [BooleanExpression, Expression]))
-            }
-        }
-    }
-
-    /**
-     * Creates a TryCatchStatement.
-     */
-    void tryCatch(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("TryCatchStatement", argBlock) {
-            def result = new TryCatchStatement(expression[0], expression[1])
-            def catchStatements = expression.tail().tail()
-            catchStatements.each {statement -> result.addCatch(statement) }
-            return result
-        }
-    }
-
-    /**
-     * Creates a VariableExpression.
-     */
-    void variable(String variable) {
-        expression << new VariableExpression(variable)
-    }
-
-    /**
-     * Creates a MethodNode.
-     */
-    void method(String name, int modifiers, Class returnType, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("MethodNode", argBlock) {
-            //todo: enforce contract
-            def result = new MethodNode(name, modifiers, ClassHelper.make(returnType), expression[0], expression[1], expression[2])
-            if (expression[3]) {
-                result.addAnnotations(new ArrayList(expression[3]))
-            }
-            result
-        }
-    }
-
-    /**
-     * Creates a token.
-     */
-    void token(String value) {
-        if (value == null) throw new IllegalArgumentException("Null: value")
-
-        def tokenID = Types.lookupKeyword(value)
-        if (tokenID == Types.UNKNOWN) {
-            tokenID = Types.lookupSymbol(value)
-        }
-        if (tokenID == Types.UNKNOWN) throw new IllegalArgumentException("could not find token for $value")
-
-        expression << new Token(tokenID, value, -1, -1)
-    }
-
-    /**
-     * Creates a RangeExpression.
-     */
-    void range(Range range) {
-        if (range == null) throw new IllegalArgumentException('Null: range')
-        expression << new RangeExpression(new ConstantExpression(range.getFrom()), new ConstantExpression(range.getTo()), true) //default is inclusive
-    }
-
-    /**
-     * Creates a SwitchStatement.
-     */
-    void switchStatement(@DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("SwitchStatement", argBlock) {
-            def switchExpression = expression.head()
-            def caseStatements = expression.tail().tail()
-            def defaultExpression = expression.tail().head()
-            new SwitchStatement(switchExpression, caseStatements, defaultExpression)
-        }
-    }
-
-    /**
-     * Creates a mapEntry.
-     */
-    void mapEntry(Map map) {
-        map.entrySet().each {
-            expression << new MapEntryExpression(
-                    new ConstantExpression(it.key),
-                    new ConstantExpression(it.value))
-        }
-    }
-
-    //
-    // todo: these methods can still be reduced smaller
-    //
-
-    /**
-     * Creates a FieldNode.
-     */
-    void fieldNode(String name, int modifiers, Class type, Class owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("FieldNode", argBlock) {
-            def annotations = null
-            if (expression.size() > 1) {
-                annotations = expression[1]
-                expression.remove(1)
-            }
-            expression.add(0, ClassHelper.make(owner))
-            expression.add(0, ClassHelper.make(type))
-            expression.add(0, modifiers)
-            expression.add(0, name)
-            def result = new FieldNode(*enforceConstraints('fieldNode', [String, Integer, ClassNode, ClassNode, Expression]))
-            if (annotations) {
-                result.addAnnotations(new ArrayList(annotations))
-            }
-            result
-        }
-    }
-
-    /**
-     * Creates an inner class.
-     */
-    void innerClass(String name, int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("InnerClassNode", argBlock) {
-            //todo: enforce contract
-            new InnerClassNode(
-                    expression[0],
-                    name,
-                    modifiers,
-                    expression[1],
-                    new ArrayList(expression[2]) as ClassNode[],
-                    new ArrayList(expression[3]) as MixinNode[])
-        }
-    }
-
-    /**
-     * Creates a PropertyNode.
-     */
-    void propertyNode(String name, int modifiers, Class type, Class owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        //todo: improve error handling?
-        captureAndCreateNode("PropertyNode", argBlock) {
-            def annotations = null
-            // check if the last expression looks like annotations
-            if (List.isAssignableFrom(expression[-1].getClass())) {
-                annotations = expression[-1]
-                expression.remove(expression.size() - 1)
-            }
-            def result = new PropertyNode(name, modifiers, ClassHelper.make(type), ClassHelper.make(owner),
-                    expression[0],  // initial value (possibly null)
-                    expression[1],  // getter block (possibly null)
-                    expression[2])  // setter block (possibly null)
-            if (annotations) {
-                result.addAnnotations(new ArrayList(annotations))
-            }
-            result
-        }
-    }
-
-    /**
-     * Creates a StaticMethodCallExpression.
-     */
-    void staticMethodCall(Class target, String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("StaticMethodCallExpression", argBlock) {
-            expression.add(0, name)
-            expression.add(0, ClassHelper.make(target))
-            new StaticMethodCallExpression(*enforceConstraints('staticMethodCall', [ClassNode, String, Expression]))
-        }
-    }
-
-    /**
-     * Creates a StaticMethodCallExpression.
-     */
-    void staticMethodCall(MethodClosure target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("StaticMethodCallExpression", argBlock) {
-            expression.add(0, target.method)
-            expression.add(0, ClassHelper.makeWithoutCaching(target.owner.class, false))
-            new StaticMethodCallExpression(*enforceConstraints('staticMethodCall', [ClassNode, String, Expression]))
-        }
-    }
-
-    /**
-     * Creates a ConstructorNode.
-     */
-    void constructor(int modifiers, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) {
-        captureAndCreateNode("ConstructorNode", argBlock) {
-            def annotations = null
-            if (expression.size() > 3) {
-                annotations = expression[3]
-                expression.remove(3)
-            }
-            expression.add(0, modifiers)
-            def result = new ConstructorNode(*enforceConstraints('constructor', [Integer, Parameter[], ClassNode[], Statement]))
-            if (annotations) {
-                result.addAnnotations(new ArrayList(annotations))
-            }
-            result
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/AstStringCompiler.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/AstStringCompiler.groovy b/src/main/groovy/AstStringCompiler.groovy
deleted file mode 100644
index 497c125..0000000
--- a/src/main/groovy/AstStringCompiler.groovy
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  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.ast.builder
-
-import groovy.transform.PackageScope
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.ModuleNode
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.CompilerConfiguration
-
-/**
- * This class handles converting Strings to ASTNode lists.
- *
- * @author Hamlet D'Arcy
- */
-@PackageScope class AstStringCompiler {
-    
-    /**
-     * Performs the String source to {@link List} of {@link ASTNode}.
-     *
-     * @param script
-     *      a Groovy script in String form
-     * @param compilePhase
-     *      the int based CompilePhase to compile it to.
-     * @param statementsOnly
-     */
-    List<ASTNode> compile(String script, CompilePhase compilePhase, boolean statementsOnly) {
-        def scriptClassName = "script" + System.currentTimeMillis()
-        GroovyClassLoader classLoader = new GroovyClassLoader()
-        GroovyCodeSource codeSource = new GroovyCodeSource(script, scriptClassName + ".groovy", "/groovy/script")
-        CompilationUnit cu = new CompilationUnit(CompilerConfiguration.DEFAULT, codeSource.codeSource, classLoader)
-        cu.addSource(codeSource.getName(), script);
-        cu.compile(compilePhase.getPhaseNumber())
-        // collect all the ASTNodes into the result, possibly ignoring the script body if desired
-        return cu.ast.modules.inject([]) {List acc, ModuleNode node ->
-            if (node.statementBlock) acc.add(node.statementBlock)
-            node.classes?.each {
-                if (!(it.name == scriptClassName && statementsOnly)) {
-                    acc << it
-                }
-            }
-            acc
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/CollectRecursiveCalls.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/CollectRecursiveCalls.groovy b/src/main/groovy/CollectRecursiveCalls.groovy
deleted file mode 100644
index 2c7e6de..0000000
--- a/src/main/groovy/CollectRecursiveCalls.groovy
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.CodeVisitorSupport
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
-
-/**
- * Collect all recursive calls within method
- *
- * @author Johannes Link
- */
-@CompileStatic
-class CollectRecursiveCalls extends CodeVisitorSupport {
-	MethodNode method
-	List<Expression> recursiveCalls = []
-
-	public void visitMethodCallExpression(MethodCallExpression call) {
-		if (isRecursive(call)) {
-			recursiveCalls << call
-		}
-        super.visitMethodCallExpression(call)
-    }
-
-	public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
-		if (isRecursive(call)) {
-            recursiveCalls << call
-        }
-		super.visitStaticMethodCallExpression(call)
-	}
-	
-	private boolean isRecursive(call) {
-		new RecursivenessTester().isRecursive(method: method, call: call)
-	}
-	
-	synchronized List<Expression> collect(MethodNode method) {
-		recursiveCalls.clear()
-		this.method = method
-		this.method.code.visit(this)
-		recursiveCalls
-	}
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/CompilerCustomizationBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/CompilerCustomizationBuilder.groovy b/src/main/groovy/CompilerCustomizationBuilder.groovy
deleted file mode 100644
index 59b8cc5..0000000
--- a/src/main/groovy/CompilerCustomizationBuilder.groovy
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  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.control.customizers.builder
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.control.CompilerConfiguration
-
-/**
- * <p>A builder which allows easy configuration of compilation customizers. Instead of creating
- * various compilation customizers by hand, you may use this builder instead, which provides a
- * shorter syntax and removes most of the verbosity.
- *
- */
-@CompileStatic
-class CompilerCustomizationBuilder extends FactoryBuilderSupport {
-    public CompilerCustomizationBuilder() {
-        registerFactories()
-    }
-
-    public static CompilerConfiguration withConfig(CompilerConfiguration config, Closure code) {
-        CompilerCustomizationBuilder builder = new CompilerCustomizationBuilder()
-        config.invokeMethod('addCompilationCustomizers', builder.invokeMethod('customizers', code))
-
-        config
-    }
-
-    @Override
-    protected Object postNodeCompletion(final Object parent, final Object node) {
-        Object value = super.postNodeCompletion(parent, node)
-        Object factory = getContextAttribute(CURRENT_FACTORY)
-        if (factory instanceof PostCompletionFactory) {
-            value = factory.postCompleteNode(this, parent, value)
-            setParent(parent, value)
-        }
-
-        value
-    }
-
-    private void registerFactories() {
-        registerFactory("ast", new ASTTransformationCustomizerFactory())
-        registerFactory("customizers", new CustomizersFactory())
-        registerFactory("imports", new ImportCustomizerFactory())
-        registerFactory("inline", new InlinedASTCustomizerFactory())
-        registerFactory("secureAst", new SecureASTCustomizerFactory())
-        registerFactory("source", new SourceAwareCustomizerFactory())
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ConditionalInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ConditionalInterruptibleASTTransformation.groovy b/src/main/groovy/ConditionalInterruptibleASTTransformation.groovy
deleted file mode 100644
index 2cda121..0000000
--- a/src/main/groovy/ConditionalInterruptibleASTTransformation.groovy
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  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.transform
-
-import groovy.transform.ConditionalInterrupt
-import org.codehaus.groovy.ast.AnnotatedNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.FieldNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.PropertyNode
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.tools.ClosureUtils
-import org.codehaus.groovy.control.CompilePhase
-
-/**
- * Allows "interrupt-safe" executions of scripts by adding a custom conditional
- * check on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
- * statement on the beginning of method calls.
- *
- * @see groovy.transform.ConditionalInterrupt
- * @author Cedric Champeau
- * @author Hamlet D'Arcy
- * @author Paul King
- * @since 1.8.0
- */
-@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
-public class ConditionalInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
-
-  private static final ClassNode MY_TYPE = ClassHelper.make(ConditionalInterrupt)
-
-  private ClosureExpression conditionNode
-  private String conditionMethod
-  private MethodCallExpression conditionCallExpression
-  private ClassNode currentClass
-
-  protected ClassNode type() {
-    return MY_TYPE
-  }
-
-  protected void setupTransform(AnnotationNode node) {
-    super.setupTransform(node)
-    def member = node.getMember("value")
-    if (!member || !(member instanceof ClosureExpression)) internalError("Expected closure value for annotation parameter 'value'. Found $member")
-    conditionNode = member;
-    conditionMethod = 'conditionalTransform' + node.hashCode() + '$condition'
-    conditionCallExpression = new MethodCallExpression(new VariableExpression('this'), conditionMethod, new ArgumentListExpression())
-  }
-
-  protected String getErrorMessage() {
-    'Execution interrupted. The following condition failed: ' + convertClosureToSource(conditionNode)
-  }
-
-  void visitClass(ClassNode type) {
-    currentClass = type
-    def method = type.addMethod(conditionMethod, ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, conditionNode.code)
-    method.synthetic = true
-    if (applyToAllMembers) {
-      super.visitClass(type)
-    }
-  }
-
-  protected Expression createCondition() {
-    conditionCallExpression
-  }
-
-  @Override
-  void visitAnnotations(AnnotatedNode node) {
-    // this transformation does not apply on annotation nodes
-    // visiting could lead to stack overflows
-  }
-
-  @Override
-  void visitField(FieldNode node) {
-    if (!node.isStatic() && !node.isSynthetic()) {
-      super.visitField node
-    }
-  }
-
-  @Override
-  void visitProperty(PropertyNode node) {
-    if (!node.isStatic() && !node.isSynthetic()) {
-      super.visitProperty node
-    }
-  }
-
-  @Override
-  void visitClosureExpression(ClosureExpression closureExpr) {
-    if (closureExpr == conditionNode) return // do not visit the closure from the annotation itself
-    def code = closureExpr.code
-    closureExpr.code = wrapBlock(code)
-    super.visitClosureExpression closureExpr
-  }
-
-  @Override
-  void visitMethod(MethodNode node) {
-    if (node.name == conditionMethod && !node.isSynthetic()) return // do not visit the generated method
-    if (node.name == 'run' && currentClass.isScript() && node.parameters.length == 0) {
-      // the run() method should not have the statement added, otherwise the script binding won't be set before
-      // the condition is actually tested
-      super.visitMethod(node)
-    } else {
-      if (checkOnMethodStart && !node.isSynthetic() && !node.isStatic() && !node.isAbstract()) {
-        def code = node.code
-        node.code = wrapBlock(code);
-      }
-      if (!node.isSynthetic() && !node.isStatic()) super.visitMethod(node)
-    }
-  }
-
-  /**
-   * Converts a ClosureExpression into the String source.
-   * @param expression a closure
-   * @return the source the closure was created from
-   */
-  private String convertClosureToSource(ClosureExpression expression) {
-    try {
-        return ClosureUtils.convertClosureToSource(this.source.source, expression);
-    } catch(Exception e) {
-        return e.message
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/GrapeMain.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/GrapeMain.groovy b/src/main/groovy/GrapeMain.groovy
deleted file mode 100644
index c78d25e..0000000
--- a/src/main/groovy/GrapeMain.groovy
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- *  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.tools
-
-import groovy.grape.Grape
-import groovy.transform.Field
-import org.apache.commons.cli.CommandLine
-import org.apache.commons.cli.DefaultParser
-import org.apache.commons.cli.HelpFormatter
-import org.apache.commons.cli.Option
-import org.apache.commons.cli.OptionGroup
-import org.apache.commons.cli.Options
-import org.apache.ivy.util.DefaultMessageLogger
-import org.apache.ivy.util.Message
-
-//commands
-
-@Field install = {arg, cmd ->
-    if (arg.size() > 5 || arg.size() < 3) {
-        println 'install requires two to four arguments: <group> <module> [<version> [<classifier>]]'
-        return
-    }
-    def ver = '*'
-    if (arg.size() >= 4) {
-        ver = arg[3]
-    }
-    def classifier = null
-    if (arg.size() >= 5) {
-        classifier = arg[4]
-    }
-
-    // set the instance so we can re-set the logger
-    Grape.getInstance()
-    setupLogging()
-
-    cmd.getOptionValues('r')?.each { String url ->
-        Grape.addResolver(name:url, root:url)
-    }
-
-    try {
-        Grape.grab(autoDownload: true, group: arg[1], module: arg[2], version: ver, classifier: classifier, noExceptions: true)
-    } catch (Exception e) {
-        println "An error occured : $ex"
-    }
-}
-
-@Field uninstall = {arg, cmd ->
-    if (arg.size() != 4) {
-        println 'uninstall requires three arguments: <group> <module> <version>'
-        // TODO make version optional? support classifier?
-//        println 'uninstall requires two to four arguments, <group> <module> [<version>] [<classifier>]'
-        return
-    }
-    String group = arg[1]
-    String module = arg[2]
-    String ver = arg[3]
-//    def classifier = null
-
-    // set the instance so we can re-set the logger
-    Grape.getInstance()
-    setupLogging()
-
-    if (!Grape.enumerateGrapes().find {String groupName, Map g ->
-        g.any {String moduleName, List<String> versions ->
-            group == groupName && module == moduleName && ver in versions
-        }
-    }) {
-        println "uninstall did not find grape matching: $group $module $ver"
-        def fuzzyMatches = Grape.enumerateGrapes().findAll { String groupName, Map g ->
-            g.any {String moduleName, List<String> versions ->
-                groupName.contains(group) || moduleName.contains(module) ||
-                group.contains(groupName) || module.contains(moduleName)
-            }
-        }
-        if (fuzzyMatches) {
-            println 'possible matches:'
-            fuzzyMatches.each { String groupName, Map g -> println "    $groupName: $g" }
-        }
-        return
-    }
-    Grape.instance.uninstallArtifact(group, module, ver)
-}
-
-@Field list = {arg, cmd ->
-    println ""
-
-    int moduleCount = 0
-    int versionCount = 0
-
-    // set the instance so we can re-set the logger
-    Grape.getInstance()
-    setupLogging()
-
-    Grape.enumerateGrapes().each {String groupName, Map group ->
-        group.each {String moduleName, List<String> versions ->
-            println "$groupName $moduleName  $versions"
-            moduleCount++
-            versionCount += versions.size()
-        }
-    }
-    println ""
-    println "$moduleCount Grape modules cached"
-    println "$versionCount Grape module versions cached"
-}
-
-@Field resolve = {arg, cmd ->
-    Options options = new Options();
-    options.addOption(Option.builder("a").hasArg(false).longOpt("ant").build());
-    options.addOption(Option.builder("d").hasArg(false).longOpt("dos").build());
-    options.addOption(Option.builder("s").hasArg(false).longOpt("shell").build());
-    options.addOption(Option.builder("i").hasArg(false).longOpt("ivy").build());
-    CommandLine cmd2 = new DefaultParser().parse(options, arg[1..-1] as String[], true);
-    arg = cmd2.args
-
-    // set the instance so we can re-set the logger
-    Grape.getInstance()
-    setupLogging(Message.MSG_ERR)
-
-    if ((arg.size() % 3) != 0) {
-        println 'There needs to be a multiple of three arguments: (group module version)+'
-        return
-    }
-    if (args.size() < 3) {
-        println 'At least one Grape reference is required'
-        return
-    }
-    def before, between, after
-    def ivyFormatRequested = false
-
-    if (cmd2.hasOption('a')) {
-        before = '<pathelement location="'
-        between = '">\n<pathelement location="'
-        after = '">'
-    } else if (cmd2.hasOption('d')) {
-        before = 'set CLASSPATH='
-        between = ';'
-        after = ''
-    } else if (cmd2.hasOption('s')) {
-        before = 'export CLASSPATH='
-        between = ':'
-        after = ''
-    } else if (cmd2.hasOption('i')) {
-        ivyFormatRequested = true
-        before = '<dependency '
-        between = '">\n<dependency '
-        after = '">'
-    } else {
-        before = ''
-        between = '\n'
-        after = '\n'
-    }
-
-    iter = arg.iterator()
-    def params = [[:]]
-    def depsInfo = [] // this list will contain the module/group/version info of all resolved dependencies
-    if(ivyFormatRequested) {
-        params << depsInfo
-    }
-    while (iter.hasNext()) {
-        params.add([group: iter.next(), module: iter.next(), version: iter.next()])
-    }
-    try {
-        def results = []
-        def uris = Grape.resolve(* params)
-        if(!ivyFormatRequested) {
-            for (URI uri: uris) {
-                if (uri.scheme == 'file') {
-                    results += new File(uri).path
-                } else {
-                    results += uri.toASCIIString()
-                }
-            }
-        } else {
-            depsInfo.each { dep ->
-                results += ('org="' + dep.group + '" name="' + dep.module + '" revision="' + dep.revision)
-            }
-        }
-
-        if (results) {
-            println "${before}${results.join(between)}${after}"
-        } else {
-            println 'Nothing was resolved'
-        }
-    } catch (Exception e) {
-        println "Error in resolve:\n\t$e.message"
-        if (e.message =~ /unresolved dependency/) println "Perhaps the grape is not installed?"
-    }
-}
-
-@Field help = { arg, cmd -> grapeHelp() }
-
-@Field commands = [
-    'install': [closure: install,
-        shortHelp: 'Installs a particular grape'],
-    'uninstall': [closure: uninstall,
-        shortHelp: 'Uninstalls a particular grape (non-transitively removes the respective jar file from the grape cache)'],
-    'list': [closure: list,
-        shortHelp: 'Lists all installed grapes'],
-    'resolve': [closure: resolve,
-        shortHelp: 'Enumerates the jars used by a grape'],
-    'help': [closure: help,
-        shortHelp: 'Usage information']
-]
-
-@Field grapeHelp = {
-    int spacesLen = commands.keySet().max {it.length()}.length() + 3
-    String spaces = ' ' * spacesLen
-
-    PrintWriter pw = new PrintWriter(binding.variables.out ?: System.out)
-    new HelpFormatter().printHelp(
-            pw,
-            80,
-            "grape [options] <command> [args]\n",
-            "options:",
-            options,
-            2,
-            4,
-            null, // footer
-            true);
-    pw.flush()
-
-    println ""
-    println "commands:"
-    commands.each {String k, v ->
-        println "  ${(k + spaces).substring(0, spacesLen)} $v.shortHelp"
-    }
-    println ""
-}
-
-@Field setupLogging = {int defaultLevel = 2 -> // = Message.MSG_INFO -> some parsing error :(
-    if (cmd.hasOption('q')) {
-        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_ERR))
-    } else if (cmd.hasOption('w')) {
-        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_WARN))
-    } else if (cmd.hasOption('i')) {
-        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_INFO))
-    } else if (cmd.hasOption('V')) {
-        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_VERBOSE))
-    } else if (cmd.hasOption('d')) {
-        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_DEBUG))
-    } else {
-        Message.setDefaultLogger(new DefaultMessageLogger(defaultLevel))
-    }
-}
-
-// command line parsing
-@Field Options options = new Options();
-
-options.addOption(Option.builder("D").longOpt("define").desc("define a system property").numberOfArgs(2).valueSeparator().argName("name=value").build());
-options.addOption(Option.builder("r").longOpt("resolver").desc("define a grab resolver (for install)").hasArg(true).argName("url").build());
-options.addOption(Option.builder("h").hasArg(false).desc("usage information").longOpt("help").build());
-
-// Logging Level Options
-options.addOptionGroup(
-        new OptionGroup()
-                .addOption(Option.builder("q").hasArg(false).desc("Log level 0 - only errors").longOpt("quiet").build())
-                .addOption(Option.builder("w").hasArg(false).desc("Log level 1 - errors and warnings").longOpt("warn").build())
-                .addOption(Option.builder("i").hasArg(false).desc("Log level 2 - info").longOpt("info").build())
-                .addOption(Option.builder("V").hasArg(false).desc("Log level 3 - verbose").longOpt("verbose").build())
-                .addOption(Option.builder("d").hasArg(false).desc("Log level 4 - debug").longOpt("debug").build())
-)
-options.addOption(Option.builder("v").hasArg(false).desc("display the Groovy and JVM versions").longOpt("version").build());
-
-@Field CommandLine cmd
-
-cmd = new DefaultParser().parse(options, args, true);
-
-if (cmd.hasOption('h')) {
-    grapeHelp()
-    return
-}
-
-if (cmd.hasOption('v')) {
-    String version = GroovySystem.getVersion();
-    println "Groovy Version: $version JVM: ${System.getProperty('java.version')}"
-    return
-}
-
-if (options.hasOption('D')) {
-    options.getOptionProperties('D')?.each { k, v ->
-        System.setProperty(k, v)
-    }
-}
-
-String[] arg = cmd.args
-if (arg?.length == 0) {
-    grapeHelp()
-} else if (commands.containsKey(arg[0])) {
-    commands[arg[0]].closure(arg, cmd)
-} else {
-    println "grape: '${arg[0]}' is not a grape command. See 'grape --help'"
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/HasRecursiveCalls.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/HasRecursiveCalls.groovy b/src/main/groovy/HasRecursiveCalls.groovy
deleted file mode 100644
index 79f8e6d..0000000
--- a/src/main/groovy/HasRecursiveCalls.groovy
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.CodeVisitorSupport
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
-
-/**
- *
- * Check if there are any recursive calls in a method
- *
- * @author Johannes Link
- */
-@CompileStatic
-class HasRecursiveCalls extends CodeVisitorSupport {
-    MethodNode method
-    boolean hasRecursiveCalls = false
-
-    public void visitMethodCallExpression(MethodCallExpression call) {
-        if (isRecursive(call)) {
-            hasRecursiveCalls = true
-        } else {
-            super.visitMethodCallExpression(call)
-        }
-    }
-
-    public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
-        if (isRecursive(call)) {
-            hasRecursiveCalls = true
-        } else {
-            super.visitStaticMethodCallExpression(call)
-        }
-    }
-
-    private boolean isRecursive(call) {
-        new RecursivenessTester().isRecursive(method: method, call: call)
-    }
-
-    synchronized boolean test(MethodNode method) {
-        hasRecursiveCalls = false
-        this.method = method
-        this.method.code.visit(this)
-        hasRecursiveCalls
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/InWhileLoopWrapper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/InWhileLoopWrapper.groovy b/src/main/groovy/InWhileLoopWrapper.groovy
deleted file mode 100644
index 0fe2baa..0000000
--- a/src/main/groovy/InWhileLoopWrapper.groovy
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.VariableScope
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.CatchStatement
-import org.codehaus.groovy.ast.stmt.ContinueStatement
-import org.codehaus.groovy.ast.stmt.EmptyStatement
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.ast.stmt.TryCatchStatement
-import org.codehaus.groovy.ast.stmt.WhileStatement
-
-/**
- * Wrap the body of a method in a while loop, nested in a try-catch.
- * This is the first step in making a tail recursive method iterative.
- *
- * There are two ways to invoke the next iteration step:
- * 1. "continue _RECURE_HERE_" is used by recursive calls outside of closures
- * 2. "throw LOOP_EXCEPTION" is used by recursive calls within closures b/c you cannot invoke "continue" from there
- *
- * @author Johannes Link
- */
-@CompileStatic
-class InWhileLoopWrapper {
-	
-	static final String LOOP_LABEL = '_RECUR_HERE_'
-    static final GotoRecurHereException  LOOP_EXCEPTION = new GotoRecurHereException()
-
-	void wrap(MethodNode method) {
-		BlockStatement oldBody = method.code as BlockStatement
-        TryCatchStatement tryCatchStatement = new TryCatchStatement(
-                oldBody,
-                new EmptyStatement()
-        )
-        tryCatchStatement.addCatch(new CatchStatement(
-                new Parameter(ClassHelper.make(GotoRecurHereException), 'ignore'),
-                new ContinueStatement(InWhileLoopWrapper.LOOP_LABEL)
-        ))
-
-        WhileStatement whileLoop = new WhileStatement(
-                new BooleanExpression(new ConstantExpression(true)),
-                new BlockStatement([tryCatchStatement] as List<Statement>, new VariableScope(method.variableScope))
-        )
-        List<Statement> whileLoopStatements = ((BlockStatement) whileLoop.loopBlock).statements
-        if (whileLoopStatements.size() > 0)
-            whileLoopStatements[0].statementLabel = LOOP_LABEL
-		BlockStatement newBody = new BlockStatement([] as List<Statement>, new VariableScope(method.variableScope))
-		newBody.addStatement(whileLoop)
-		method.code = newBody
-	}
-}
-
-/**
- * Exception will be thrown by recursive calls in closures and caught in while loop to continue to LOOP_LABEL
- */
-class GotoRecurHereException extends Throwable {
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/RecursivenessTester.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/RecursivenessTester.groovy b/src/main/groovy/RecursivenessTester.groovy
deleted file mode 100644
index 7c9545a..0000000
--- a/src/main/groovy/RecursivenessTester.groovy
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-
-/**
- *
- * Test if a method call is recursive if called within a given method node.
- * Handles static calls as well.
- * 
- * Currently known simplifications:
- * - Does not check for method overloading or overridden methods.
- * - Does not check for matching return types; even void and any object type are considered to be compatible.
- * - Argument type matching could be more specific in case of static compilation.
- * - Method names via a GString are never considered to be recursive
- * 
- * @author Johannes Link
- */
-class RecursivenessTester {
-	public boolean isRecursive(params) {
-		assert params.method.class == MethodNode
-		assert params.call.class == MethodCallExpression || StaticMethodCallExpression
-
-		isRecursive(params.method, params.call)
-	}
-
-	public boolean isRecursive(MethodNode method, MethodCallExpression call) {
-		if (!isCallToThis(call))
-			return false
-        // Could be a GStringExpression
-        if (! (call.method instanceof ConstantExpression))
-            return false
-		if (call.method.value != method.name)
-			return false
-		methodParamsMatchCallArgs(method, call)
-	}
-
-    public boolean isRecursive(MethodNode method, StaticMethodCallExpression call) {
-        if (!method.isStatic())
-            return false
-        if (method.declaringClass != call.ownerType)
-            return false
-        if (call.method != method.name)
-            return false
-        methodParamsMatchCallArgs(method, call)
-    }
-
-	private boolean isCallToThis(MethodCallExpression call) {
-		if (call.objectExpression == null)
-			return call.isImplicitThis()
-        if (! (call.objectExpression instanceof VariableExpression)) {
-            return false
-        }
-		return call.objectExpression.isThisExpression()
-	}
-	
-	private boolean methodParamsMatchCallArgs(method, call) {
-        if (method.parameters.size() != call.arguments.expressions.size())
-            return false
-        def classNodePairs = [method.parameters*.type, call.arguments*.type].transpose()
-        return classNodePairs.every { ClassNode paramType, ClassNode argType  ->
-            return areTypesCallCompatible(argType, paramType)
-        }
-	}
-
-    /**
-     * Parameter type and calling argument type can both be derived from the other since typing information is
-     * optional in Groovy.
-     * Since int is not derived from Integer (nor the other way around) we compare the boxed types
-     */
-    private areTypesCallCompatible(ClassNode argType, ClassNode paramType) {
-        ClassNode boxedArg = ClassHelper.getWrapper(argType)
-        ClassNode boxedParam = ClassHelper.getWrapper(paramType)
-        return boxedArg.isDerivedFrom(boxedParam) || boxedParam.isDerivedFrom(boxedArg)
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ReturnAdderForClosures.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ReturnAdderForClosures.groovy b/src/main/groovy/ReturnAdderForClosures.groovy
deleted file mode 100644
index 64ebce7..0000000
--- a/src/main/groovy/ReturnAdderForClosures.groovy
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.CodeVisitorSupport
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.Parameter
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.classgen.ReturnAdder
-
-/**
- * Adds explicit return statements to implicit return points in a closure. This is necessary since
- * tail-recursion is detected by having the recursive call within the return statement.
- *
- * @author Johannes Link
- */
-class ReturnAdderForClosures extends CodeVisitorSupport {
-
-    synchronized void visitMethod(MethodNode method) {
-        method.code.visit(this)
-    }
-
-    public void visitClosureExpression(ClosureExpression expression) {
-        //Create a dummy method with the closure's code as the method's code. Then user ReturnAdder, which only works for methods.
-        MethodNode node = new MethodNode("dummy", 0, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, expression.code);
-        new ReturnAdder().visitMethod(node);
-        super.visitClosureExpression(expression)
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ReturnStatementToIterationConverter.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ReturnStatementToIterationConverter.groovy b/src/main/groovy/ReturnStatementToIterationConverter.groovy
deleted file mode 100644
index 2c75f4f..0000000
--- a/src/main/groovy/ReturnStatementToIterationConverter.groovy
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
-import org.codehaus.groovy.ast.expr.TupleExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
-import org.codehaus.groovy.ast.stmt.ReturnStatement
-import org.codehaus.groovy.ast.stmt.Statement
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
-
-/**
- * Translates all return statements into an invocation of the next iteration. This can be either
- * - "continue LOOP_LABEL": Outside closures
- * - "throw LOOP_EXCEPTION": Inside closures
- *
- * Moreover, before adding the recur statement the iteration parameters (originally the method args)
- * are set to their new value. To prevent variable aliasing parameters will be copied into temp vars
- * before they are changes so that their current iteration value can be used when setting other params.
- *
- * There's probably place for optimizing the amount of variable copying being done, e.g.
- * parameters that are only handed through must not be copied at all.
- *
- * @author Johannes Link
- */
-@CompileStatic
-class ReturnStatementToIterationConverter {
-
-    Statement recurStatement = AstHelper.recurStatement()
-
-    Statement convert(ReturnStatement statement, Map<Integer, Map> positionMapping) {
-        Expression recursiveCall = statement.expression
-        if (!isAMethodCalls(recursiveCall))
-            return statement
-
-        Map<String, Map> tempMapping = [:]
-        Map tempDeclarations = [:]
-        List<ExpressionStatement> argAssignments = []
-
-        BlockStatement result = new BlockStatement()
-        result.statementLabel = statement.statementLabel
-
-        /* Create temp declarations for all method arguments.
-         * Add the declarations and var mapping to tempMapping and tempDeclarations for further reference.
-         */
-        getArguments(recursiveCall).eachWithIndex { Expression expression, int index ->
-            ExpressionStatement tempDeclaration = createTempDeclaration(index, positionMapping, tempMapping, tempDeclarations)
-            result.addStatement(tempDeclaration)
-        }
-
-        /*
-         * Assign the iteration variables their new value before recuring
-         */
-        getArguments(recursiveCall).eachWithIndex { Expression expression, int index ->
-            ExpressionStatement argAssignment = createAssignmentToIterationVariable(expression, index, positionMapping)
-            argAssignments.add(argAssignment)
-            result.addStatement(argAssignment)
-        }
-
-        Set<String> unusedTemps = replaceAllArgUsages(argAssignments, tempMapping)
-        for (String temp : unusedTemps) {
-            result.statements.remove(tempDeclarations[temp])
-        }
-        result.addStatement(recurStatement)
-
-        return result
-    }
-
-    private ExpressionStatement createAssignmentToIterationVariable(Expression expression, int index, Map<Integer, Map> positionMapping) {
-        String argName = positionMapping[index]['name']
-        ClassNode argAndTempType = positionMapping[index]['type'] as ClassNode
-        ExpressionStatement argAssignment = (ExpressionStatement) assignS(varX(argName, argAndTempType), expression)
-        argAssignment
-    }
-
-    private ExpressionStatement createTempDeclaration(int index,  Map<Integer, Map> positionMapping, Map<String, Map> tempMapping, Map tempDeclarations) {
-        String argName = positionMapping[index]['name']
-        String tempName = "_${argName}_"
-        ClassNode argAndTempType = positionMapping[index]['type'] as ClassNode
-        ExpressionStatement tempDeclaration = AstHelper.createVariableAlias(tempName, argAndTempType, argName)
-        tempMapping[argName] = [name: tempName, type: argAndTempType]
-        tempDeclarations[tempName] = tempDeclaration
-        return tempDeclaration
-    }
-
-    private List<Expression> getArguments(Expression recursiveCall) {
-        if (recursiveCall instanceof MethodCallExpression)
-            return ((TupleExpression) ((MethodCallExpression) recursiveCall).arguments).expressions
-        if (recursiveCall instanceof StaticMethodCallExpression)
-            return ((TupleExpression) ((StaticMethodCallExpression) recursiveCall).arguments).expressions
-    }
-
-    private boolean isAMethodCalls(Expression expression) {
-        expression.class in [MethodCallExpression, StaticMethodCallExpression]
-    }
-
-    private Set<String> replaceAllArgUsages(List<ExpressionStatement> iterationVariablesAssignmentNodes, Map<String, Map> tempMapping) {
-        Set<String> unusedTempNames = tempMapping.values().collect {Map nameAndType -> (String) nameAndType['name']} as Set<String>
-        VariableReplacedListener tracker = new UsedVariableTracker()
-        for (ExpressionStatement statement : iterationVariablesAssignmentNodes) {
-            replaceArgUsageByTempUsage((BinaryExpression) statement.expression, tempMapping, tracker)
-        }
-        unusedTempNames = unusedTempNames - tracker.usedVariableNames
-        return unusedTempNames
-    }
-
-    private void replaceArgUsageByTempUsage(BinaryExpression binary, Map tempMapping, UsedVariableTracker tracker) {
-        VariableAccessReplacer replacer = new VariableAccessReplacer(nameAndTypeMapping: tempMapping, listener: tracker)
-        // Replacement must only happen in binary.rightExpression. It's a hack in VariableExpressionReplacer which takes care of that.
-        replacer.replaceIn(binary)
-    }
-}
-
-@CompileStatic
-class UsedVariableTracker implements VariableReplacedListener {
-
-    final Set<String> usedVariableNames = [] as Set
-
-    @Override
-    void variableReplaced(VariableExpression oldVar, VariableExpression newVar) {
-        usedVariableNames.add(newVar.name)
-    }
-}


[17/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyShell.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyShell.java b/src/main/groovy/lang/GroovyShell.java
deleted file mode 100644
index 4dc51c9..0000000
--- a/src/main/groovy/lang/GroovyShell.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import groovy.security.GroovyCodeSourcePermission;
-import groovy.ui.GroovyMain;
-import org.apache.groovy.plugin.GroovyRunner;
-import org.apache.groovy.plugin.GroovyRunnerRegistry;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.List;
-
-import static org.codehaus.groovy.runtime.InvokerHelper.MAIN_METHOD_NAME;
-
-/**
- * Represents a groovy shell capable of running arbitrary groovy scripts
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Guillaume Laforge
- * @author Paul King
- */
-public class GroovyShell extends GroovyObjectSupport {
-
-    public static final String DEFAULT_CODE_BASE = "/groovy/shell";
-
-    private final Binding context;
-    private int counter;
-    private final CompilerConfiguration config;
-    private GroovyClassLoader loader;
-
-    public static void main(String[] args) {
-        GroovyMain.main(args);
-    }
-
-    public GroovyShell() {
-        this(null, new Binding());
-    }
-
-    public GroovyShell(Binding binding) {
-        this(null, binding);
-    }
-
-    public GroovyShell(ClassLoader parent, CompilerConfiguration config) {
-        this(parent, new Binding(), config);
-    }
-
-    public GroovyShell(CompilerConfiguration config) {
-        this(new Binding(), config);
-    }
-
-    public GroovyShell(Binding binding, CompilerConfiguration config) {
-        this(null, binding, config);
-    }
-
-    public GroovyShell(ClassLoader parent, Binding binding) {
-        this(parent, binding, CompilerConfiguration.DEFAULT);
-    }
-
-    public GroovyShell(ClassLoader parent) {
-        this(parent, new Binding(), CompilerConfiguration.DEFAULT);
-    }
-    
-    public GroovyShell(ClassLoader parent, Binding binding, final CompilerConfiguration config) {
-        if (binding == null) {
-            throw new IllegalArgumentException("Binding must not be null.");
-        }
-        if (config == null) {
-            throw new IllegalArgumentException("Compiler configuration must not be null.");
-        }
-        final ClassLoader parentLoader = (parent!=null)?parent:GroovyShell.class.getClassLoader();
-        this.loader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
-            public GroovyClassLoader run() {
-                return new GroovyClassLoader(parentLoader,config);
-            }
-        });
-        this.context = binding;        
-        this.config = config;
-    }
-    
-    public void resetLoadedClasses() {
-        loader.clearCache();
-    }
-
-    /**
-     * Creates a child shell using a new ClassLoader which uses the parent shell's
-     * class loader as its parent
-     *
-     * @param shell is the parent shell used for the variable bindings and the parent class loader
-     */
-    public GroovyShell(GroovyShell shell) {
-        this(shell.loader, shell.context);
-    }
-
-    public Binding getContext() {
-        return context;
-    }
-
-    public GroovyClassLoader getClassLoader() {
-        return loader;
-    }
-
-    public Object getProperty(String property) {
-        Object answer = getVariable(property);
-        if (answer == null) {
-            answer = super.getProperty(property);
-        }
-        return answer;
-    }
-
-    public void setProperty(String property, Object newValue) {
-        setVariable(property, newValue);
-        try {
-            super.setProperty(property, newValue);
-        } catch (GroovyRuntimeException e) {
-            // ignore, was probably a dynamic property
-        }
-    }
-
-    //
-    // FIXME: Use List<String> here, current version is not safe
-    //
-
-    /**
-     * A helper method which runs the given script file with the given command line arguments
-     *
-     * @param scriptFile the file of the script to run
-     * @param list       the command line arguments to pass in
-     */
-    public Object run(File scriptFile, List list) throws CompilationFailedException, IOException {
-        String[] args = new String[list.size()];
-        return run(scriptFile, (String[]) list.toArray(args));
-    }
-
-    /**
-     * A helper method which runs the given cl script with the given command line arguments
-     *
-     * @param scriptText is the text content of the script
-     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
-     * @param list       the command line arguments to pass in
-     */
-    public Object run(String scriptText, String fileName, List list) throws CompilationFailedException {
-        String[] args = new String[list.size()];
-        list.toArray(args);
-        return run(scriptText, fileName, args);
-    }
-
-    /**
-     * Runs the given script file name with the given command line arguments
-     *
-     * @param scriptFile the file name of the script to run
-     * @param args       the command line arguments to pass in
-     */
-    public Object run(final File scriptFile, String[] args) throws CompilationFailedException, IOException {
-        String scriptName = scriptFile.getName();
-        int p = scriptName.lastIndexOf(".");
-        if (p++ >= 0) {
-            if (scriptName.substring(p).equals("java")) {
-                throw new CompilationFailedException(0, null);
-            }
-        }
-
-        // Get the current context classloader and save it on the stack
-        final Thread thread = Thread.currentThread();
-        //ClassLoader currentClassLoader = thread.getContextClassLoader();
-
-        class DoSetContext implements PrivilegedAction {
-            ClassLoader classLoader;
-
-            public DoSetContext(ClassLoader loader) {
-                classLoader = loader;
-            }
-
-            public Object run() {
-                thread.setContextClassLoader(classLoader);
-                return null;
-            }
-        }
-
-        AccessController.doPrivileged(new DoSetContext(loader));
-
-        // Parse the script, generate the class, and invoke the main method.  This is a little looser than
-        // if you are compiling the script because the JVM isn't executing the main method.
-        Class scriptClass;
-        try {
-            scriptClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Class>() {
-                public Class run() throws CompilationFailedException, IOException {
-                    return loader.parseClass(scriptFile);
-                }
-            });
-        } catch (PrivilegedActionException pae) {
-            Exception e = pae.getException();
-            if (e instanceof CompilationFailedException) {
-                throw (CompilationFailedException) e;
-            } else if (e instanceof IOException) {
-                throw (IOException) e;
-            } else {
-                throw (RuntimeException) pae.getException();
-            }
-        }
-
-        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
-
-        // Set the context classloader back to what it was.
-        //AccessController.doPrivileged(new DoSetContext(currentClassLoader));
-    }
-
-    /**
-     * if (theClass is a Script) {
-     * run it like a script
-     * } else if (theClass has a main method) {
-     * run the main method
-     * } else if (theClass instanceof GroovyTestCase) {
-     * use the test runner to run it
-     * } else if (theClass implements Runnable) {
-     * if (theClass has a constructor with String[] params)
-     * instantiate theClass with this constructor and run
-     * else if (theClass has a no-args constructor)
-     * instantiate theClass with the no-args constructor and run
-     * }
-     */
-    private Object runScriptOrMainOrTestOrRunnable(Class scriptClass, String[] args) {
-        // Always set the "args" property, regardless of what path we take in the code.
-        // Bad enough to have side effects but worse if their behavior is wonky.
-        context.setProperty("args", args);
-
-        if (scriptClass == null) {
-            return null;
-        }
-
-        //TODO: This logic mostly duplicates InvokerHelper.createScript.  They should probably be unified.
-
-        if (Script.class.isAssignableFrom(scriptClass)) {
-            // treat it just like a script if it is one
-            try {
-                Script script = InvokerHelper.newScript(scriptClass, context);
-                return script.run();
-            } catch (InstantiationException e) {
-                // ignore instantiation errors,, try to do main
-            } catch (IllegalAccessException e) {
-               // ignore instantiation errors, try to do main
-            } catch (InvocationTargetException e) {
-                // ignore instantiation errors, try to do main
-            }
-        }
-        try {
-            // let's find a main method
-            scriptClass.getMethod(MAIN_METHOD_NAME, String[].class);
-            // if that main method exist, invoke it
-            return InvokerHelper.invokeMethod(scriptClass, MAIN_METHOD_NAME, new Object[]{args});
-        } catch (NoSuchMethodException e) {
-            // if it implements Runnable, try to instantiate it
-            if (Runnable.class.isAssignableFrom(scriptClass)) {
-                return runRunnable(scriptClass, args);
-            }
-            GroovyRunnerRegistry runnerRegistry = GroovyRunnerRegistry.getInstance();
-            for (GroovyRunner runner : runnerRegistry) {
-                if (runner.canRun(scriptClass, this.loader)) {
-                    return runner.run(scriptClass, this.loader);
-                }
-            }
-            StringBuilder message = new StringBuilder("This script or class could not be run.\n" +
-                    "It should either:\n" +
-                    "- have a main method,\n" +
-                    "- be a JUnit test or extend GroovyTestCase,\n" +
-                    "- implement the Runnable interface,\n" +
-                    "- or be compatible with a registered script runner. Known runners:\n");
-            if (runnerRegistry.isEmpty()) {
-                message.append("  * <none>");
-            } else {
-                for (String key : runnerRegistry.keySet()) {
-                    message.append("  * ").append(key).append("\n");
-                }
-            }
-            throw new GroovyRuntimeException(message.toString());
-        }
-    }
-
-    private static Object runRunnable(Class scriptClass, String[] args) {
-        Constructor constructor = null;
-        Runnable runnable = null;
-        Throwable reason = null;
-        try {
-            // first, fetch the constructor taking String[] as parameter
-            constructor = scriptClass.getConstructor((new String[]{}).getClass());
-            try {
-                // instantiate a runnable and run it
-                runnable = (Runnable) constructor.newInstance(new Object[]{args});
-            } catch (Throwable t) {
-                reason = t;
-            }
-        } catch (NoSuchMethodException e1) {
-            try {
-                // otherwise, find the default constructor
-                constructor = scriptClass.getConstructor();
-                try {
-                    // instantiate a runnable and run it
-                    runnable = (Runnable) constructor.newInstance();
-                } catch (InvocationTargetException ite) {
-                    throw new InvokerInvocationException(ite.getTargetException());
-                } catch (Throwable t) {
-                    reason = t;
-                }
-            } catch (NoSuchMethodException nsme) {
-                reason = nsme;
-            }
-        }
-        if (constructor != null && runnable != null) {
-            runnable.run();
-        } else {
-            throw new GroovyRuntimeException("This script or class was runnable but could not be run. ", reason);
-        }
-        return null;
-    }
-
-    /**
-     * Runs the given script text with command line arguments
-     *
-     * @param scriptText is the text content of the script
-     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
-     * @param args       the command line arguments to pass in
-     */
-    public Object run(final String scriptText, final String fileName, String[] args) throws CompilationFailedException {
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                return new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE);
-            }
-        });
-        return run(gcs, args);
-    }
-
-    /**
-     * Runs the given script source with command line arguments
-     *
-     * @param source    is the source content of the script
-     * @param args      the command line arguments to pass in
-     */
-    public Object run(GroovyCodeSource source, List args) throws CompilationFailedException {
-        return run(source, ((String[]) args.toArray(new String[args.size()])));
-    }
-
-    /**
-     * Runs the given script source with command line arguments
-     *
-     * @param source    is the source content of the script
-     * @param args      the command line arguments to pass in
-     */
-    public Object run(GroovyCodeSource source, String[] args) throws CompilationFailedException {
-        Class scriptClass = parseClass(source);
-        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
-    }
-
-    /**
-     * Runs the given script source with command line arguments
-     *
-     * @param source    is the source content of the script
-     * @param args      the command line arguments to pass in
-     */
-    public Object run(URI source, List args) throws CompilationFailedException, IOException {
-        return run(new GroovyCodeSource(source), ((String[]) args.toArray(new String[args.size()])));
-    }
-
-    /**
-     * Runs the given script source with command line arguments
-     *
-     * @param source    is the source content of the script
-     * @param args      the command line arguments to pass in
-     */
-    public Object run(URI source, String[] args) throws CompilationFailedException, IOException {
-        return run(new GroovyCodeSource(source), args);
-    }
-
-    /**
-     * Runs the given script with command line arguments
-     *
-     * @param in       the stream reading the script
-     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
-     * @param list     the command line arguments to pass in
-     */
-    public Object run(final Reader in, final String fileName, List list) throws CompilationFailedException {
-        return run(in, fileName, (String[]) list.toArray(new String[list.size()]));
-    }
-
-    /**
-     * Runs the given script with command line arguments
-     *
-     * @param in       the stream reading the script
-     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
-     * @param args     the command line arguments to pass in
-     */
-    public Object run(final Reader in, final String fileName, String[] args) throws CompilationFailedException {
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-                    public GroovyCodeSource run() {
-                        return new GroovyCodeSource(in, fileName, DEFAULT_CODE_BASE);
-                    }
-        });
-        Class scriptClass = parseClass(gcs);
-        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
-    }
-
-    public Object getVariable(String name) {
-        return context.getVariables().get(name);
-    }
-
-    public void setVariable(String name, Object value) {
-        context.setVariable(name, value);
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param codeSource
-     * @throws CompilationFailedException
-     */
-    public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
-        Script script = parse(codeSource);
-        return script.run();
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param scriptText the text of the script
-     */
-    public Object evaluate(final String scriptText) throws CompilationFailedException {
-        return evaluate(scriptText, generateScriptName(), DEFAULT_CODE_BASE);
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param scriptText the text of the script
-     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
-     */
-    public Object evaluate(String scriptText, String fileName) throws CompilationFailedException {
-        return evaluate(scriptText, fileName, DEFAULT_CODE_BASE);
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result.
-     * The .class file created from the script is given the supplied codeBase
-     */
-    public Object evaluate(final String scriptText, final String fileName, final String codeBase) throws CompilationFailedException {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
-        }
-
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                return new GroovyCodeSource(scriptText, fileName, codeBase);
-            }
-        });
-
-        return evaluate(gcs);
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param file is the file of the script (which is used to create the class name of the script)
-     */
-    public Object evaluate(File file) throws CompilationFailedException, IOException {
-        return evaluate(new GroovyCodeSource(file, config.getSourceEncoding()));
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param uri is the URI of the script (which is used to create the class name of the script)
-     */
-    public Object evaluate(URI uri) throws CompilationFailedException, IOException {
-        return evaluate(new GroovyCodeSource(uri));
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param in the stream reading the script
-     */
-    public Object evaluate(Reader in) throws CompilationFailedException {
-        return evaluate(in, generateScriptName());
-    }
-
-    /**
-     * Evaluates some script against the current Binding and returns the result
-     *
-     * @param in       the stream reading the script
-     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
-     */
-    public Object evaluate(Reader in, String fileName) throws CompilationFailedException {
-        Script script = null;
-        try {
-            script = parse(in, fileName);
-            return script.run();
-        } finally {
-            if (script != null) {
-                InvokerHelper.removeClass(script.getClass());
-            }
-        }
-    }
-
-
-    /**
-     * Parses the given script and returns it ready to be run
-     *
-     * @param reader    the stream reading the script
-     * @param fileName  is the logical file name of the script (which is used to create the class name of the script)
-     * @return the parsed script which is ready to be run via {@link Script#run()}
-     */
-    public Script parse(final Reader reader, final String fileName) throws CompilationFailedException {
-        return parse(new GroovyCodeSource(reader, fileName, DEFAULT_CODE_BASE));
-    }
-
-    /**
-     * Parses the groovy code contained in codeSource and returns a java class.
-     */
-    private Class parseClass(final GroovyCodeSource codeSource) throws CompilationFailedException {
-        // Don't cache scripts
-        return loader.parseClass(codeSource, false);
-    }
-
-    /**
-     * Parses the given script and returns it ready to be run.  When running in a secure environment
-     * (-Djava.security.manager) codeSource.getCodeSource() determines what policy grants should be
-     * given to the script.
-     *
-     * @param codeSource
-     * @return ready to run script
-     */
-    public Script parse(final GroovyCodeSource codeSource) throws CompilationFailedException {
-        return InvokerHelper.createScript(parseClass(codeSource), context);
-    }
-
-    /**
-     * Parses the given script and returns it ready to be run
-     *
-     * @param file is the file of the script (which is used to create the class name of the script)
-     */
-    public Script parse(File file) throws CompilationFailedException, IOException {
-        return parse(new GroovyCodeSource(file, config.getSourceEncoding()));
-    }
-
-    /**
-     * Parses the given script and returns it ready to be run
-     *
-     * @param uri is the URI of the script (which is used to create the class name of the script)
-     */
-    public Script parse(URI uri) throws CompilationFailedException, IOException {
-        return parse(new GroovyCodeSource(uri));
-    }
-
-    /**
-     * Parses the given script and returns it ready to be run
-     *
-     * @param scriptText the text of the script
-     */
-    public Script parse(String scriptText) throws CompilationFailedException {
-        return parse(scriptText, generateScriptName());
-    }
-
-    public Script parse(final String scriptText, final String fileName) throws CompilationFailedException {
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                return new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE);
-            }
-        });
-        return parse(gcs);
-    }
-
-    /**
-     * Parses the given script and returns it ready to be run
-     *
-     * @param in the stream reading the script
-     */
-    public Script parse(Reader in) throws CompilationFailedException {
-        return parse(in, generateScriptName());
-    }
-
-    protected synchronized String generateScriptName() {
-        return "Script" + (++counter) + ".groovy";
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovySystem.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovySystem.java b/src/main/groovy/lang/GroovySystem.java
deleted file mode 100644
index cb5ea98..0000000
--- a/src/main/groovy/lang/GroovySystem.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.apache.groovy.plugin.GroovyRunner;
-import org.apache.groovy.plugin.GroovyRunnerRegistry;
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
-import org.codehaus.groovy.util.ReferenceBundle;
-import org.codehaus.groovy.util.ReleaseInfo;
-
-import java.util.Map;
-
-public final class GroovySystem {
-    //
-    //  TODO: make this initialization able to set useReflection true
-    //  TODO: have some way of specifying another MetaClass Registry implementation
-    //
-    static {
-        USE_REFLECTION = true;
-        META_CLASS_REGISTRY = new MetaClassRegistryImpl();
-    }
-    
-    /**
-     * If true then the MetaClass will only use reflection for method dispatch, property access, etc.
-     */
-    @Deprecated
-    private static final boolean USE_REFLECTION;
-
-    /**
-     * Reference to the MetaClass Registry to be used by the Groovy run-time system to map classes to MetaClasses
-     */
-    private static final MetaClassRegistry META_CLASS_REGISTRY;
-
-    /**
-     * Reference to the Runtime Registry to be used by the Groovy run-time system to find classes capable of running scripts
-     *
-     * @deprecated use {@link GroovyRunnerRegistry}
-     */
-    @Deprecated
-    public static final Map<String, GroovyRunner> RUNNER_REGISTRY = GroovyRunnerRegistry.getInstance();
-
-    private static boolean keepJavaMetaClasses=false;
-    
-    private GroovySystem() {
-        // Do not allow this class to be instantiated
-    }
-
-    @Deprecated
-    public static boolean isUseReflection() {
-        return USE_REFLECTION;
-    }
-
-    public static MetaClassRegistry getMetaClassRegistry() {
-        return META_CLASS_REGISTRY;
-    }
-    
-    public static void setKeepJavaMetaClasses(boolean keepJavaMetaClasses) {
-        GroovySystem.keepJavaMetaClasses = keepJavaMetaClasses;
-    }
-    
-    public static boolean isKeepJavaMetaClasses() {
-        return keepJavaMetaClasses;
-    }
-    
-    /**
-     * This method can be used to ensure that no threaded created
-     * by a reference manager will be active. This is useful if the Groovy
-     * runtime itself is loaded through a class loader which should be disposed
-     * off. Without calling this method and if a threaded reference manager is
-     * active the class loader cannot be unloaded!
-     * 
-     * Per default no threaded manager will be used.
-     * 
-     * @since 1.6
-     */
-    public static void stopThreadedReferenceManager() {
-        ReferenceBundle.getSoftBundle().getManager().stopThread();
-        ReferenceBundle.getWeakBundle().getManager().stopThread();
-    }
-
-    /**
-     * Returns the groovy version
-     */
-    public static String getVersion() {
-        return ReleaseInfo.getVersion();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/IllegalPropertyAccessException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/IllegalPropertyAccessException.java b/src/main/groovy/lang/IllegalPropertyAccessException.java
deleted file mode 100644
index 8227e3f..0000000
--- a/src/main/groovy/lang/IllegalPropertyAccessException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-/**
- * An exception occurred if a dynamic property dispatch fails with a 
- * field not accessible.
- * 
- * @author <a href="mailto:blackdrag@uni.de">Jochen Theodorou</a>
- */
-public class IllegalPropertyAccessException extends MissingPropertyException {
-    
-    private static String makeMessage(String propertyName, Class clazz, int modifiers, boolean isField) {
-        String access = "private";
-        if (Modifier.isProtected(modifiers)) access = "protected";
-        if (Modifier.isPublic(modifiers)) access = "public";
-        String propertyType = "property";
-        if (isField) propertyType = "field";
-        return  "Can not access the "+access+" "+propertyType+" "+propertyName+" in class "+clazz.getName();
-    }
-    
-    public IllegalPropertyAccessException(String propertyName, Class clazz, int modifiers) {
-        super(makeMessage(propertyName,clazz,modifiers,false),propertyName,clazz);
-    }
-    
-    public IllegalPropertyAccessException(Field field, Class clazz) {
-        super(makeMessage(field.getName(),clazz,field.getModifiers(),true),field.getName(),clazz);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/IncorrectClosureArgumentsException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/IncorrectClosureArgumentsException.java b/src/main/groovy/lang/IncorrectClosureArgumentsException.java
deleted file mode 100644
index f5b23f5..0000000
--- a/src/main/groovy/lang/IncorrectClosureArgumentsException.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * An exception occurred when invoking a Closure with the wrong number and/or
- * types of arguments
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class IncorrectClosureArgumentsException extends GroovyRuntimeException {
-
-    private final Closure closure;
-    private final Object arguments;
-    private final Class[] expected;
-
-    public IncorrectClosureArgumentsException(Closure closure, Object arguments, Class[] expected) {
-        super(
-            "Incorrect arguments to closure: "
-                + closure
-                + ". Expected: "
-                + InvokerHelper.toString(expected)
-                + ", actual: "
-                + InvokerHelper.toString(arguments));
-        this.closure = closure;
-        this.arguments = arguments;
-        this.expected = expected;
-    }
-
-    public Object getArguments() {
-        return arguments;
-    }
-
-    public Closure getClosure() {
-        return closure;
-    }
-
-    public Class[] getExpected() {
-        return expected;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/IntRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/IntRange.java b/src/main/groovy/lang/IntRange.java
deleted file mode 100644
index 1ca3820..0000000
--- a/src/main/groovy/lang/IntRange.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.IteratorClosureAdapter;
-import org.codehaus.groovy.runtime.RangeInfo;
-
-import java.math.BigInteger;
-import java.util.AbstractList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-/**
- * Represents a list of Integer objects starting at a specified {@code from} value up (or down)
- * to and potentially including a given {@code to} value.
- * <p>
- * Instances of this class may be either inclusive aware or non-inclusive aware. See the
- * relevant constructors for creating each type. Inclusive aware IntRange instances are
- * suitable for use with Groovy's range indexing - in particular if the from or to values
- * might be negative. This normally happens underneath the covers but is worth keeping
- * in mind if creating these ranges yourself explicitly.
- * <p>
- * Note: the design of this class might seem a little strange at first. It contains a Boolean
- * field, {@code inclusive}, which can be {@code true}, {@code false} or {@code null}. This
- * design is for backwards compatibility reasons. Groovy uses this class under the covers
- * to represent range indexing, e.g. {@code someList[x..y]} and {@code someString[x..<y]}.
- * In early versions of Groovy the ranges in these expressions were represented under the
- * covers by the {@code new IntRange(x, y)} and {@code new IntRange(x, y-1)}. This turns
- * out to be a lossy abstraction when x and/or y are negative values. Now the latter case
- * is represented by {@code new IntRange(false, x, y)}.
- * <p>
- * Note: This class is a copy of {@link ObjectRange} optimized for <code>int</code>. If you make any
- * changes to this class, you might consider making parallel changes to {@link ObjectRange}.
- */
-public class IntRange extends AbstractList<Integer> implements Range<Integer> {
-
-    /**
-     * Iterates through each number in an <code>IntRange</code>.
-     */
-    private class IntRangeIterator implements Iterator<Integer> {
-        /**
-         * Counts from 0 up to size - 1.
-         */
-        private int index;
-
-        /**
-         * The number of values in the range.
-         */
-        private int size = size();
-
-        /**
-         * The next value to return.
-         */
-        private int value = isReverse() ? getTo() : getFrom();
-
-        @Override
-        public boolean hasNext() {
-            return index < size;
-        }
-
-        @Override
-        public Integer next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            if (index++ > 0) {
-                if (isReverse()) {
-                    --value;
-                } else {
-                    ++value;
-                }
-            }
-            return value;
-        }
-
-        /**
-         * Not supported.
-         *
-         * @throws java.lang.UnsupportedOperationException always
-         */
-        @Override
-        public void remove() {
-            IntRange.this.remove(index);
-        }
-    }
-
-    /**
-     * For non-inclusive aware ranges, the first number in the range; <code>from</code> is always less than or equal to <code>to</code>.
-     * For inclusive aware ranges, the <code>from</code> argument supplied to the constructor.
-     */
-    private final int from;
-
-    /**
-     * For non-inclusive aware ranges, the last number in the range; <code>to</code> is always greater than or equal to <code>from</code>.
-     * For inclusive aware ranges, the <code>from</code> argument supplied to the constructor.
-     */
-    private final int to;
-
-    /**
-     * If <code>false</code>, counts up from <code>from</code> to <code>to</code>.  Otherwise, counts down
-     * from <code>to</code> to <code>from</code>. Not used for inclusive-aware ranges (inclusive = true|false).
-     */
-    private final boolean reverse;
-
-    /**
-     * If <code>true</code> or null, <code>to</code> is included in the range.
-     * If <code>false</code>, the range stops before the <code>to</code> value.
-     * <p>
-     * Null for non-inclusive-aware ranges (which are inclusive).
-     * <p>
-     * If true or false, the reverse flag is discarded.
-     */
-    private final Boolean inclusive;
-
-    /**
-     * Creates a new non-inclusive aware <code>IntRange</code>. If <code>from</code> is greater than
-     * <code>to</code>, a reverse range is created with <code>from</code> and <code>to</code> swapped.
-     *
-     * @param from the first number in the range.
-     * @param to   the last number in the range.
-     * @throws IllegalArgumentException if the range would contain more than {@link Integer#MAX_VALUE} values.
-     */
-    public IntRange(int from, int to) {
-        this.inclusive = null;
-        if (from > to) {
-            this.from = to;
-            this.to = from;
-            this.reverse = true;
-        } else {
-            this.from = from;
-            this.to = to;
-            this.reverse = false;
-        }
-        checkSize();
-    }
-
-    /**
-     * Creates a new non-inclusive aware <code>IntRange</code>.
-     *
-     * @param from    the first value in the range.
-     * @param to      the last value in the range.
-     * @param reverse <code>true</code> if the range should count from
-     *                <code>to</code> to <code>from</code>.
-     * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
-     */
-    protected IntRange(int from, int to, boolean reverse) {
-        this.inclusive = null;
-        if (from > to) {
-            throw new IllegalArgumentException("'from' must be less than or equal to 'to'");
-        }
-
-        this.from = from;
-        this.to = to;
-        this.reverse = reverse;
-        checkSize();
-    }
-
-    /**
-     * Creates a new inclusive aware <code>IntRange</code>.
-     *
-     * @param from      the first value in the range.
-     * @param to        the last value in the range.
-     * @param inclusive <code>true</code> if the to value is included in the range.
-     */
-    public IntRange(boolean inclusive, int from, int to) {
-        this.from = from;
-        this.to = to;
-        this.inclusive = inclusive;
-        this.reverse = false; // range may still be reversed, this value is ignored for inclusive-aware ranges
-        checkSize();
-    }
-
-    /**
-     * Creates a new NumberRange with the same <code>from</code> and <code>to</code> as this
-     * IntRange but with a step size of <code>stepSize</code>.
-     *
-     * @param stepSize the desired step size
-     * @return a new NumberRange
-     * @since 2.5
-     */
-    public <T extends Number & Comparable> NumberRange by(T stepSize) {
-        return new NumberRange(NumberRange.comparableNumber((Number)from), NumberRange.comparableNumber((Number)to), stepSize, inclusive);
-    }
-
-    private void checkSize() {
-        // size() in the Collection interface returns an integer, so ranges can have no more than Integer.MAX_VALUE elements
-        final Long size = (long) to - from + 1;
-        if (size > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException("A range must have no more than " + Integer.MAX_VALUE + " elements but attempted " + size + " elements");
-        }
-    }
-
-    /**
-     * A method for determining from and to information when using this IntRange to index an aggregate object of the specified size.
-     * Normally only used internally within Groovy but useful if adding range indexing support for your own aggregates.
-     *
-     * @param size the size of the aggregate being indexed
-     * @return the calculated range information (with 1 added to the to value, ready for providing to subList
-     */
-    public RangeInfo subListBorders(int size) {
-        if (inclusive == null) {
-            throw new IllegalStateException("Should not call subListBorders on a non-inclusive aware IntRange");
-        }
-        int tempFrom = from;
-        if (tempFrom < 0) {
-            tempFrom += size;
-        }
-        int tempTo = to;
-        if (tempTo < 0) {
-            tempTo += size;
-        }
-        if (tempFrom > tempTo) {
-            return new RangeInfo(inclusive ? tempTo : tempTo + 1, tempFrom + 1, true);
-        }
-        return new RangeInfo(tempFrom, inclusive ? tempTo + 1 : tempTo, false);
-    }
-
-    /**
-     * Determines if this object is equal to another object. Delegates to
-     * {@link AbstractList#equals(Object)} if <code>that</code> is anything
-     * other than an {@link IntRange}.
-     * <p>
-     * It is not necessary to override <code>hashCode</code>, as
-     * {@link AbstractList#hashCode()} provides a suitable hash code.<p>
-     * <p>
-     * Note that equals is generally handled by {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#equals(List, List)}
-     * instead of this method.
-     *
-     * @param that the object to compare
-     * @return <code>true</code> if the objects are equal
-     */
-    public boolean equals(Object that) {
-        return that instanceof IntRange ? equals((IntRange) that) : super.equals(that);
-    }
-
-    /**
-     * Compares an {@link IntRange} to another {@link IntRange}.
-     *
-     * @param that the object to compare for equality
-     * @return <code>true</code> if the ranges are equal
-     */
-    public boolean equals(IntRange that) {
-        return that != null && ((inclusive == null && reverse == that.reverse && from == that.from && to == that.to)
-                || (inclusive != null && inclusive == that.inclusive && from == that.from && to == that.to));
-    }
-
-    @Override
-    public Integer getFrom() {
-        if (inclusive == null || from <= to) {
-            return from;
-        }
-        return inclusive ? to : to + 1;
-    }
-
-    @Override
-    public Integer getTo() {
-        if (inclusive == null) {
-            return to;
-        }
-        if (from <= to) {
-            return inclusive ? to : to - 1;
-        }
-        return from;
-    }
-
-    /**
-     * Returns the inclusive flag. Null for non-inclusive aware ranges or non-null for inclusive aware ranges.
-     */
-    public Boolean getInclusive() {
-        return inclusive;
-    }
-
-    /**
-     * Gets the 'from' value as a primitive integer.
-     *
-     * @return the 'from' value as a primitive integer.
-     */
-    public int getFromInt() {
-        return getFrom();
-    }
-
-    /**
-     * Gets the 'to' value as a primitive integer.
-     *
-     * @return the 'to' value as a primitive integer.
-     */
-    public int getToInt() {
-        return getTo();
-    }
-
-    @Override
-    public boolean isReverse() {
-        return inclusive == null ? reverse : (from > to);
-    }
-
-    @Override
-    public boolean containsWithinBounds(Object o) {
-        return contains(o);
-    }
-
-    @Override
-    public Integer get(int index) {
-        if (index < 0) {
-            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
-        }
-        if (index >= size()) {
-            throw new IndexOutOfBoundsException("Index: " + index + " too big for range: " + this);
-        }
-        return isReverse() ? getTo() - index : index + getFrom();
-    }
-
-    @Override
-    public int size() {
-        return getTo() - getFrom() + 1;
-    }
-
-    @Override
-    public Iterator<Integer> iterator() {
-        return new IntRangeIterator();
-    }
-
-    @Override
-    public List<Integer> subList(int fromIndex, int toIndex) {
-        if (fromIndex < 0) {
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-        }
-        if (toIndex > size()) {
-            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
-        }
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-
-        if (fromIndex == toIndex) {
-            return new EmptyRange<Integer>(getFrom());
-        }
-
-        return new IntRange(fromIndex + getFrom(), toIndex + getFrom() - 1, isReverse());
-    }
-
-    public String toString() {
-        return inclusive != null ? ("" + from + ".." + (inclusive ? "" : "<") + to)
-                : (reverse ? "" + to + ".." + from : "" + from + ".." + to);
-    }
-
-    @Override
-    public String inspect() {
-        return toString();
-    }
-
-    @Override
-    public boolean contains(Object value) {
-        if (value instanceof Integer) {
-            return (Integer) value >= getFrom() && (Integer) value <= getTo();
-        }
-        if (value instanceof BigInteger) {
-            final BigInteger bigint = (BigInteger) value;
-            return bigint.compareTo(BigInteger.valueOf(getFrom())) >= 0 &&
-                    bigint.compareTo(BigInteger.valueOf(getTo())) <= 0;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean containsAll(Collection other) {
-        if (other instanceof IntRange) {
-            final IntRange range = (IntRange) other;
-            return getFrom() <= range.getFrom() && range.getTo() <= getTo();
-        }
-        return super.containsAll(other);
-    }
-
-    @Override
-    public void step(int step, Closure closure) {
-        if (step == 0) {
-            if (!getFrom().equals(getTo())) {
-                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
-            }
-            return; // from == to and step == 0, nothing to do, so return
-        }
-
-        if (isReverse()) {
-            step = -step;
-        }
-        if (step > 0) {
-            int value = getFrom();
-            while (value <= getTo()) {
-                closure.call(value);
-                if (((long) value + step) >= Integer.MAX_VALUE) {
-                    break;
-                }
-                value = value + step;
-            }
-        } else {
-            int value = getTo();
-            while (value >= getFrom()) {
-                closure.call(value);
-                if (((long) value + step) <= Integer.MIN_VALUE) {
-                    break;
-                }
-                value = value + step;
-            }
-        }
-    }
-
-    @Override
-    public List<Integer> step(int step) {
-        final IteratorClosureAdapter<Integer> adapter = new IteratorClosureAdapter<Integer>(this);
-        step(step, adapter);
-        return adapter.asList();
-    }
-
-    @Override
-    public int hashCode(){
-        int hashCode;
-        final int from = this.getFrom();
-        final int to = this.getTo();
-
-        hashCode = ((from+to+1)*(from+to))/2+to;
-        return hashCode;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Interceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Interceptor.java b/src/main/groovy/lang/Interceptor.java
deleted file mode 100644
index e496f1d..0000000
--- a/src/main/groovy/lang/Interceptor.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Implementers of this interface can be registered in the ProxyMetaClass for
- * notifications about method calls for objects managed by the ProxyMetaClass.
- * See groovy/lang/InterceptorTest.groovy for details.
- * @author Dierk Koenig
- */
-public interface Interceptor {
-    /**
-     * This code is executed before the method is optionally called.
-     * @param object        receiver object for the method call
-     * @param methodName    name of the method to call
-     * @param arguments     arguments to the method call
-     * @return any arbitrary result that replaces the result of the
-     * original method call only if doInvoke() returns false and afterInvoke()
-     * relays this result.
-     */
-    Object beforeInvoke(Object object, String methodName, Object[] arguments);
-    /**
-     * This code is executed after the method is optionally called.
-     * @param object        receiver object for the called method
-     * @param methodName    name of the called method
-     * @param arguments     arguments to the called method
-     * @param result        result of the executed method call or result of beforeInvoke if method was not called
-     * @return any arbitrary result that can replace the result of the
-     * original method call. Typically, the result parameter is returned.
-     */
-    Object afterInvoke(Object object, String methodName, Object[] arguments, Object result);
-    /**
-     * @return whether the target method should be invoked at all.
-     */
-    boolean doInvoke();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Lazy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Lazy.java b/src/main/groovy/lang/Lazy.java
deleted file mode 100644
index c715bc0..0000000
--- a/src/main/groovy/lang/Lazy.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Field annotation to simplify lazy initialization.
- * <p>
- * Example usage without any special modifiers just defers initialization until the first call but is not thread-safe:
- * <pre>
- * {@code @Lazy} T x
- * </pre>
- * becomes
- * <pre>
- * private T $x
- *
- * T getX() {
- *    if ($x != null)
- *       return $x
- *    else {
- *       $x = new T()
- *       return $x
- *    }
- * }
- * </pre>
- *
- * If the field is declared volatile then initialization will be synchronized using
- * the <a href="http://en.wikipedia.org/wiki/Double-checked_locking">double-checked locking</a> pattern as shown here:
- *
- * <pre>
- * {@code @Lazy} volatile T x
- * </pre>
- * becomes
- * <pre>
- * private volatile T $x
- *
- * T getX() {
- *    T $x_local = $x
- *    if ($x_local != null)
- *       return $x_local
- *    else {
- *       synchronized(this) {
- *          if ($x == null) {
- *             $x = new T()
- *          }
- *          return $x
- *       }
- *    }
- * }
- * </pre>
- *
- * By default a field will be initialized by calling its default constructor.
- *
- * If the field has an initial value expression then this expression will be used instead of calling the default constructor.
- * In particular, it is possible to use closure <code>{ ... } ()</code> syntax as follows:
- *
- * <pre>
- * {@code @Lazy} T x = { [1, 2, 3] } ()
- * </pre>
- * becomes
- * <pre>
- * private T $x
- *
- * T getX() {
- *    T $x_local = $x
- *    if ($x_local != null)
- *       return $x_local
- *    else {
- *       synchronized(this) {
- *          if ($x == null) {
- *             $x = { [1, 2, 3] } ()
- *          }
- *          return $x
- *       }
- *    }
- * }
- * </pre>
- * <p>
- * <code>@Lazy(soft=true)</code> will use a soft reference instead of the field and use the above rules each time re-initialization is required.
- * <p>
- * If the <code>soft</code> flag for the annotation is not set but the field is static, then
- * the <a href="http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom">initialization on demand holder idiom</a> is
- * used as follows:
- * <pre>
- * {@code @Lazy} static FieldType field
- * {@code @Lazy} static Date date1
- * {@code @Lazy} static Date date2 = { new Date().copyWith(year: 2000) }()
- * {@code @Lazy} static Date date3 = new GregorianCalendar(2009, Calendar.JANUARY, 1).time
- * </pre>
- * becomes these methods and inners classes within the class containing the above definitions:
- * <pre>
- * private static class FieldTypeHolder_field {
- *     private static final FieldType INSTANCE = new FieldType()
- * }
- *
- * private static class DateHolder_date1 {
- *     private static final Date INSTANCE = new Date()
- * }
- *
- * private static class DateHolder_date2 {
- *     private static final Date INSTANCE = { new Date().copyWith(year: 2000) }()
- * }
- *
- * private static class DateHolder_date3 {
- *     private static final Date INSTANCE = new GregorianCalendar(2009, Calendar.JANUARY, 1).time
- * }
- *
- * static FieldType getField() {
- *     return FieldTypeHolder_field.INSTANCE
- * }
- *
- * static Date getDate1() {
- *     return DateHolder_date1.INSTANCE
- * }
- *
- * static Date getDate2() {
- *     return DateHolder_date2.INSTANCE
- * }
- *
- * static Date getDate3() {
- *     return DateHolder_date3.INSTANCE
- * }
- * </pre>
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.FIELD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.LazyASTTransformation")
-public @interface Lazy {
-    /**
-     * @return if field should be soft referenced instead of hard referenced
-     */
-    boolean soft () default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ListWithDefault.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ListWithDefault.java b/src/main/groovy/lang/ListWithDefault.java
deleted file mode 100644
index 6b87548..0000000
--- a/src/main/groovy/lang/ListWithDefault.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * A wrapper for {@link List} which automatically grows the list when either {@link #get(int)} or
- * {@link #getAt(int)} is called with an index greater than or equal to {@code size()}.
- *
- * @author Andre Steingress
- * @since 1.8.7
- */
-public final class ListWithDefault<T> implements List<T> {
-
-    private final List<T> delegate;
-    private final boolean lazyDefaultValues;
-
-    private final Closure initClosure;
-
-    private ListWithDefault(List<T> items, boolean lazyDefaultValues, Closure initClosure) {
-        this.delegate = items;
-        this.lazyDefaultValues = lazyDefaultValues;
-        this.initClosure = initClosure;
-    }
-
-    public List<T> getDelegate() {
-        return delegate != null ? new ArrayList<T>(delegate) : null;
-    }
-
-    public boolean isLazyDefaultValues() {
-        return lazyDefaultValues;
-    }
-
-    public Closure getInitClosure() {
-        return initClosure != null ? (Closure) initClosure.clone() : null;
-    }
-
-    public static <T> ListWithDefault<T> newInstance(List<T> items, boolean lazyDefaultValues, Closure initClosure) {
-        if (items == null)
-            throw new IllegalArgumentException("Parameter \"items\" must not be null");
-        if (initClosure == null)
-            throw new IllegalArgumentException("Parameter \"initClosure\" must not be null");
-
-        return new ListWithDefault<T>(new ArrayList<T>(items), lazyDefaultValues, (Closure) initClosure.clone());
-    }
-
-    public int size() {
-        return delegate.size();
-    }
-
-    public boolean isEmpty() {
-        return delegate.isEmpty();
-    }
-
-    public boolean contains(Object o) {
-        return delegate.contains(o);
-    }
-
-    public Iterator<T> iterator() {
-        return delegate.iterator();
-    }
-
-    public Object[] toArray() {
-        return delegate.toArray();
-    }
-
-    public <T> T[] toArray(T[] ts) {
-        return delegate.toArray(ts);
-    }
-
-    public boolean add(T t) {
-        return delegate.add(t);
-    }
-
-    public boolean remove(Object o) {
-        return delegate.remove(o);
-    }
-
-    public boolean containsAll(Collection<?> objects) {
-        return delegate.containsAll(objects);
-    }
-
-    public boolean addAll(Collection<? extends T> ts) {
-        return delegate.addAll(ts);
-    }
-
-    public boolean addAll(int i, Collection<? extends T> ts) {
-        return delegate.addAll(i, ts);
-    }
-
-    public boolean removeAll(Collection<?> objects) {
-        return delegate.removeAll(objects);
-    }
-
-    public boolean retainAll(Collection<?> objects) {
-        return delegate.retainAll(objects);
-    }
-
-    public void clear() {
-        delegate.clear();
-    }
-
-    /**
-     * Overwrites subscript operator handling by redirecting to {@link #get(int)}.
-     *
-     * @param index an index (might be greater or equal to {@code size()}, or smaller than 0)
-     * @return the value at the given {@code index} or the default value
-     */
-    public T getAt(int index) {
-        return get(index);
-    }
-
-    /**
-     * Returns the element at the given index but grows the list if needed. If the requested {@code index} is
-     * greater than or equal to {@code size()}, the list will grow to the new size and a default value calculated
-     * using the <code>initClosure</code> will be used to populate the missing value and returned.
-     * <p>
-     * If <code>lazyDefaultValues</code> is <code>true</code> any gaps when growing the list are filled
-     * with nulls. Subsequent attempts to retrieve items from the list from those gap index values
-     * will, upon finding null, call the <code>initClosure</code> to populate the list for the
-     * given list value. Hence, when in this mode, nulls cannot be stored in this list.
-     * If <code>lazyDefaultValues</code> is <code>false</code> any gaps when growing the list are filled
-     * eagerly by calling the <code>initClosure</code> for all gap indexes during list growth.
-     * No calls to <code>initClosure</code> are made except during list growth and it is ok to
-     * store null values in the list when in this mode.
-     * <p>
-     * This implementation breaks
-     * the contract of {@link java.util.List#get(int)} as it a) possibly modifies the underlying list and b) does
-     * NOT throw an {@link IndexOutOfBoundsException} when {@code index < 0 || index >= size()}.
-     *
-     * @param index an index (might be greater or equal to {@code size()}, or smaller than 0)
-     * @return the value at the given {@code index} or the default value
-     */
-    public T get(int index) {
-
-        final int size = size();
-        int normalisedIndex = normaliseIndex(index, size);
-        if (normalisedIndex < 0) {
-            throw new IndexOutOfBoundsException("Negative index [" + normalisedIndex + "] too large for list size " + size);
-        }
-
-        // either index >= size or the normalised index is negative
-        if (normalisedIndex >= size) {
-            // find out the number of gaps to fill with null/the default value
-            final int gapCount = normalisedIndex - size;
-
-            // fill all gaps
-            for (int i = 0; i < gapCount; i++) {
-                final int idx = size();
-
-                // if we lazily create default values, use 'null' as placeholder
-                if (lazyDefaultValues)
-                    delegate.add(idx, null);
-                else
-                    delegate.add(idx, getDefaultValue(idx));
-            }
-
-            // add the first/last element being always the default value
-            final int idx = normalisedIndex;
-            delegate.add(idx, getDefaultValue(idx));
-
-            // normalise index again to get positive index
-            normalisedIndex = normaliseIndex(index, size());
-        }
-
-        T item = delegate.get(normalisedIndex);
-        if (item == null && lazyDefaultValues) {
-            item = getDefaultValue(normalisedIndex);
-            delegate.set(normalisedIndex, item);
-        }
-
-        return item;
-    }
-
-    @SuppressWarnings("unchecked")
-    private T getDefaultValue(int idx) {
-        return (T) initClosure.call(new Object[]{idx});
-    }
-
-    private static int normaliseIndex(int index, int size) {
-        if (index < 0) {
-            index += size;
-        }
-        return index;
-    }
-
-    public T set(int i, T t) {
-        return delegate.set(i, t);
-    }
-
-    public void add(int i, T t) {
-        delegate.add(i, t);
-    }
-
-    public T remove(int i) {
-        return delegate.remove(i);
-    }
-
-    public int indexOf(Object o) {
-        return delegate.indexOf(o);
-    }
-
-    public int lastIndexOf(Object o) {
-        return delegate.lastIndexOf(o);
-    }
-
-    public ListIterator<T> listIterator() {
-        return delegate.listIterator();
-    }
-
-    public ListIterator<T> listIterator(int i) {
-        return delegate.listIterator(i);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return delegate.equals(obj);
-    }
-
-    @Override
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    /**
-     * Returns a view of a portion of this list. This method returns a list with the same
-     * lazy list settings as the original list.
-     *
-     * @param fromIndex low endpoint of the subList (inclusive)
-     * @param toIndex   upper endpoint of the subList (exclusive)
-     * @return a view of a specified range within this list, keeping all lazy list settings
-     */
-    public ListWithDefault<T> subList(int fromIndex, int toIndex) {
-        return new ListWithDefault<T>(delegate.subList(fromIndex, toIndex), lazyDefaultValues, (Closure) initClosure.clone());
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MapWithDefault.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MapWithDefault.java b/src/main/groovy/lang/MapWithDefault.java
deleted file mode 100644
index 166e06b..0000000
--- a/src/main/groovy/lang/MapWithDefault.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A wrapper for Map which allows a default value to be specified.
- *
- * @author Paul King
- * @since 1.7.1
- */
-public final class MapWithDefault<K, V> implements Map<K, V> {
-
-    private final Map<K, V> delegate;
-    private final Closure initClosure;
-
-    private MapWithDefault(Map<K, V> m, Closure initClosure) {
-        delegate = m;
-        this.initClosure = initClosure;
-    }
-
-    public static <K, V> Map<K, V> newInstance(Map<K, V> m, Closure initClosure) {
-        return new MapWithDefault<K, V>(m, initClosure);
-    }
-
-    public int size() {
-        return delegate.size();
-    }
-
-    public boolean isEmpty() {
-        return delegate.isEmpty();
-    }
-
-    public boolean containsKey(Object key) {
-        return delegate.containsKey(key);
-    }
-
-    public boolean containsValue(Object value) {
-        return delegate.containsValue(value);
-    }
-
-    public V get(Object key) {
-        if (!delegate.containsKey(key)) {
-            delegate.put((K)key, (V)initClosure.call(new Object[]{key}));
-        }
-        return delegate.get(key);
-    }
-
-    public V put(K key, V value) {
-        return delegate.put(key, value);
-    }
-
-    public V remove(Object key) {
-        return delegate.remove(key);
-    }
-
-    public void putAll(Map<? extends K, ? extends V> m) {
-        delegate.putAll(m);
-    }
-
-    public void clear() {
-        delegate.clear();
-    }
-
-    public Set<K> keySet() {
-        return delegate.keySet();
-    }
-
-    public Collection<V> values() {
-        return delegate.values();
-    }
-
-    public Set<Map.Entry<K, V>> entrySet() {
-        return delegate.entrySet();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return delegate.equals(obj);
-    }
-
-    @Override
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaArrayLengthProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaArrayLengthProperty.java b/src/main/groovy/lang/MetaArrayLengthProperty.java
deleted file mode 100644
index 8310386..0000000
--- a/src/main/groovy/lang/MetaArrayLengthProperty.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  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 groovy.lang;
-
-
-/**
- * Represents the length property of an array
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class MetaArrayLengthProperty extends MetaProperty {
-
-    /**
-     * Sole constructor setting name to "length" and type to int
-     */
-    public MetaArrayLengthProperty() {
-        super("length", int.class);
-    }
-
-    /**
-     * Get this property from the given object.
-     * @param object an array
-     * @return the length of the array object
-     * @throws IllegalArgumentException if object is not an array
-     */
-    public Object getProperty(Object object) {
-        return java.lang.reflect.Array.getLength(object);
-    }
-
-    /**
-     * Sets the property on the given object to the new value
-     *
-     * @param object   on which to set the property
-     * @param newValue the new value of the property
-     * @throws RuntimeException if the property could not be set
-     */
-    public void setProperty(Object object, Object newValue) {
-        throw new ReadOnlyPropertyException("length", object.getClass());
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaBeanProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaBeanProperty.java b/src/main/groovy/lang/MetaBeanProperty.java
deleted file mode 100644
index 89328af..0000000
--- a/src/main/groovy/lang/MetaBeanProperty.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.reflection.CachedField;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.lang.reflect.Modifier;
-
-/**
- * Represents a property on a bean which may have a getter and/or a setter
- */
-public class MetaBeanProperty extends MetaProperty {
-
-    private MetaMethod getter;
-    private MetaMethod setter;
-    private CachedField field;
-
-    /**
-     * Sole constructor setting name, type (class), getter and setter.
-     */
-    public MetaBeanProperty(String name, Class type, MetaMethod getter, MetaMethod setter) {
-        super(name, type);
-        this.getter = getter;
-        this.setter = setter;
-    }
-
-    /**
-     * Get the property of the given object.
-     *
-     * @param object which to be got
-     * @return the property of the given object
-     * @throws RuntimeException if the property could not be evaluated
-     */
-    public Object getProperty(Object object) {
-        MetaMethod getter = getGetter();
-        if (getter == null) {
-            if (field != null) return field.getProperty(object);
-            //TODO: create a WriteOnlyException class?
-            throw new GroovyRuntimeException("Cannot read write-only property: " + name);
-        }
-        return getter.invoke(object, MetaClassHelper.EMPTY_ARRAY);
-    }
-
-    /**
-     * Set the property on the given object to the new value.
-     *
-     * @param object   on which to set the property
-     * @param newValue the new value of the property
-     * @throws RuntimeException if the property could not be set
-     */
-    public void setProperty(Object object, Object newValue) {
-        MetaMethod setter = getSetter();
-        if (setter == null) {
-            if (field != null && !Modifier.isFinal(field.getModifiers())) {
-                field.setProperty(object, newValue);
-                return;
-            }
-            throw new GroovyRuntimeException("Cannot set read-only property: " + name);
-        }
-        newValue = DefaultTypeTransformation.castToType(newValue, getType());
-        setter.invoke(object, new Object[]{newValue});
-    }
-
-    /**
-     * Get the getter method.
-     *
-     * @return the getter method for this property.
-     */
-    public MetaMethod getGetter() {
-        return getter;
-    }
-
-    /**
-     * Get the setter method.
-     *
-     * @return the setter method for this property.
-     */
-    public MetaMethod getSetter() {
-        return setter;
-    }
-
-    /**
-     * This is for MetaClass to patch up the object later when looking for get*() methods.
-     *
-     * @param getter The getter for this property
-     */
-    void setGetter(MetaMethod getter) {
-        this.getter = getter;
-    }
-
-    /**
-     * This is for MetaClass to patch up the object later when looking for set*() methods.
-     *
-     * @param setter The setter for this property 
-     */
-    void setSetter(MetaMethod setter) {
-        this.setter = setter;
-    }
-
-    /**
-     * Gets the visibility modifiers for the property as defined by the getter and setter methods.
-     *
-     * @return the visibility modifier of the getter, the setter, or both depending on which exist
-     */
-    public int getModifiers() {
-        MetaMethod getter = getGetter();
-        MetaMethod setter = getSetter();
-        if (setter != null && getter == null) return setter.getModifiers();
-        if (getter != null && setter == null) return getter.getModifiers();
-        int modifiers = getter.getModifiers() | setter.getModifiers();
-        int visibility = 0;
-        if (Modifier.isPublic(modifiers)) visibility = Modifier.PUBLIC;
-        if (Modifier.isProtected(modifiers)) visibility = Modifier.PROTECTED;
-        if (Modifier.isPrivate(modifiers)) visibility = Modifier.PRIVATE;
-        int states = getter.getModifiers() & setter.getModifiers();
-        states &= ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);
-        states |= visibility;
-        return states;
-    }
-
-    /**
-     * Sets the field of this property
-     *
-     * @param field
-     */
-    public void setField(CachedField field) {
-        this.field = field;
-    }
-
-    /**
-     * Gets the field of this property
-     *
-     * @return The field of this property
-     */
-    public CachedField getField() {
-        return field;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/MetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClass.java b/src/main/groovy/lang/MetaClass.java
deleted file mode 100644
index 42c6a83..0000000
--- a/src/main/groovy/lang/MetaClass.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.ast.ClassNode;
-
-import java.util.List;
-
-/**
- * A MetaClass within Groovy defines the behaviour of any given Groovy or Java class. The MetaClass
- * interface defines two parts. The client API, which is defined via the extend MetaObjectProtocol interface
- * and the contract with the Groovy runtime system.
- *
- * In general the compiler and Groovy runtime engine interact with methods on this class whilst MetaClass
- * clients interact with the method defined by the MetaObjectProtocol interface
- *
- * @see MetaClassImpl
- * @see groovy.lang.MetaObjectProtocol
- * 
- * @author John Wilson
- * @author Graeme Rocher
- */
-public interface MetaClass extends MetaObjectProtocol {
-
-    /**
-     * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
-     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
-     *
-     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
-     * to the super class if necessary
-     *
-     * @param sender The java.lang.Class instance that invoked the method
-     * @param receiver The object which the method was invoked on
-     * @param methodName The name of the method
-     * @param arguments The arguments to the method
-     * @param isCallToSuper Whether the method is a call to a super class method
-     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
-     *
-     * @return The return value of the method
-     */
-     Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass);
-
-    /**
-     * <p>Retrieves a property on the given receiver for the specified arguments. The sender is the class that is requesting the property from the object.
-     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
-     *
-     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
-     * to the super class if necessary
-     *
-     * @param sender The java.lang.Class instance that requested the property
-     * @param receiver The Object which the property is being retrieved from
-     * @param property The name of the property
-     * @param isCallToSuper Whether the call is to a super class property
-     * @param fromInsideClass ??
-     *
-     * @return The properties value
-     */
-     Object getProperty(Class sender, Object receiver, String property, boolean isCallToSuper, boolean fromInsideClass);
-
-    /**
-     * <p>Sets a property on the given receiver for the specified arguments. The sender is the class that is setting the property from the object.
-     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
-     *
-     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
-     * to the super class if necessary
-     *
-     * @param sender The java.lang.Class instance that is mutating the property
-     * @param receiver The Object which the property is being set on
-     * @param property The name of the property
-     * @param value The new value of the property to set
-     * @param isCallToSuper Whether the call is to a super class property
-     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
-     */
-     void setProperty(Class sender, Object receiver, String property, Object value, boolean isCallToSuper, boolean fromInsideClass);
-
-    /**
-     *
-     * <p>Attempts to invoke the methodMissing method otherwise throws a MissingMethodException
-     *
-     * @see groovy.lang.MissingMethodException
-     *
-     * @param instance The instance to invoke methodMissing on
-     * @param methodName The name of the method
-     * @param arguments The arguments to the method
-     * @return The results of methodMissing or throws MissingMethodException
-     */
-     Object invokeMissingMethod(Object instance, String methodName, Object[] arguments);
-
-    /**
-     * Invokes the propertyMissing method otherwise throws a MissingPropertyException
-     *
-     * @param instance The instance of the class
-     * @param propertyName The name of the property
-     * @param optionalValue The value of the property which could be null in the case of a getter
-     * @param isGetter Whether the missing property event was the result of a getter or a setter
-     * 
-     * @return The result of the propertyMissing method or throws MissingPropertyException
-     */
-     Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter);
-
-    /**
-     * Retrieves the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
-     *
-     * @param sender The class of the object that requested the attribute
-     * @param receiver The instance
-     * @param messageName The name of the attribute
-     * @param useSuper Whether to look-up on the super class or not
-     * @return The attribute value
-     */
-     Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper);
-
-    /**
-     * Sets the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
-     *
-     * @param sender The class of the object that requested the attribute
-     * @param receiver The instance
-     * @param messageName The name of the attribute
-     * @param messageValue The value of the attribute
-     * @param useSuper Whether to look-up on the super class or not
-     * @param fromInsideClass Whether the call happened from the inside or the outside of a class
-     */
-     void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass);
-    
-    /**
-     * Complete the initialisation process. After this method
-     * is called no methods should be added to the meta class.
-     * Invocation of methods or access to fields/properties is
-     * forbidden unless this method is called. This method 
-     * should contain any initialisation code, taking a longer
-     * time to complete. An example is the creation of the 
-     * Reflector. It is suggested to synchronize this 
-     * method.
-     */
-     void initialize();
-
-    /**
-     * Retrieves a list of MetaProperty instances that the MetaClass has
-     *
-     * @see MetaProperty
-     *
-     * @return A list of MetaProperty instances
-     */
-     List<MetaProperty> getProperties();
-
-    /**
-     * Retrieves a list of MetaMethods held by the class. This list does not include MetaMethods added by groovy.lang.ExpandoMetaClass.
-     *
-     * @return A list of MetaMethods
-     */
-     List<MetaMethod> getMethods();
-     
-     /**
-      * Obtains a reference to the original AST for the MetaClass if it is available at runtime
-      *
-      * @return The original AST or null if it cannot be returned
-      */
-     ClassNode getClassNode();
-
-     /**
-      * Retrieves a list of MetaMethods held by this class. This list includes MetaMethods added by groovy.lang.ExpandoMetaClass.
-      *
-      * @return A list of MetaMethods
-      */
-     List<MetaMethod> getMetaMethods();
-    
-     /**
-      *
-      * Internal method to support Groovy runtime. Not for client usage.
-      *
-      * @param numberOfConstructors The number of constructors
-      * @param arguments The arguments
-      *
-      * @return selected index
-      */
-     int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments);
-
-    /**
-     * Selects a method by name and argument classes. This method
-     * does not search for an exact match, it searches for a compatible
-     * method. For this the method selection mechanism is used as provided
-     * by the implementation of this MetaClass. pickMethod may or may
-     * not be used during the method selection process when invoking a method.
-     * There is no warranty for that.
-     *
-     * @return a matching MetaMethod or null
-     * @throws GroovyRuntimeException if there is more than one matching method
-     * @param methodName the name of the method to pick
-     * @param arguments the method arguments
-     */
-     MetaMethod pickMethod(String methodName, Class[] arguments);
-}


[40/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/inspect/Inspector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/inspect/Inspector.java b/src/main/groovy/groovy/inspect/Inspector.java
new file mode 100644
index 0000000..f0c94a7
--- /dev/null
+++ b/src/main/groovy/groovy/inspect/Inspector.java
@@ -0,0 +1,348 @@
+/*
+ *  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 groovy.inspect;
+
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+import groovy.lang.MetaMethod;
+import groovy.lang.PropertyValue;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The Inspector provides a unified access to an object's
+ * information that can be determined by introspection.
+ *
+ * @author Dierk Koenig
+ */
+public class Inspector {
+    protected Object objectUnderInspection;
+
+    // Indexes to retrieve Class Property information
+    public static final int CLASS_PACKAGE_IDX = 0;
+    public static final int CLASS_CLASS_IDX = 1;
+    public static final int CLASS_INTERFACE_IDX = 2;
+    public static final int CLASS_SUPERCLASS_IDX = 3;
+    public static final int CLASS_OTHER_IDX = 4;
+
+    // Indexes to retrieve field and method information
+    public static final int MEMBER_ORIGIN_IDX = 0;
+    public static final int MEMBER_MODIFIER_IDX = 1;
+    public static final int MEMBER_DECLARER_IDX = 2;
+    public static final int MEMBER_TYPE_IDX = 3;
+    public static final int MEMBER_NAME_IDX = 4;
+    public static final int MEMBER_PARAMS_IDX = 5;
+    public static final int MEMBER_VALUE_IDX = 5;
+    public static final int MEMBER_EXCEPTIONS_IDX = 6;
+
+    public static final String NOT_APPLICABLE = "n/a";
+    public static final String GROOVY = "GROOVY";
+    public static final String JAVA = "JAVA";
+
+    /**
+     * @param objectUnderInspection must not be null
+     */
+    public Inspector(Object objectUnderInspection) {
+        if (null == objectUnderInspection) {
+            throw new IllegalArgumentException("argument must not be null");
+        }
+        this.objectUnderInspection = objectUnderInspection;
+    }
+
+    /**
+     * Get the Class Properties of the object under inspection.
+     *
+     * @return String array to be indexed by the CLASS_xxx_IDX constants
+     */
+    public String[] getClassProps() {
+        String[] result = new String[CLASS_OTHER_IDX + 1];
+        Package pack = getClassUnderInspection().getPackage();
+        result[CLASS_PACKAGE_IDX] = "package " + ((pack == null) ? NOT_APPLICABLE : pack.getName());
+        String modifiers = Modifier.toString(getClassUnderInspection().getModifiers());
+        result[CLASS_CLASS_IDX] = modifiers + " class " + shortName(getClassUnderInspection());
+        result[CLASS_INTERFACE_IDX] = "implements ";
+        Class[] interfaces = getClassUnderInspection().getInterfaces();
+        for (Class anInterface : interfaces) {
+            result[CLASS_INTERFACE_IDX] += shortName(anInterface) + " ";
+        }
+        result[CLASS_SUPERCLASS_IDX] = "extends " + shortName(getClassUnderInspection().getSuperclass());
+        result[CLASS_OTHER_IDX] = "is Primitive: " + getClassUnderInspection().isPrimitive()
+                + ", is Array: " + getClassUnderInspection().isArray()
+                + ", is Groovy: " + isGroovy();
+        return result;
+    }
+
+    public boolean isGroovy() {
+        return GroovyObject.class.isAssignableFrom(getClassUnderInspection());
+    }
+
+    /**
+     * Gets the object being inspected.
+     *
+     * @return the object
+     */
+    public Object getObject() {
+        return objectUnderInspection;
+    }
+
+    /**
+     * Get info about usual Java instance and class Methods as well as Constructors.
+     *
+     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
+     */
+    public Object[] getMethods() {
+        Method[] methods = getClassUnderInspection().getMethods();
+        Constructor[] ctors = getClassUnderInspection().getConstructors();
+        Object[] result = new Object[methods.length + ctors.length];
+        int resultIndex = 0;
+        for (; resultIndex < methods.length; resultIndex++) {
+            Method method = methods[resultIndex];
+            result[resultIndex] = methodInfo(method);
+        }
+        for (int i = 0; i < ctors.length; i++, resultIndex++) {
+            Constructor ctor = ctors[i];
+            result[resultIndex] = methodInfo(ctor);
+        }
+        return result;
+    }
+
+    /**
+     * Get info about instance and class Methods that are dynamically added through Groovy.
+     *
+     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
+     */
+    public Object[] getMetaMethods() {
+        MetaClass metaClass = InvokerHelper.getMetaClass(objectUnderInspection);
+        List metaMethods = metaClass.getMetaMethods();
+        Object[] result = new Object[metaMethods.size()];
+        int i = 0;
+        for (Iterator iter = metaMethods.iterator(); iter.hasNext(); i++) {
+            MetaMethod metaMethod = (MetaMethod) iter.next();
+            result[i] = methodInfo(metaMethod);
+        }
+        return result;
+    }
+
+    /**
+     * Get info about usual Java public fields incl. constants.
+     *
+     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
+     */
+    public Object[] getPublicFields() {
+        Field[] fields = getClassUnderInspection().getFields();
+        Object[] result = new Object[fields.length];
+        for (int i = 0; i < fields.length; i++) {
+            Field field = fields[i];
+            result[i] = fieldInfo(field);
+        }
+        return result;
+    }
+
+    /**
+     * Get info about Properties (Java and Groovy alike).
+     *
+     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
+     */
+    public Object[] getPropertyInfo() {
+        List props = DefaultGroovyMethods.getMetaPropertyValues(objectUnderInspection);
+        Object[] result = new Object[props.size()];
+        int i = 0;
+        for (Iterator iter = props.iterator(); iter.hasNext(); i++) {
+            PropertyValue pv = (PropertyValue) iter.next();
+            result[i] = fieldInfo(pv);
+        }
+        return result;
+    }
+
+    protected String[] fieldInfo(Field field) {
+        String[] result = new String[MEMBER_VALUE_IDX + 1];
+        result[MEMBER_ORIGIN_IDX] = JAVA;
+        result[MEMBER_MODIFIER_IDX] = Modifier.toString(field.getModifiers());
+        result[MEMBER_DECLARER_IDX] = shortName(field.getDeclaringClass());
+        result[MEMBER_TYPE_IDX] = shortName(field.getType());
+        result[MEMBER_NAME_IDX] = field.getName();
+        try {
+            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(field.get(objectUnderInspection));
+        } catch (IllegalAccessException e) {
+            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
+        }
+        return withoutNulls(result);
+    }
+
+    protected String[] fieldInfo(PropertyValue pv) {
+        String[] result = new String[MEMBER_VALUE_IDX + 1];
+        result[MEMBER_ORIGIN_IDX] = GROOVY;
+        result[MEMBER_MODIFIER_IDX] = "public";
+        result[MEMBER_DECLARER_IDX] = NOT_APPLICABLE;
+        result[MEMBER_TYPE_IDX] = shortName(pv.getType());
+        result[MEMBER_NAME_IDX] = pv.getName();
+        try {
+            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(pv.getValue());
+        } catch (Exception e) {
+            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
+        }
+        return withoutNulls(result);
+    }
+
+    protected Class getClassUnderInspection() {
+        return objectUnderInspection.getClass();
+    }
+
+    public static String shortName(Class clazz) {
+        if (null == clazz) return NOT_APPLICABLE;
+        String className = clazz.getName();
+        if (null == clazz.getPackage()) return className;
+        String packageName = clazz.getPackage().getName();
+        int offset = packageName.length();
+        if (offset > 0) offset++;
+        className = className.substring(offset);
+        return className;
+    }
+
+    protected String[] methodInfo(Method method) {
+        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
+        int mod = method.getModifiers();
+        result[MEMBER_ORIGIN_IDX] = JAVA;
+        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass());
+        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
+        result[MEMBER_NAME_IDX] = method.getName();
+        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
+        Class[] params = method.getParameterTypes();
+        StringBuilder sb = new StringBuilder();
+        for (int j = 0; j < params.length; j++) {
+            sb.append(shortName(params[j]));
+            if (j < (params.length - 1)) sb.append(", ");
+        }
+        result[MEMBER_PARAMS_IDX] = sb.toString();
+        sb.setLength(0);
+        Class[] exceptions = method.getExceptionTypes();
+        for (int k = 0; k < exceptions.length; k++) {
+            sb.append(shortName(exceptions[k]));
+            if (k < (exceptions.length - 1)) sb.append(", ");
+        }
+        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
+        return withoutNulls(result);
+    }
+
+    protected String[] methodInfo(Constructor ctor) {
+        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
+        int mod = ctor.getModifiers();
+        result[MEMBER_ORIGIN_IDX] = JAVA;
+        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
+        result[MEMBER_DECLARER_IDX] = shortName(ctor.getDeclaringClass());
+        result[MEMBER_TYPE_IDX] = shortName(ctor.getDeclaringClass());
+        result[MEMBER_NAME_IDX] = ctor.getName();
+        Class[] params = ctor.getParameterTypes();
+        StringBuilder sb = new StringBuilder();
+        for (int j = 0; j < params.length; j++) {
+            sb.append(shortName(params[j]));
+            if (j < (params.length - 1)) sb.append(", ");
+        }
+        result[MEMBER_PARAMS_IDX] = sb.toString();
+        sb.setLength(0);
+        Class[] exceptions = ctor.getExceptionTypes();
+        for (int k = 0; k < exceptions.length; k++) {
+            sb.append(shortName(exceptions[k]));
+            if (k < (exceptions.length - 1)) sb.append(", ");
+        }
+        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
+        return withoutNulls(result);
+    }
+
+    protected String[] methodInfo(MetaMethod method) {
+        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
+        int mod = method.getModifiers();
+        result[MEMBER_ORIGIN_IDX] = GROOVY;
+        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
+        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass().getTheClass());
+        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
+        result[MEMBER_NAME_IDX] = method.getName();
+        CachedClass[] params = method.getParameterTypes();
+        StringBuilder sb = new StringBuilder();
+        for (int j = 0; j < params.length; j++) {
+            sb.append(shortName(params[j].getTheClass()));
+            if (j < (params.length - 1)) sb.append(", ");
+        }
+        result[MEMBER_PARAMS_IDX] = sb.toString();
+        result[MEMBER_EXCEPTIONS_IDX] = NOT_APPLICABLE; // no exception info for Groovy MetaMethods
+        return withoutNulls(result);
+    }
+
+    protected String[] withoutNulls(String[] toNormalize) {
+        for (int i = 0; i < toNormalize.length; i++) {
+            String s = toNormalize[i];
+            if (null == s) toNormalize[i] = NOT_APPLICABLE;
+        }
+        return toNormalize;
+    }
+
+    public static void print(Object[] memberInfo) {
+        print(System.out, memberInfo);
+    }
+
+    static void print(final PrintStream out, Object[] memberInfo) {
+        for (int i = 0; i < memberInfo.length; i++) {
+            String[] metaMethod = (String[]) memberInfo[i];
+            out.print(i + ":\t");
+            for (String s : metaMethod) {
+                out.print(s + " ");
+            }
+            out.println("");
+        }
+    }
+
+    public static Collection sort(List<Object> memberInfo) {
+        Collections.sort(memberInfo, new MemberComparator());
+        return memberInfo;
+    }
+
+    public static class MemberComparator implements Comparator<Object>, Serializable {
+        private static final long serialVersionUID = -7691851726606749541L;
+
+        public int compare(Object a, Object b) {
+            String[] aStr = (String[]) a;
+            String[] bStr = (String[]) b;
+            int result = aStr[Inspector.MEMBER_NAME_IDX].compareTo(bStr[Inspector.MEMBER_NAME_IDX]);
+            if (0 != result) return result;
+            result = aStr[Inspector.MEMBER_TYPE_IDX].compareTo(bStr[Inspector.MEMBER_TYPE_IDX]);
+            if (0 != result) return result;
+            result = aStr[Inspector.MEMBER_PARAMS_IDX].compareTo(bStr[Inspector.MEMBER_PARAMS_IDX]);
+            if (0 != result) return result;
+            result = aStr[Inspector.MEMBER_DECLARER_IDX].compareTo(bStr[Inspector.MEMBER_DECLARER_IDX]);
+            if (0 != result) return result;
+            result = aStr[Inspector.MEMBER_MODIFIER_IDX].compareTo(bStr[Inspector.MEMBER_MODIFIER_IDX]);
+            if (0 != result) return result;
+            result = aStr[Inspector.MEMBER_ORIGIN_IDX].compareTo(bStr[Inspector.MEMBER_ORIGIN_IDX]);
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/inspect/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/inspect/package.html b/src/main/groovy/groovy/inspect/package.html
new file mode 100644
index 0000000..6d80c2b
--- /dev/null
+++ b/src/main/groovy/groovy/inspect/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 groovy.inspect.*</title>
+  </head>
+  <body>
+    <p>Classes for inspecting object properties through introspection.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/EncodingAwareBufferedWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/EncodingAwareBufferedWriter.java b/src/main/groovy/groovy/io/EncodingAwareBufferedWriter.java
new file mode 100644
index 0000000..2faaaeb
--- /dev/null
+++ b/src/main/groovy/groovy/io/EncodingAwareBufferedWriter.java
@@ -0,0 +1,58 @@
+/*
+ *  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 groovy.io;
+
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+
+/**
+ * A buffered writer only for OutputStreamWriter that is aware of
+ * the encoding of the OutputStreamWriter.
+ *
+ * @author Paul King
+ */
+
+public class EncodingAwareBufferedWriter extends BufferedWriter {
+    private final OutputStreamWriter out;
+    public EncodingAwareBufferedWriter(OutputStreamWriter out) {
+        super(out);
+        this.out = out;
+    }
+
+    /**
+     * The encoding as returned by the underlying OutputStreamWriter. Can be the historical name.
+     *
+     * @return the encoding
+     * @see java.io.OutputStreamWriter#getEncoding()
+     */
+    public String getEncoding() {
+        return out.getEncoding();
+    }
+
+    /**
+     * The encoding as returned by the underlying OutputStreamWriter. Will be the preferred name.
+     *
+     * @return the encoding
+     * @see java.io.OutputStreamWriter#getEncoding()
+     */
+    public String getNormalizedEncoding() {
+        return Charset.forName(getEncoding()).name();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/FileType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/FileType.java b/src/main/groovy/groovy/io/FileType.java
new file mode 100644
index 0000000..945b9ae
--- /dev/null
+++ b/src/main/groovy/groovy/io/FileType.java
@@ -0,0 +1,31 @@
+/*
+ *  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 groovy.io;
+
+/**
+ * Represents particular files of interest.
+ */
+public enum FileType {
+    /** Represents normal files */
+    FILES,
+    /** Represents directories */
+    DIRECTORIES,
+    /** Represents both normal files and directories */
+    ANY
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/FileVisitResult.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/FileVisitResult.java b/src/main/groovy/groovy/io/FileVisitResult.java
new file mode 100644
index 0000000..55ecb4a
--- /dev/null
+++ b/src/main/groovy/groovy/io/FileVisitResult.java
@@ -0,0 +1,35 @@
+/*
+ *  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 groovy.io;
+
+/**
+ * Represents special return values for the 'preDir', 'postDir' and 'visit'/supplied Closures used with
+ * {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#traverse(java.io.File, java.util.Map, groovy.lang.Closure)}
+ * and related methods to control subsequent traversal behavior.
+ */
+public enum FileVisitResult {
+    /** Continue processing; the default */
+    CONTINUE,
+    /** Skip processing sibling files/directories within the current directory being processed */
+    SKIP_SIBLINGS,
+    /** Do not process the child files/subdirectories within the current directory being processed */
+    SKIP_SUBTREE,
+    /** Do not process any more files */
+    TERMINATE
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/GroovyPrintStream.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/GroovyPrintStream.java b/src/main/groovy/groovy/io/GroovyPrintStream.java
new file mode 100644
index 0000000..d77c5aa
--- /dev/null
+++ b/src/main/groovy/groovy/io/GroovyPrintStream.java
@@ -0,0 +1,130 @@
+/*
+ *  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 groovy.io;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A PrintStream that outputs objects in Groovy style.
+ * That means print(Object) uses InvokerHelper.toString(Object)
+ * to produce the same results as Writer.print(Object).
+ *
+ * @author Jim White
+ * @since 1.6
+ */
+public class GroovyPrintStream extends PrintStream
+{
+    /**
+     * Creates a new print stream.  This stream will not flush automatically.
+     *
+     * @see java.io.PrintStream#PrintStream(java.io.OutputStream)
+     */
+    public GroovyPrintStream(OutputStream out) {
+        super(out, false);
+    }
+
+    /**
+     * Creates a new print stream.
+     *
+     * @see java.io.PrintStream#PrintStream(java.io.OutputStream, boolean)
+     */
+    public GroovyPrintStream(OutputStream out, boolean autoFlush) {
+        super(out, autoFlush);
+    }
+
+    /**
+     * Creates a new print stream.
+     *
+     * @see java.io.PrintStream#PrintStream(java.io.OutputStream, boolean, String)
+     */
+    public GroovyPrintStream(OutputStream out, boolean autoFlush, String encoding)
+        throws UnsupportedEncodingException
+    {
+        super(out, autoFlush, encoding);
+    }
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
+     * specified file name.
+     *
+     * @see java.io.PrintStream#PrintStream(String)
+     */
+    public GroovyPrintStream(String fileName) throws FileNotFoundException {
+        super(fileName);
+    }
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
+     * specified file name and charset. 
+     *
+     * @see java.io.PrintStream#PrintStream(String, String)
+     */
+    public GroovyPrintStream(String fileName, String csn)
+        throws FileNotFoundException, UnsupportedEncodingException
+    {
+        super(fileName, csn);
+    }
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
+     * specified file. 
+     *
+     * @see java.io.PrintStream#PrintStream(File)
+     */
+    public GroovyPrintStream(File file) throws FileNotFoundException {
+        super(file);
+    }
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
+     * specified file and charset. 
+     *
+     * @see java.io.PrintStream#PrintStream(File, String)
+     */
+    public GroovyPrintStream(File file, String csn)
+        throws FileNotFoundException, UnsupportedEncodingException
+    {
+        super(file, csn);
+    }
+
+    /**
+     * Prints an object Groovy style.
+     *
+     * @param      obj   The <code>Object</code> to be printed
+     */
+    public void print(Object obj) {
+        print(InvokerHelper.toString(obj));
+    }
+
+    /**
+     * Prints an object Groovy style followed by a newline.  
+     *
+     * @param      obj   The <code>Object</code> to be printed
+     */
+    public void println(Object obj) {
+        println(InvokerHelper.toString(obj));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/GroovyPrintWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/GroovyPrintWriter.java b/src/main/groovy/groovy/io/GroovyPrintWriter.java
new file mode 100644
index 0000000..0a076b9
--- /dev/null
+++ b/src/main/groovy/groovy/io/GroovyPrintWriter.java
@@ -0,0 +1,101 @@
+/*
+ *  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 groovy.io;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
+/**
+ * A PrintWriter that outputs objects in Groovy style.
+ * That means print(Object) uses InvokerHelper.toString(Object)
+ * to produce the same results as Writer.print(Object).
+ *
+ * @author Jim White
+ * @since 1.6
+ */
+public class GroovyPrintWriter extends PrintWriter 
+{
+    public GroovyPrintWriter(File file) throws FileNotFoundException
+    {
+        super(file);
+    }
+
+    public GroovyPrintWriter(File file, String csn)
+        throws FileNotFoundException, UnsupportedEncodingException
+    {
+        super(file, csn);
+    }
+
+    public GroovyPrintWriter(Writer out) 
+    {
+        super(out);
+    }
+
+    public GroovyPrintWriter(Writer out, boolean autoflush) 
+    {
+        super(out, autoflush);
+    }
+
+    public GroovyPrintWriter(OutputStream out) 
+    {
+        super(out);
+    }
+
+    public GroovyPrintWriter(OutputStream out, boolean autoflush) 
+    {
+        super(out, autoflush);
+    }
+
+    public GroovyPrintWriter(String filename) throws FileNotFoundException 
+    {
+        super(filename);
+    }
+
+    public GroovyPrintWriter(String filename, String csn)
+        throws FileNotFoundException, UnsupportedEncodingException 
+    {
+        super(filename, csn);
+    }
+        
+// Don't need to do this if Groovy is going to print char[] like a string.
+//    public void print(char[] x) 
+//    {
+//        write(InvokerHelper.toString(x));
+//    }
+
+    public void print(Object x) 
+    {
+        write(InvokerHelper.toString(x));
+    }
+
+    public void println(Object x) 
+    {
+        // JDK 1.6 has changed the implementation to do a
+        // String.valueOf(x) rather than call print(x).
+        // Probably to improve performance by doing the conversion outside the lock.
+        // This will do the same thing for us, and we don't have to have access to the lock.
+        println(InvokerHelper.toString(x));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/LineColumnReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/LineColumnReader.java b/src/main/groovy/groovy/io/LineColumnReader.java
new file mode 100644
index 0000000..49b7c94
--- /dev/null
+++ b/src/main/groovy/groovy/io/LineColumnReader.java
@@ -0,0 +1,252 @@
+/*
+ *  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 groovy.io;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.CharBuffer;
+
+/**
+ * The <code>LineColumnReader</code> is an extension to <code>BufferedReader</code>
+ * that keeps track of the line and column information of where the cursor is.
+ *
+ * @author Guillaume Laforge
+ * @since 1.8.0
+ */
+public class LineColumnReader extends BufferedReader {
+
+    /**
+     * The current line position
+     */
+    private long line = 1;
+
+    /**
+     * The current column position
+     */
+    private long column = 1;
+
+    /**
+     * The latest marked line position
+     */
+    private long lineMark = 1;
+
+    /**
+     * The latest marked line position
+     */
+    private long columnMark = 1;
+
+    private boolean newLineWasRead = false;
+
+    /**
+     * Constructor wrapping a <code>Reader</code>
+     * (<code>FileReader</code>, <code>FileReader</code>, <code>InputStreamReader</code>, etc.)
+     *
+     * @param reader the reader to wrap
+     */
+    public LineColumnReader(Reader reader) {
+        super(reader);
+    }
+
+    /**
+     * Marks the present position in the stream. Subsequent calls to reset() will attempt to reposition the stream to this point.
+     *
+     * @param readAheadLimit  Limit on the number of characters that may be read while still preserving the mark.
+     *      An attempt to reset the stream after reading characters up to this limit or beyond may fail.
+     *      A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit.
+     *      Therefore large values should be used with care.
+     */
+    @Override
+    public void mark(int readAheadLimit) throws IOException {
+        lineMark = line;
+        columnMark = column;
+        super.mark(readAheadLimit);
+    }
+
+    /**
+     * Resets the stream to the most recent mark.
+     */
+    @Override
+    public void reset() throws IOException {
+        line = lineMark;
+        column = columnMark;
+        super.reset();
+    }
+
+    /**
+     * Reads a single character.
+     *
+     * @return The character read, as an integer in the range 0 to 65535 (0x00-0xffff),
+     *      or -1 if the end of the stream has been reached
+     */
+    @Override
+    public int read() throws IOException {
+        if (newLineWasRead) {
+            line += 1;
+            column = 1;
+            newLineWasRead = false;
+        }
+
+        int charRead = super.read();
+        if (charRead > -1) {
+            char c = (char)charRead;
+            // found a \r or \n, like on Mac or Unix
+            // could also be Windows' \r\n
+            if (c == '\r' || c == '\n') {
+                newLineWasRead = true;
+                if (c == '\r') {
+                    mark(1);
+                    c = (char)super.read();
+                    // check if we have \r\n like on Windows
+                    // if it's not \r\n we reset, otherwise, the \n is just consummed
+                    if (c != '\n') {
+                        reset();
+                    }
+                }
+            } else {
+                column += 1;
+            }
+        }
+
+        return charRead;
+    }
+
+    /**
+     * Reads characters into a portion of an array.
+     *
+     * @param chars Destination array of char
+     * @param startOffset Offset at which to start storing characters
+     * @param length Maximum number of characters to read
+     * @return an exception if an error occurs
+     */
+    @Override
+    public int read(char[] chars, int startOffset, int length) throws IOException {
+        for (int i = startOffset; i <= startOffset + length; i++) {
+            int readInt = read();
+            if (readInt == -1) return i - startOffset;
+            chars[i] = (char)readInt;
+        }
+        return length;
+    }
+
+    /**
+     * Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'),
+     * a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
+     *
+     * @return A String containing the contents of the line, not including any line-termination characters,
+     *      or null if the end of the stream has been reached
+     */
+    @Override
+    public String readLine() throws IOException {
+        StringBuilder result = new StringBuilder();
+        for (;;) {
+            int intRead = read();
+            if (intRead == -1) {
+                return result.length() == 0 ? null : result.toString();
+            }
+
+            char c = (char)intRead;
+            if (c == '\n' || c == '\r') break;
+            result.append(c);
+        }
+        return result.toString();
+    }
+
+    /**
+     * Skips characters.
+     *
+     * @param toSkip the number of characters to skip
+     * @return The number of characters actually skipped
+     */
+    @Override
+    public long skip(long toSkip) throws IOException {
+        for (long i = 0; i < toSkip; i++) {
+            int intRead = read();
+            if (intRead == -1) return i;
+        }
+        return toSkip;
+    }
+
+    /**
+     * Reads characters into an array.
+     * This method will block until some input is available, an I/O error occurs,
+     *  or the end of the stream is reached.
+     *
+     * @param chars Destination buffer
+     * @return The number of characters read, or -1 if the end of the stream has been reached
+     */
+    @Override
+    public int read(char[] chars) throws IOException {
+        return read(chars, 0, chars.length - 1);
+    }
+
+    /**
+     * Not implemented.
+     *
+     * @param buffer Destination buffer
+     * @return The number of characters read, or -1 if the end of the stream has been reached
+     * @throws UnsupportedOperationException as the method is not implemented
+     */
+    @Override
+    public int read(CharBuffer buffer) {
+        throw new UnsupportedOperationException("read(CharBuffer) not yet implemented");
+    }
+
+    /**
+     * Closes the stream and releases any system resources associated with it.
+     * Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations
+     * will throw an IOException. Closing a previously closed stream has no effect.
+     */
+    @Override
+    public void close() throws IOException {
+        super.close();
+    }
+
+    public long getColumn() {
+        return column;
+    }
+
+    public void setColumn(long column) {
+        this.column = column;
+    }
+
+    public long getColumnMark() {
+        return columnMark;
+    }
+
+    public void setColumnMark(long columnMark) {
+        this.columnMark = columnMark;
+    }
+
+    public long getLine() {
+        return line;
+    }
+
+    public void setLine(long line) {
+        this.line = line;
+    }
+
+    public long getLineMark() {
+        return lineMark;
+    }
+
+    public void setLineMark(long lineMark) {
+        this.lineMark = lineMark;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/PlatformLineWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/PlatformLineWriter.java b/src/main/groovy/groovy/io/PlatformLineWriter.java
new file mode 100644
index 0000000..0071e0f
--- /dev/null
+++ b/src/main/groovy/groovy/io/PlatformLineWriter.java
@@ -0,0 +1,64 @@
+/*
+ *  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 groovy.io;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * A buffered writer that gobbles any \r characters
+ * and replaces every \n with a platform specific newline.
+ * In many places Groovy normalises streams to only have \n
+ * characters but when creating files that must be used
+ * by other platform-aware tools, you sometimes want the
+ * newlines to match what the platform expects.
+ *
+ * @author Paul King
+ */
+public class PlatformLineWriter extends Writer {
+    private final BufferedWriter writer;
+
+    public PlatformLineWriter(Writer out) {
+        writer = new BufferedWriter(out);
+    }
+
+    public PlatformLineWriter(Writer out, int sz) {
+        writer = new BufferedWriter(out, sz);
+    }
+
+    public void write(char cbuf[], int off, int len) throws IOException {
+        for (; len > 0; len--) {
+            char c = cbuf[off++];
+            if (c == '\n') {
+                writer.newLine();
+            } else if (c != '\r') {
+                writer.write(c);
+            }
+        }
+    }
+
+    public void flush() throws IOException {
+        writer.flush();
+    }
+
+    public void close() throws IOException {
+        writer.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/io/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/io/package.html b/src/main/groovy/groovy/io/package.html
new file mode 100644
index 0000000..fef0d09
--- /dev/null
+++ b/src/main/groovy/groovy/io/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 groovy.io.*</title>
+  </head>
+  <body>
+    <p>Classes for Groovier Input/Output.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/AdaptingMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/AdaptingMetaClass.java b/src/main/groovy/groovy/lang/AdaptingMetaClass.java
new file mode 100644
index 0000000..81afc26
--- /dev/null
+++ b/src/main/groovy/groovy/lang/AdaptingMetaClass.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 groovy.lang;
+
+/**
+ * An interface for MetaClass instances that "adapt" other MetaClass instances such as a proxy or
+ * delegating MetaClass.
+ *
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public interface AdaptingMetaClass extends MetaClass {
+
+    /**
+     * Returns the MetaClass that this adapter adapts
+     *
+     * @return The MetaClass instance
+     */
+    MetaClass getAdaptee();
+
+    /**
+     * Sets the MetaClass adapted by this MetaClass
+     *
+     * @param metaClass The MetaClass to adapt
+     */
+    void setAdaptee(MetaClass metaClass);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/BenchmarkInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/BenchmarkInterceptor.java b/src/main/groovy/groovy/lang/BenchmarkInterceptor.java
new file mode 100644
index 0000000..77bcb64
--- /dev/null
+++ b/src/main/groovy/groovy/lang/BenchmarkInterceptor.java
@@ -0,0 +1,126 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interceptor that registers the timestamp of each method call
+ * before and after invocation. The timestamps are stored internally
+ * and can be retrieved through the with the <pre>getCalls()</pre> 
+ * and <pre>statistic()</pre> API.
+ * <p>
+ * Example usage:
+ * <pre>
+ * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
+ * proxy.interceptor = new BenchmarkInterceptor()
+ * proxy.use {
+ *     def list = (0..10000).collect{ it }
+ *     4.times { list.size() }
+ *     4000.times { list.set(it, it+1) }
+ * }
+ * proxy.interceptor.statistic()
+ * </pre>
+ * Which produces the following output: 
+ * <pre>
+ * [[size, 4, 0], [set, 4000, 21]]
+ * </pre>
+ */
+public class BenchmarkInterceptor implements Interceptor {
+
+    protected Map calls = new LinkedHashMap(); // keys to list of invocation times and before and after
+
+    /**
+    * Returns the raw data associated with the current benchmark run. 
+    */ 
+    public Map getCalls() {
+        return calls;
+    }
+    
+    /**
+    * Resets all the benchmark data on this object. 
+    */
+    public void reset() {
+        calls = new HashMap();
+    }
+    /**
+     * This code is executed before the method is called.
+     * @param object        receiver object for the method call
+     * @param methodName    name of the method to call
+     * @param arguments     arguments to the method call
+     * @return null
+     * relays this result.
+     */
+    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
+        if (!calls.containsKey(methodName)) calls.put(methodName, new LinkedList());
+        ((List) calls.get(methodName)).add(Long.valueOf(System.currentTimeMillis()));
+
+        return null;
+    }
+    /**
+     * This code is executed after the method is called.
+     * @param object        receiver object for the called method
+     * @param methodName    name of the called method
+     * @param arguments     arguments to the called method
+     * @param result        result of the executed method call or result of beforeInvoke if method was not called
+     * @return result
+     */
+    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
+        ((List) calls.get(methodName)).add(Long.valueOf(System.currentTimeMillis()));
+        return result;
+    }
+
+    /**
+     * The call should be invoked separately
+     * @return true
+     */
+    public boolean doInvoke() {
+        return true;
+    }
+
+    /**
+     * Returns benchmark statistics as a List&lt;Object[]&gt;. 
+     * AccumulateTime is measured in milliseconds and is as accurate as
+     * System.currentTimeMillis() allows it to be. 
+     * @return a list of lines, each item is [methodname, numberOfCalls, accumulatedTime]
+     */
+    public List statistic() {
+        List result = new LinkedList();
+        for (Iterator iter = calls.keySet().iterator(); iter.hasNext();) {
+            Object[] line = new Object[3];
+            result.add(line);
+            line[0] = iter.next();
+            List times = (List) calls.get(line[0]);
+            line[1] = Integer.valueOf(times.size() / 2);
+            int accTime = 0;
+            for (Iterator it = times.iterator(); it.hasNext();) {
+                Long start = (Long) it.next();
+                Long end = (Long) it.next();
+                accTime += end.longValue() - start.longValue();
+            }
+            line[2] = Long.valueOf(accTime);
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Binding.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Binding.java b/src/main/groovy/groovy/lang/Binding.java
new file mode 100644
index 0000000..6505ea5
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Binding.java
@@ -0,0 +1,122 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Represents the variable bindings of a script which can be altered
+ * from outside the script object or created outside of a script and passed
+ * into it.
+ * <p> Binding instances are not supposed to be used in a multi-threaded context.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Binding extends GroovyObjectSupport {
+    private Map variables;
+
+    public Binding() {
+    }
+
+    public Binding(Map variables) {
+        this.variables = variables;
+    }
+
+    /**
+     * A helper constructor used in main(String[]) method calls
+     *
+     * @param args are the command line arguments from a main()
+     */
+    public Binding(String[] args) {
+        this();
+        setVariable("args", args);
+    }
+
+    /**
+     * @param name the name of the variable to lookup
+     * @return the variable value
+     */
+    public Object getVariable(String name) {
+        if (variables == null)
+            throw new MissingPropertyException(name, this.getClass());
+
+        Object result = variables.get(name);
+
+        if (result == null && !variables.containsKey(name)) {
+            throw new MissingPropertyException(name, this.getClass());
+        }
+
+        return result;
+    }
+
+    /**
+     * Sets the value of the given variable
+     *
+     * @param name  the name of the variable to set
+     * @param value the new value for the given variable
+     */
+    public void setVariable(String name, Object value) {
+        if (variables == null)
+            variables = new LinkedHashMap();
+        variables.put(name, value);
+    }
+    
+    /**
+     * Simple check for whether the binding contains a particular variable or not.
+     * 
+     * @param name the name of the variable to check for
+     */
+    public boolean hasVariable(String name) {
+        return variables != null && variables.containsKey(name);
+    }
+
+    public Map getVariables() {
+        if (variables == null)
+            variables = new LinkedHashMap();
+        return variables;
+    }
+
+    /**
+     * Overloaded to make variables appear as bean properties or via the subscript operator
+     */
+    public Object getProperty(String property) {
+        /** @todo we should check if we have the property with the metaClass instead of try/catch  */
+        try {
+            return super.getProperty(property);
+        }
+        catch (MissingPropertyException e) {
+            return getVariable(property);
+        }
+    }
+
+    /**
+     * Overloaded to make variables appear as bean properties or via the subscript operator
+     */
+    public void setProperty(String property, Object newValue) {
+        /** @todo we should check if we have the property with the metaClass instead of try/catch  */
+        try {
+            super.setProperty(property, newValue);
+        }
+        catch (MissingPropertyException e) {
+            setVariable(property, newValue);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Buildable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Buildable.java b/src/main/groovy/groovy/lang/Buildable.java
new file mode 100644
index 0000000..af22958
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Buildable.java
@@ -0,0 +1,24 @@
+/*
+ *  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 groovy.lang;
+
+
+public interface Buildable {
+    void build(GroovyObject builder);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Category.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Category.java b/src/main/groovy/groovy/lang/Category.java
new file mode 100644
index 0000000..a7d3336
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Category.java
@@ -0,0 +1,105 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Transforms an instance-style Groovy class or interface to become a static-style
+ * conventional Groovy category.
+ * <p>
+ * Groovy categories are the original mechanism used
+ * by Groovy when augmenting classes with new methods. Writing categories required
+ * using a class writing style where all methods were static and an additional
+ * self parameter was defined. The self parameter and static nature of the methods
+ * disappeared once applied by Groovy's metaclass framework but some regarded
+ * the writing style as a little noisy. This transformation allows you to write
+ * your categories without the "apparent noise" but adds it back in during
+ * compilation so that the classes appear as normal categories.
+ * <p>
+ * It might seem strange writing your class/object enhancements using a succinct
+ * notation, then having "noise" added, then having the noise removed during
+ * category application. If this worries you, then you may also like to consider
+ * using Groovy's {@code ExpandoMetaClass} mechanism which avoids
+ * the category definition altogether. If you already have an investment in
+ * categories or like some of the other features which categories currently give you,
+ * then read on.
+ * <p>
+ * The mechanics: during compilation, all methods are transformed to static ones with an additional
+ * self parameter of the type you supply as the annotation parameter (the default type
+ * for the self parameters is {@code Object} which might be more broad reaching than
+ * you like so it is usually wise to specify a type).
+ * Properties invoked using 'this' references are transformed so that
+ * they are instead invoked on the additional self parameter and not on
+ * the Category instance. (Remember that once the category is applied, the reverse
+ * will occur and we will be back to conceptually having methods on the {@code this}
+ * references again!)
+ * <p>
+ * Classes conforming to the conventional Groovy category conventions can be used
+ * within {@code use} statements or mixed in at runtime with the {@code mixin} method on classes.
+ * <p>
+ * An example showing a {@code use} statement (allowing fine-grained application of
+ * the category methods):
+ * <pre class="groovyTestCase">
+ * {@code @Category}(Integer)
+ * class IntegerOps {
+ *     def triple() {
+ *         this * 3
+ *     }
+ * }
+ *
+ * use (IntegerOps) {
+ *     assert 25.triple() == 75
+ * }
+ * </pre>
+ * Or, "mixing in" your methods at runtime:
+ * <pre class="groovyTestCase">
+ * {@code @Category}(List)
+ * class Shuffler {
+ *     def shuffle() {
+ *         def result = new ArrayList(this)
+ *         Collections.shuffle(result)
+ *         result
+ *     }
+ * }
+ *
+ * class Sentence extends ArrayList {
+ *     Sentence(Collection initial) { super(initial) }
+ * }
+ * Sentence.mixin Shuffler
+ *
+ * def words = ["The", "quick", "brown", "fox"]
+ * println new Sentence(words).shuffle()
+ * // => [quick, fox, The, brown]       (order will vary)
+ * </pre>
+ *
+ * @author Alex Tkachman
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.CategoryASTTransformation")
+public @interface Category {
+    Class value () default Object.class;
+}


[36/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyShell.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyShell.java b/src/main/groovy/groovy/lang/GroovyShell.java
new file mode 100644
index 0000000..4dc51c9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyShell.java
@@ -0,0 +1,611 @@
+/*
+ *  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 groovy.lang;
+
+import groovy.security.GroovyCodeSourcePermission;
+import groovy.ui.GroovyMain;
+import org.apache.groovy.plugin.GroovyRunner;
+import org.apache.groovy.plugin.GroovyRunnerRegistry;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.List;
+
+import static org.codehaus.groovy.runtime.InvokerHelper.MAIN_METHOD_NAME;
+
+/**
+ * Represents a groovy shell capable of running arbitrary groovy scripts
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Guillaume Laforge
+ * @author Paul King
+ */
+public class GroovyShell extends GroovyObjectSupport {
+
+    public static final String DEFAULT_CODE_BASE = "/groovy/shell";
+
+    private final Binding context;
+    private int counter;
+    private final CompilerConfiguration config;
+    private GroovyClassLoader loader;
+
+    public static void main(String[] args) {
+        GroovyMain.main(args);
+    }
+
+    public GroovyShell() {
+        this(null, new Binding());
+    }
+
+    public GroovyShell(Binding binding) {
+        this(null, binding);
+    }
+
+    public GroovyShell(ClassLoader parent, CompilerConfiguration config) {
+        this(parent, new Binding(), config);
+    }
+
+    public GroovyShell(CompilerConfiguration config) {
+        this(new Binding(), config);
+    }
+
+    public GroovyShell(Binding binding, CompilerConfiguration config) {
+        this(null, binding, config);
+    }
+
+    public GroovyShell(ClassLoader parent, Binding binding) {
+        this(parent, binding, CompilerConfiguration.DEFAULT);
+    }
+
+    public GroovyShell(ClassLoader parent) {
+        this(parent, new Binding(), CompilerConfiguration.DEFAULT);
+    }
+    
+    public GroovyShell(ClassLoader parent, Binding binding, final CompilerConfiguration config) {
+        if (binding == null) {
+            throw new IllegalArgumentException("Binding must not be null.");
+        }
+        if (config == null) {
+            throw new IllegalArgumentException("Compiler configuration must not be null.");
+        }
+        final ClassLoader parentLoader = (parent!=null)?parent:GroovyShell.class.getClassLoader();
+        this.loader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
+            public GroovyClassLoader run() {
+                return new GroovyClassLoader(parentLoader,config);
+            }
+        });
+        this.context = binding;        
+        this.config = config;
+    }
+    
+    public void resetLoadedClasses() {
+        loader.clearCache();
+    }
+
+    /**
+     * Creates a child shell using a new ClassLoader which uses the parent shell's
+     * class loader as its parent
+     *
+     * @param shell is the parent shell used for the variable bindings and the parent class loader
+     */
+    public GroovyShell(GroovyShell shell) {
+        this(shell.loader, shell.context);
+    }
+
+    public Binding getContext() {
+        return context;
+    }
+
+    public GroovyClassLoader getClassLoader() {
+        return loader;
+    }
+
+    public Object getProperty(String property) {
+        Object answer = getVariable(property);
+        if (answer == null) {
+            answer = super.getProperty(property);
+        }
+        return answer;
+    }
+
+    public void setProperty(String property, Object newValue) {
+        setVariable(property, newValue);
+        try {
+            super.setProperty(property, newValue);
+        } catch (GroovyRuntimeException e) {
+            // ignore, was probably a dynamic property
+        }
+    }
+
+    //
+    // FIXME: Use List<String> here, current version is not safe
+    //
+
+    /**
+     * A helper method which runs the given script file with the given command line arguments
+     *
+     * @param scriptFile the file of the script to run
+     * @param list       the command line arguments to pass in
+     */
+    public Object run(File scriptFile, List list) throws CompilationFailedException, IOException {
+        String[] args = new String[list.size()];
+        return run(scriptFile, (String[]) list.toArray(args));
+    }
+
+    /**
+     * A helper method which runs the given cl script with the given command line arguments
+     *
+     * @param scriptText is the text content of the script
+     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
+     * @param list       the command line arguments to pass in
+     */
+    public Object run(String scriptText, String fileName, List list) throws CompilationFailedException {
+        String[] args = new String[list.size()];
+        list.toArray(args);
+        return run(scriptText, fileName, args);
+    }
+
+    /**
+     * Runs the given script file name with the given command line arguments
+     *
+     * @param scriptFile the file name of the script to run
+     * @param args       the command line arguments to pass in
+     */
+    public Object run(final File scriptFile, String[] args) throws CompilationFailedException, IOException {
+        String scriptName = scriptFile.getName();
+        int p = scriptName.lastIndexOf(".");
+        if (p++ >= 0) {
+            if (scriptName.substring(p).equals("java")) {
+                throw new CompilationFailedException(0, null);
+            }
+        }
+
+        // Get the current context classloader and save it on the stack
+        final Thread thread = Thread.currentThread();
+        //ClassLoader currentClassLoader = thread.getContextClassLoader();
+
+        class DoSetContext implements PrivilegedAction {
+            ClassLoader classLoader;
+
+            public DoSetContext(ClassLoader loader) {
+                classLoader = loader;
+            }
+
+            public Object run() {
+                thread.setContextClassLoader(classLoader);
+                return null;
+            }
+        }
+
+        AccessController.doPrivileged(new DoSetContext(loader));
+
+        // Parse the script, generate the class, and invoke the main method.  This is a little looser than
+        // if you are compiling the script because the JVM isn't executing the main method.
+        Class scriptClass;
+        try {
+            scriptClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Class>() {
+                public Class run() throws CompilationFailedException, IOException {
+                    return loader.parseClass(scriptFile);
+                }
+            });
+        } catch (PrivilegedActionException pae) {
+            Exception e = pae.getException();
+            if (e instanceof CompilationFailedException) {
+                throw (CompilationFailedException) e;
+            } else if (e instanceof IOException) {
+                throw (IOException) e;
+            } else {
+                throw (RuntimeException) pae.getException();
+            }
+        }
+
+        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
+
+        // Set the context classloader back to what it was.
+        //AccessController.doPrivileged(new DoSetContext(currentClassLoader));
+    }
+
+    /**
+     * if (theClass is a Script) {
+     * run it like a script
+     * } else if (theClass has a main method) {
+     * run the main method
+     * } else if (theClass instanceof GroovyTestCase) {
+     * use the test runner to run it
+     * } else if (theClass implements Runnable) {
+     * if (theClass has a constructor with String[] params)
+     * instantiate theClass with this constructor and run
+     * else if (theClass has a no-args constructor)
+     * instantiate theClass with the no-args constructor and run
+     * }
+     */
+    private Object runScriptOrMainOrTestOrRunnable(Class scriptClass, String[] args) {
+        // Always set the "args" property, regardless of what path we take in the code.
+        // Bad enough to have side effects but worse if their behavior is wonky.
+        context.setProperty("args", args);
+
+        if (scriptClass == null) {
+            return null;
+        }
+
+        //TODO: This logic mostly duplicates InvokerHelper.createScript.  They should probably be unified.
+
+        if (Script.class.isAssignableFrom(scriptClass)) {
+            // treat it just like a script if it is one
+            try {
+                Script script = InvokerHelper.newScript(scriptClass, context);
+                return script.run();
+            } catch (InstantiationException e) {
+                // ignore instantiation errors,, try to do main
+            } catch (IllegalAccessException e) {
+               // ignore instantiation errors, try to do main
+            } catch (InvocationTargetException e) {
+                // ignore instantiation errors, try to do main
+            }
+        }
+        try {
+            // let's find a main method
+            scriptClass.getMethod(MAIN_METHOD_NAME, String[].class);
+            // if that main method exist, invoke it
+            return InvokerHelper.invokeMethod(scriptClass, MAIN_METHOD_NAME, new Object[]{args});
+        } catch (NoSuchMethodException e) {
+            // if it implements Runnable, try to instantiate it
+            if (Runnable.class.isAssignableFrom(scriptClass)) {
+                return runRunnable(scriptClass, args);
+            }
+            GroovyRunnerRegistry runnerRegistry = GroovyRunnerRegistry.getInstance();
+            for (GroovyRunner runner : runnerRegistry) {
+                if (runner.canRun(scriptClass, this.loader)) {
+                    return runner.run(scriptClass, this.loader);
+                }
+            }
+            StringBuilder message = new StringBuilder("This script or class could not be run.\n" +
+                    "It should either:\n" +
+                    "- have a main method,\n" +
+                    "- be a JUnit test or extend GroovyTestCase,\n" +
+                    "- implement the Runnable interface,\n" +
+                    "- or be compatible with a registered script runner. Known runners:\n");
+            if (runnerRegistry.isEmpty()) {
+                message.append("  * <none>");
+            } else {
+                for (String key : runnerRegistry.keySet()) {
+                    message.append("  * ").append(key).append("\n");
+                }
+            }
+            throw new GroovyRuntimeException(message.toString());
+        }
+    }
+
+    private static Object runRunnable(Class scriptClass, String[] args) {
+        Constructor constructor = null;
+        Runnable runnable = null;
+        Throwable reason = null;
+        try {
+            // first, fetch the constructor taking String[] as parameter
+            constructor = scriptClass.getConstructor((new String[]{}).getClass());
+            try {
+                // instantiate a runnable and run it
+                runnable = (Runnable) constructor.newInstance(new Object[]{args});
+            } catch (Throwable t) {
+                reason = t;
+            }
+        } catch (NoSuchMethodException e1) {
+            try {
+                // otherwise, find the default constructor
+                constructor = scriptClass.getConstructor();
+                try {
+                    // instantiate a runnable and run it
+                    runnable = (Runnable) constructor.newInstance();
+                } catch (InvocationTargetException ite) {
+                    throw new InvokerInvocationException(ite.getTargetException());
+                } catch (Throwable t) {
+                    reason = t;
+                }
+            } catch (NoSuchMethodException nsme) {
+                reason = nsme;
+            }
+        }
+        if (constructor != null && runnable != null) {
+            runnable.run();
+        } else {
+            throw new GroovyRuntimeException("This script or class was runnable but could not be run. ", reason);
+        }
+        return null;
+    }
+
+    /**
+     * Runs the given script text with command line arguments
+     *
+     * @param scriptText is the text content of the script
+     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
+     * @param args       the command line arguments to pass in
+     */
+    public Object run(final String scriptText, final String fileName, String[] args) throws CompilationFailedException {
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                return new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE);
+            }
+        });
+        return run(gcs, args);
+    }
+
+    /**
+     * Runs the given script source with command line arguments
+     *
+     * @param source    is the source content of the script
+     * @param args      the command line arguments to pass in
+     */
+    public Object run(GroovyCodeSource source, List args) throws CompilationFailedException {
+        return run(source, ((String[]) args.toArray(new String[args.size()])));
+    }
+
+    /**
+     * Runs the given script source with command line arguments
+     *
+     * @param source    is the source content of the script
+     * @param args      the command line arguments to pass in
+     */
+    public Object run(GroovyCodeSource source, String[] args) throws CompilationFailedException {
+        Class scriptClass = parseClass(source);
+        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
+    }
+
+    /**
+     * Runs the given script source with command line arguments
+     *
+     * @param source    is the source content of the script
+     * @param args      the command line arguments to pass in
+     */
+    public Object run(URI source, List args) throws CompilationFailedException, IOException {
+        return run(new GroovyCodeSource(source), ((String[]) args.toArray(new String[args.size()])));
+    }
+
+    /**
+     * Runs the given script source with command line arguments
+     *
+     * @param source    is the source content of the script
+     * @param args      the command line arguments to pass in
+     */
+    public Object run(URI source, String[] args) throws CompilationFailedException, IOException {
+        return run(new GroovyCodeSource(source), args);
+    }
+
+    /**
+     * Runs the given script with command line arguments
+     *
+     * @param in       the stream reading the script
+     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
+     * @param list     the command line arguments to pass in
+     */
+    public Object run(final Reader in, final String fileName, List list) throws CompilationFailedException {
+        return run(in, fileName, (String[]) list.toArray(new String[list.size()]));
+    }
+
+    /**
+     * Runs the given script with command line arguments
+     *
+     * @param in       the stream reading the script
+     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
+     * @param args     the command line arguments to pass in
+     */
+    public Object run(final Reader in, final String fileName, String[] args) throws CompilationFailedException {
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+                    public GroovyCodeSource run() {
+                        return new GroovyCodeSource(in, fileName, DEFAULT_CODE_BASE);
+                    }
+        });
+        Class scriptClass = parseClass(gcs);
+        return runScriptOrMainOrTestOrRunnable(scriptClass, args);
+    }
+
+    public Object getVariable(String name) {
+        return context.getVariables().get(name);
+    }
+
+    public void setVariable(String name, Object value) {
+        context.setVariable(name, value);
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param codeSource
+     * @throws CompilationFailedException
+     */
+    public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
+        Script script = parse(codeSource);
+        return script.run();
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param scriptText the text of the script
+     */
+    public Object evaluate(final String scriptText) throws CompilationFailedException {
+        return evaluate(scriptText, generateScriptName(), DEFAULT_CODE_BASE);
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param scriptText the text of the script
+     * @param fileName   is the logical file name of the script (which is used to create the class name of the script)
+     */
+    public Object evaluate(String scriptText, String fileName) throws CompilationFailedException {
+        return evaluate(scriptText, fileName, DEFAULT_CODE_BASE);
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result.
+     * The .class file created from the script is given the supplied codeBase
+     */
+    public Object evaluate(final String scriptText, final String fileName, final String codeBase) throws CompilationFailedException {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
+        }
+
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                return new GroovyCodeSource(scriptText, fileName, codeBase);
+            }
+        });
+
+        return evaluate(gcs);
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param file is the file of the script (which is used to create the class name of the script)
+     */
+    public Object evaluate(File file) throws CompilationFailedException, IOException {
+        return evaluate(new GroovyCodeSource(file, config.getSourceEncoding()));
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param uri is the URI of the script (which is used to create the class name of the script)
+     */
+    public Object evaluate(URI uri) throws CompilationFailedException, IOException {
+        return evaluate(new GroovyCodeSource(uri));
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param in the stream reading the script
+     */
+    public Object evaluate(Reader in) throws CompilationFailedException {
+        return evaluate(in, generateScriptName());
+    }
+
+    /**
+     * Evaluates some script against the current Binding and returns the result
+     *
+     * @param in       the stream reading the script
+     * @param fileName is the logical file name of the script (which is used to create the class name of the script)
+     */
+    public Object evaluate(Reader in, String fileName) throws CompilationFailedException {
+        Script script = null;
+        try {
+            script = parse(in, fileName);
+            return script.run();
+        } finally {
+            if (script != null) {
+                InvokerHelper.removeClass(script.getClass());
+            }
+        }
+    }
+
+
+    /**
+     * Parses the given script and returns it ready to be run
+     *
+     * @param reader    the stream reading the script
+     * @param fileName  is the logical file name of the script (which is used to create the class name of the script)
+     * @return the parsed script which is ready to be run via {@link Script#run()}
+     */
+    public Script parse(final Reader reader, final String fileName) throws CompilationFailedException {
+        return parse(new GroovyCodeSource(reader, fileName, DEFAULT_CODE_BASE));
+    }
+
+    /**
+     * Parses the groovy code contained in codeSource and returns a java class.
+     */
+    private Class parseClass(final GroovyCodeSource codeSource) throws CompilationFailedException {
+        // Don't cache scripts
+        return loader.parseClass(codeSource, false);
+    }
+
+    /**
+     * Parses the given script and returns it ready to be run.  When running in a secure environment
+     * (-Djava.security.manager) codeSource.getCodeSource() determines what policy grants should be
+     * given to the script.
+     *
+     * @param codeSource
+     * @return ready to run script
+     */
+    public Script parse(final GroovyCodeSource codeSource) throws CompilationFailedException {
+        return InvokerHelper.createScript(parseClass(codeSource), context);
+    }
+
+    /**
+     * Parses the given script and returns it ready to be run
+     *
+     * @param file is the file of the script (which is used to create the class name of the script)
+     */
+    public Script parse(File file) throws CompilationFailedException, IOException {
+        return parse(new GroovyCodeSource(file, config.getSourceEncoding()));
+    }
+
+    /**
+     * Parses the given script and returns it ready to be run
+     *
+     * @param uri is the URI of the script (which is used to create the class name of the script)
+     */
+    public Script parse(URI uri) throws CompilationFailedException, IOException {
+        return parse(new GroovyCodeSource(uri));
+    }
+
+    /**
+     * Parses the given script and returns it ready to be run
+     *
+     * @param scriptText the text of the script
+     */
+    public Script parse(String scriptText) throws CompilationFailedException {
+        return parse(scriptText, generateScriptName());
+    }
+
+    public Script parse(final String scriptText, final String fileName) throws CompilationFailedException {
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                return new GroovyCodeSource(scriptText, fileName, DEFAULT_CODE_BASE);
+            }
+        });
+        return parse(gcs);
+    }
+
+    /**
+     * Parses the given script and returns it ready to be run
+     *
+     * @param in the stream reading the script
+     */
+    public Script parse(Reader in) throws CompilationFailedException {
+        return parse(in, generateScriptName());
+    }
+
+    protected synchronized String generateScriptName() {
+        return "Script" + (++counter) + ".groovy";
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovySystem.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovySystem.java b/src/main/groovy/groovy/lang/GroovySystem.java
new file mode 100644
index 0000000..cb5ea98
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovySystem.java
@@ -0,0 +1,103 @@
+/*
+ *  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 groovy.lang;
+
+import org.apache.groovy.plugin.GroovyRunner;
+import org.apache.groovy.plugin.GroovyRunnerRegistry;
+import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
+import org.codehaus.groovy.util.ReferenceBundle;
+import org.codehaus.groovy.util.ReleaseInfo;
+
+import java.util.Map;
+
+public final class GroovySystem {
+    //
+    //  TODO: make this initialization able to set useReflection true
+    //  TODO: have some way of specifying another MetaClass Registry implementation
+    //
+    static {
+        USE_REFLECTION = true;
+        META_CLASS_REGISTRY = new MetaClassRegistryImpl();
+    }
+    
+    /**
+     * If true then the MetaClass will only use reflection for method dispatch, property access, etc.
+     */
+    @Deprecated
+    private static final boolean USE_REFLECTION;
+
+    /**
+     * Reference to the MetaClass Registry to be used by the Groovy run-time system to map classes to MetaClasses
+     */
+    private static final MetaClassRegistry META_CLASS_REGISTRY;
+
+    /**
+     * Reference to the Runtime Registry to be used by the Groovy run-time system to find classes capable of running scripts
+     *
+     * @deprecated use {@link GroovyRunnerRegistry}
+     */
+    @Deprecated
+    public static final Map<String, GroovyRunner> RUNNER_REGISTRY = GroovyRunnerRegistry.getInstance();
+
+    private static boolean keepJavaMetaClasses=false;
+    
+    private GroovySystem() {
+        // Do not allow this class to be instantiated
+    }
+
+    @Deprecated
+    public static boolean isUseReflection() {
+        return USE_REFLECTION;
+    }
+
+    public static MetaClassRegistry getMetaClassRegistry() {
+        return META_CLASS_REGISTRY;
+    }
+    
+    public static void setKeepJavaMetaClasses(boolean keepJavaMetaClasses) {
+        GroovySystem.keepJavaMetaClasses = keepJavaMetaClasses;
+    }
+    
+    public static boolean isKeepJavaMetaClasses() {
+        return keepJavaMetaClasses;
+    }
+    
+    /**
+     * This method can be used to ensure that no threaded created
+     * by a reference manager will be active. This is useful if the Groovy
+     * runtime itself is loaded through a class loader which should be disposed
+     * off. Without calling this method and if a threaded reference manager is
+     * active the class loader cannot be unloaded!
+     * 
+     * Per default no threaded manager will be used.
+     * 
+     * @since 1.6
+     */
+    public static void stopThreadedReferenceManager() {
+        ReferenceBundle.getSoftBundle().getManager().stopThread();
+        ReferenceBundle.getWeakBundle().getManager().stopThread();
+    }
+
+    /**
+     * Returns the groovy version
+     */
+    public static String getVersion() {
+        return ReleaseInfo.getVersion();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/IllegalPropertyAccessException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/IllegalPropertyAccessException.java b/src/main/groovy/groovy/lang/IllegalPropertyAccessException.java
new file mode 100644
index 0000000..8227e3f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/IllegalPropertyAccessException.java
@@ -0,0 +1,49 @@
+/*
+ *  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 groovy.lang;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * An exception occurred if a dynamic property dispatch fails with a 
+ * field not accessible.
+ * 
+ * @author <a href="mailto:blackdrag@uni.de">Jochen Theodorou</a>
+ */
+public class IllegalPropertyAccessException extends MissingPropertyException {
+    
+    private static String makeMessage(String propertyName, Class clazz, int modifiers, boolean isField) {
+        String access = "private";
+        if (Modifier.isProtected(modifiers)) access = "protected";
+        if (Modifier.isPublic(modifiers)) access = "public";
+        String propertyType = "property";
+        if (isField) propertyType = "field";
+        return  "Can not access the "+access+" "+propertyType+" "+propertyName+" in class "+clazz.getName();
+    }
+    
+    public IllegalPropertyAccessException(String propertyName, Class clazz, int modifiers) {
+        super(makeMessage(propertyName,clazz,modifiers,false),propertyName,clazz);
+    }
+    
+    public IllegalPropertyAccessException(Field field, Class clazz) {
+        super(makeMessage(field.getName(),clazz,field.getModifiers(),true),field.getName(),clazz);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/IncorrectClosureArgumentsException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/IncorrectClosureArgumentsException.java b/src/main/groovy/groovy/lang/IncorrectClosureArgumentsException.java
new file mode 100644
index 0000000..f5b23f5
--- /dev/null
+++ b/src/main/groovy/groovy/lang/IncorrectClosureArgumentsException.java
@@ -0,0 +1,60 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * An exception occurred when invoking a Closure with the wrong number and/or
+ * types of arguments
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class IncorrectClosureArgumentsException extends GroovyRuntimeException {
+
+    private final Closure closure;
+    private final Object arguments;
+    private final Class[] expected;
+
+    public IncorrectClosureArgumentsException(Closure closure, Object arguments, Class[] expected) {
+        super(
+            "Incorrect arguments to closure: "
+                + closure
+                + ". Expected: "
+                + InvokerHelper.toString(expected)
+                + ", actual: "
+                + InvokerHelper.toString(arguments));
+        this.closure = closure;
+        this.arguments = arguments;
+        this.expected = expected;
+    }
+
+    public Object getArguments() {
+        return arguments;
+    }
+
+    public Closure getClosure() {
+        return closure;
+    }
+
+    public Class[] getExpected() {
+        return expected;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/IntRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/IntRange.java b/src/main/groovy/groovy/lang/IntRange.java
new file mode 100644
index 0000000..1ca3820
--- /dev/null
+++ b/src/main/groovy/groovy/lang/IntRange.java
@@ -0,0 +1,440 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.IteratorClosureAdapter;
+import org.codehaus.groovy.runtime.RangeInfo;
+
+import java.math.BigInteger;
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Represents a list of Integer objects starting at a specified {@code from} value up (or down)
+ * to and potentially including a given {@code to} value.
+ * <p>
+ * Instances of this class may be either inclusive aware or non-inclusive aware. See the
+ * relevant constructors for creating each type. Inclusive aware IntRange instances are
+ * suitable for use with Groovy's range indexing - in particular if the from or to values
+ * might be negative. This normally happens underneath the covers but is worth keeping
+ * in mind if creating these ranges yourself explicitly.
+ * <p>
+ * Note: the design of this class might seem a little strange at first. It contains a Boolean
+ * field, {@code inclusive}, which can be {@code true}, {@code false} or {@code null}. This
+ * design is for backwards compatibility reasons. Groovy uses this class under the covers
+ * to represent range indexing, e.g. {@code someList[x..y]} and {@code someString[x..<y]}.
+ * In early versions of Groovy the ranges in these expressions were represented under the
+ * covers by the {@code new IntRange(x, y)} and {@code new IntRange(x, y-1)}. This turns
+ * out to be a lossy abstraction when x and/or y are negative values. Now the latter case
+ * is represented by {@code new IntRange(false, x, y)}.
+ * <p>
+ * Note: This class is a copy of {@link ObjectRange} optimized for <code>int</code>. If you make any
+ * changes to this class, you might consider making parallel changes to {@link ObjectRange}.
+ */
+public class IntRange extends AbstractList<Integer> implements Range<Integer> {
+
+    /**
+     * Iterates through each number in an <code>IntRange</code>.
+     */
+    private class IntRangeIterator implements Iterator<Integer> {
+        /**
+         * Counts from 0 up to size - 1.
+         */
+        private int index;
+
+        /**
+         * The number of values in the range.
+         */
+        private int size = size();
+
+        /**
+         * The next value to return.
+         */
+        private int value = isReverse() ? getTo() : getFrom();
+
+        @Override
+        public boolean hasNext() {
+            return index < size;
+        }
+
+        @Override
+        public Integer next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            if (index++ > 0) {
+                if (isReverse()) {
+                    --value;
+                } else {
+                    ++value;
+                }
+            }
+            return value;
+        }
+
+        /**
+         * Not supported.
+         *
+         * @throws java.lang.UnsupportedOperationException always
+         */
+        @Override
+        public void remove() {
+            IntRange.this.remove(index);
+        }
+    }
+
+    /**
+     * For non-inclusive aware ranges, the first number in the range; <code>from</code> is always less than or equal to <code>to</code>.
+     * For inclusive aware ranges, the <code>from</code> argument supplied to the constructor.
+     */
+    private final int from;
+
+    /**
+     * For non-inclusive aware ranges, the last number in the range; <code>to</code> is always greater than or equal to <code>from</code>.
+     * For inclusive aware ranges, the <code>from</code> argument supplied to the constructor.
+     */
+    private final int to;
+
+    /**
+     * If <code>false</code>, counts up from <code>from</code> to <code>to</code>.  Otherwise, counts down
+     * from <code>to</code> to <code>from</code>. Not used for inclusive-aware ranges (inclusive = true|false).
+     */
+    private final boolean reverse;
+
+    /**
+     * If <code>true</code> or null, <code>to</code> is included in the range.
+     * If <code>false</code>, the range stops before the <code>to</code> value.
+     * <p>
+     * Null for non-inclusive-aware ranges (which are inclusive).
+     * <p>
+     * If true or false, the reverse flag is discarded.
+     */
+    private final Boolean inclusive;
+
+    /**
+     * Creates a new non-inclusive aware <code>IntRange</code>. If <code>from</code> is greater than
+     * <code>to</code>, a reverse range is created with <code>from</code> and <code>to</code> swapped.
+     *
+     * @param from the first number in the range.
+     * @param to   the last number in the range.
+     * @throws IllegalArgumentException if the range would contain more than {@link Integer#MAX_VALUE} values.
+     */
+    public IntRange(int from, int to) {
+        this.inclusive = null;
+        if (from > to) {
+            this.from = to;
+            this.to = from;
+            this.reverse = true;
+        } else {
+            this.from = from;
+            this.to = to;
+            this.reverse = false;
+        }
+        checkSize();
+    }
+
+    /**
+     * Creates a new non-inclusive aware <code>IntRange</code>.
+     *
+     * @param from    the first value in the range.
+     * @param to      the last value in the range.
+     * @param reverse <code>true</code> if the range should count from
+     *                <code>to</code> to <code>from</code>.
+     * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
+     */
+    protected IntRange(int from, int to, boolean reverse) {
+        this.inclusive = null;
+        if (from > to) {
+            throw new IllegalArgumentException("'from' must be less than or equal to 'to'");
+        }
+
+        this.from = from;
+        this.to = to;
+        this.reverse = reverse;
+        checkSize();
+    }
+
+    /**
+     * Creates a new inclusive aware <code>IntRange</code>.
+     *
+     * @param from      the first value in the range.
+     * @param to        the last value in the range.
+     * @param inclusive <code>true</code> if the to value is included in the range.
+     */
+    public IntRange(boolean inclusive, int from, int to) {
+        this.from = from;
+        this.to = to;
+        this.inclusive = inclusive;
+        this.reverse = false; // range may still be reversed, this value is ignored for inclusive-aware ranges
+        checkSize();
+    }
+
+    /**
+     * Creates a new NumberRange with the same <code>from</code> and <code>to</code> as this
+     * IntRange but with a step size of <code>stepSize</code>.
+     *
+     * @param stepSize the desired step size
+     * @return a new NumberRange
+     * @since 2.5
+     */
+    public <T extends Number & Comparable> NumberRange by(T stepSize) {
+        return new NumberRange(NumberRange.comparableNumber((Number)from), NumberRange.comparableNumber((Number)to), stepSize, inclusive);
+    }
+
+    private void checkSize() {
+        // size() in the Collection interface returns an integer, so ranges can have no more than Integer.MAX_VALUE elements
+        final Long size = (long) to - from + 1;
+        if (size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("A range must have no more than " + Integer.MAX_VALUE + " elements but attempted " + size + " elements");
+        }
+    }
+
+    /**
+     * A method for determining from and to information when using this IntRange to index an aggregate object of the specified size.
+     * Normally only used internally within Groovy but useful if adding range indexing support for your own aggregates.
+     *
+     * @param size the size of the aggregate being indexed
+     * @return the calculated range information (with 1 added to the to value, ready for providing to subList
+     */
+    public RangeInfo subListBorders(int size) {
+        if (inclusive == null) {
+            throw new IllegalStateException("Should not call subListBorders on a non-inclusive aware IntRange");
+        }
+        int tempFrom = from;
+        if (tempFrom < 0) {
+            tempFrom += size;
+        }
+        int tempTo = to;
+        if (tempTo < 0) {
+            tempTo += size;
+        }
+        if (tempFrom > tempTo) {
+            return new RangeInfo(inclusive ? tempTo : tempTo + 1, tempFrom + 1, true);
+        }
+        return new RangeInfo(tempFrom, inclusive ? tempTo + 1 : tempTo, false);
+    }
+
+    /**
+     * Determines if this object is equal to another object. Delegates to
+     * {@link AbstractList#equals(Object)} if <code>that</code> is anything
+     * other than an {@link IntRange}.
+     * <p>
+     * It is not necessary to override <code>hashCode</code>, as
+     * {@link AbstractList#hashCode()} provides a suitable hash code.<p>
+     * <p>
+     * Note that equals is generally handled by {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#equals(List, List)}
+     * instead of this method.
+     *
+     * @param that the object to compare
+     * @return <code>true</code> if the objects are equal
+     */
+    public boolean equals(Object that) {
+        return that instanceof IntRange ? equals((IntRange) that) : super.equals(that);
+    }
+
+    /**
+     * Compares an {@link IntRange} to another {@link IntRange}.
+     *
+     * @param that the object to compare for equality
+     * @return <code>true</code> if the ranges are equal
+     */
+    public boolean equals(IntRange that) {
+        return that != null && ((inclusive == null && reverse == that.reverse && from == that.from && to == that.to)
+                || (inclusive != null && inclusive == that.inclusive && from == that.from && to == that.to));
+    }
+
+    @Override
+    public Integer getFrom() {
+        if (inclusive == null || from <= to) {
+            return from;
+        }
+        return inclusive ? to : to + 1;
+    }
+
+    @Override
+    public Integer getTo() {
+        if (inclusive == null) {
+            return to;
+        }
+        if (from <= to) {
+            return inclusive ? to : to - 1;
+        }
+        return from;
+    }
+
+    /**
+     * Returns the inclusive flag. Null for non-inclusive aware ranges or non-null for inclusive aware ranges.
+     */
+    public Boolean getInclusive() {
+        return inclusive;
+    }
+
+    /**
+     * Gets the 'from' value as a primitive integer.
+     *
+     * @return the 'from' value as a primitive integer.
+     */
+    public int getFromInt() {
+        return getFrom();
+    }
+
+    /**
+     * Gets the 'to' value as a primitive integer.
+     *
+     * @return the 'to' value as a primitive integer.
+     */
+    public int getToInt() {
+        return getTo();
+    }
+
+    @Override
+    public boolean isReverse() {
+        return inclusive == null ? reverse : (from > to);
+    }
+
+    @Override
+    public boolean containsWithinBounds(Object o) {
+        return contains(o);
+    }
+
+    @Override
+    public Integer get(int index) {
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
+        }
+        if (index >= size()) {
+            throw new IndexOutOfBoundsException("Index: " + index + " too big for range: " + this);
+        }
+        return isReverse() ? getTo() - index : index + getFrom();
+    }
+
+    @Override
+    public int size() {
+        return getTo() - getFrom() + 1;
+    }
+
+    @Override
+    public Iterator<Integer> iterator() {
+        return new IntRangeIterator();
+    }
+
+    @Override
+    public List<Integer> subList(int fromIndex, int toIndex) {
+        if (fromIndex < 0) {
+            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+        }
+        if (toIndex > size()) {
+            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
+        }
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+
+        if (fromIndex == toIndex) {
+            return new EmptyRange<Integer>(getFrom());
+        }
+
+        return new IntRange(fromIndex + getFrom(), toIndex + getFrom() - 1, isReverse());
+    }
+
+    public String toString() {
+        return inclusive != null ? ("" + from + ".." + (inclusive ? "" : "<") + to)
+                : (reverse ? "" + to + ".." + from : "" + from + ".." + to);
+    }
+
+    @Override
+    public String inspect() {
+        return toString();
+    }
+
+    @Override
+    public boolean contains(Object value) {
+        if (value instanceof Integer) {
+            return (Integer) value >= getFrom() && (Integer) value <= getTo();
+        }
+        if (value instanceof BigInteger) {
+            final BigInteger bigint = (BigInteger) value;
+            return bigint.compareTo(BigInteger.valueOf(getFrom())) >= 0 &&
+                    bigint.compareTo(BigInteger.valueOf(getTo())) <= 0;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean containsAll(Collection other) {
+        if (other instanceof IntRange) {
+            final IntRange range = (IntRange) other;
+            return getFrom() <= range.getFrom() && range.getTo() <= getTo();
+        }
+        return super.containsAll(other);
+    }
+
+    @Override
+    public void step(int step, Closure closure) {
+        if (step == 0) {
+            if (!getFrom().equals(getTo())) {
+                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
+            }
+            return; // from == to and step == 0, nothing to do, so return
+        }
+
+        if (isReverse()) {
+            step = -step;
+        }
+        if (step > 0) {
+            int value = getFrom();
+            while (value <= getTo()) {
+                closure.call(value);
+                if (((long) value + step) >= Integer.MAX_VALUE) {
+                    break;
+                }
+                value = value + step;
+            }
+        } else {
+            int value = getTo();
+            while (value >= getFrom()) {
+                closure.call(value);
+                if (((long) value + step) <= Integer.MIN_VALUE) {
+                    break;
+                }
+                value = value + step;
+            }
+        }
+    }
+
+    @Override
+    public List<Integer> step(int step) {
+        final IteratorClosureAdapter<Integer> adapter = new IteratorClosureAdapter<Integer>(this);
+        step(step, adapter);
+        return adapter.asList();
+    }
+
+    @Override
+    public int hashCode(){
+        int hashCode;
+        final int from = this.getFrom();
+        final int to = this.getTo();
+
+        hashCode = ((from+to+1)*(from+to))/2+to;
+        return hashCode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Interceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Interceptor.java b/src/main/groovy/groovy/lang/Interceptor.java
new file mode 100644
index 0000000..e496f1d
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Interceptor.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 groovy.lang;
+
+/**
+ * Implementers of this interface can be registered in the ProxyMetaClass for
+ * notifications about method calls for objects managed by the ProxyMetaClass.
+ * See groovy/lang/InterceptorTest.groovy for details.
+ * @author Dierk Koenig
+ */
+public interface Interceptor {
+    /**
+     * This code is executed before the method is optionally called.
+     * @param object        receiver object for the method call
+     * @param methodName    name of the method to call
+     * @param arguments     arguments to the method call
+     * @return any arbitrary result that replaces the result of the
+     * original method call only if doInvoke() returns false and afterInvoke()
+     * relays this result.
+     */
+    Object beforeInvoke(Object object, String methodName, Object[] arguments);
+    /**
+     * This code is executed after the method is optionally called.
+     * @param object        receiver object for the called method
+     * @param methodName    name of the called method
+     * @param arguments     arguments to the called method
+     * @param result        result of the executed method call or result of beforeInvoke if method was not called
+     * @return any arbitrary result that can replace the result of the
+     * original method call. Typically, the result parameter is returned.
+     */
+    Object afterInvoke(Object object, String methodName, Object[] arguments, Object result);
+    /**
+     * @return whether the target method should be invoked at all.
+     */
+    boolean doInvoke();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Lazy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Lazy.java b/src/main/groovy/groovy/lang/Lazy.java
new file mode 100644
index 0000000..17f044f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Lazy.java
@@ -0,0 +1,156 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Field annotation to simplify lazy initialization.
+ * <p>
+ * Example usage without any special modifiers just defers initialization until the first call but is not thread-safe:
+ * <pre>
+ * {@code @Lazy} T x
+ * </pre>
+ * becomes
+ * <pre>
+ * private T $x
+ *
+ * T getX() {
+ *    if ($x != null)
+ *       return $x
+ *    else {
+ *       $x = new T()
+ *       return $x
+ *    }
+ * }
+ * </pre>
+ *
+ * If the field is declared volatile then initialization will be synchronized using
+ * the <a href="http://en.wikipedia.org/wiki/Double-checked_locking">double-checked locking</a> pattern as shown here:
+ *
+ * <pre>
+ * {@code @Lazy} volatile T x
+ * </pre>
+ * becomes
+ * <pre>
+ * private volatile T $x
+ *
+ * T getX() {
+ *    T $x_local = $x
+ *    if ($x_local != null)
+ *       return $x_local
+ *    else {
+ *       synchronized(this) {
+ *          if ($x == null) {
+ *             $x = new T()
+ *          }
+ *          return $x
+ *       }
+ *    }
+ * }
+ * </pre>
+ *
+ * By default a field will be initialized by calling its default constructor.
+ *
+ * If the field has an initial value expression then this expression will be used instead of calling the default constructor.
+ * In particular, it is possible to use closure <code>{ ... } ()</code> syntax as follows:
+ *
+ * <pre>
+ * {@code @Lazy} T x = { [1, 2, 3] } ()
+ * </pre>
+ * becomes
+ * <pre>
+ * private T $x
+ *
+ * T getX() {
+ *    T $x_local = $x
+ *    if ($x_local != null)
+ *       return $x_local
+ *    else {
+ *       synchronized(this) {
+ *          if ($x == null) {
+ *             $x = { [1, 2, 3] } ()
+ *          }
+ *          return $x
+ *       }
+ *    }
+ * }
+ * </pre>
+ * <p>
+ * <code>@Lazy(soft=true)</code> will use a soft reference instead of the field and use the above rules each time re-initialization is required.
+ * <p>
+ * If the <code>soft</code> flag for the annotation is not set but the field is static, then
+ * the <a href="http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom">initialization on demand holder idiom</a> is
+ * used as follows:
+ * <pre>
+ * {@code @Lazy} static FieldType field
+ * {@code @Lazy} static Date date1
+ * {@code @Lazy} static Date date2 = { new Date().copyWith(year: 2000) }()
+ * {@code @Lazy} static Date date3 = new GregorianCalendar(2009, Calendar.JANUARY, 1).time
+ * </pre>
+ * becomes these methods and inners classes within the class containing the above definitions:
+ * <pre>
+ * private static class FieldTypeHolder_field {
+ *     private static final FieldType INSTANCE = new FieldType()
+ * }
+ *
+ * private static class DateHolder_date1 {
+ *     private static final Date INSTANCE = new Date()
+ * }
+ *
+ * private static class DateHolder_date2 {
+ *     private static final Date INSTANCE = { new Date().copyWith(year: 2000) }()
+ * }
+ *
+ * private static class DateHolder_date3 {
+ *     private static final Date INSTANCE = new GregorianCalendar(2009, Calendar.JANUARY, 1).time
+ * }
+ *
+ * static FieldType getField() {
+ *     return FieldTypeHolder_field.INSTANCE
+ * }
+ *
+ * static Date getDate1() {
+ *     return DateHolder_date1.INSTANCE
+ * }
+ *
+ * static Date getDate2() {
+ *     return DateHolder_date2.INSTANCE
+ * }
+ *
+ * static Date getDate3() {
+ *     return DateHolder_date3.INSTANCE
+ * }
+ * </pre>
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LazyASTTransformation")
+public @interface Lazy {
+    /**
+     * @return if field should be soft referenced instead of hard referenced
+     */
+    boolean soft () default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ListWithDefault.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ListWithDefault.java b/src/main/groovy/groovy/lang/ListWithDefault.java
new file mode 100644
index 0000000..6b87548
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ListWithDefault.java
@@ -0,0 +1,257 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * A wrapper for {@link List} which automatically grows the list when either {@link #get(int)} or
+ * {@link #getAt(int)} is called with an index greater than or equal to {@code size()}.
+ *
+ * @author Andre Steingress
+ * @since 1.8.7
+ */
+public final class ListWithDefault<T> implements List<T> {
+
+    private final List<T> delegate;
+    private final boolean lazyDefaultValues;
+
+    private final Closure initClosure;
+
+    private ListWithDefault(List<T> items, boolean lazyDefaultValues, Closure initClosure) {
+        this.delegate = items;
+        this.lazyDefaultValues = lazyDefaultValues;
+        this.initClosure = initClosure;
+    }
+
+    public List<T> getDelegate() {
+        return delegate != null ? new ArrayList<T>(delegate) : null;
+    }
+
+    public boolean isLazyDefaultValues() {
+        return lazyDefaultValues;
+    }
+
+    public Closure getInitClosure() {
+        return initClosure != null ? (Closure) initClosure.clone() : null;
+    }
+
+    public static <T> ListWithDefault<T> newInstance(List<T> items, boolean lazyDefaultValues, Closure initClosure) {
+        if (items == null)
+            throw new IllegalArgumentException("Parameter \"items\" must not be null");
+        if (initClosure == null)
+            throw new IllegalArgumentException("Parameter \"initClosure\" must not be null");
+
+        return new ListWithDefault<T>(new ArrayList<T>(items), lazyDefaultValues, (Closure) initClosure.clone());
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public boolean contains(Object o) {
+        return delegate.contains(o);
+    }
+
+    public Iterator<T> iterator() {
+        return delegate.iterator();
+    }
+
+    public Object[] toArray() {
+        return delegate.toArray();
+    }
+
+    public <T> T[] toArray(T[] ts) {
+        return delegate.toArray(ts);
+    }
+
+    public boolean add(T t) {
+        return delegate.add(t);
+    }
+
+    public boolean remove(Object o) {
+        return delegate.remove(o);
+    }
+
+    public boolean containsAll(Collection<?> objects) {
+        return delegate.containsAll(objects);
+    }
+
+    public boolean addAll(Collection<? extends T> ts) {
+        return delegate.addAll(ts);
+    }
+
+    public boolean addAll(int i, Collection<? extends T> ts) {
+        return delegate.addAll(i, ts);
+    }
+
+    public boolean removeAll(Collection<?> objects) {
+        return delegate.removeAll(objects);
+    }
+
+    public boolean retainAll(Collection<?> objects) {
+        return delegate.retainAll(objects);
+    }
+
+    public void clear() {
+        delegate.clear();
+    }
+
+    /**
+     * Overwrites subscript operator handling by redirecting to {@link #get(int)}.
+     *
+     * @param index an index (might be greater or equal to {@code size()}, or smaller than 0)
+     * @return the value at the given {@code index} or the default value
+     */
+    public T getAt(int index) {
+        return get(index);
+    }
+
+    /**
+     * Returns the element at the given index but grows the list if needed. If the requested {@code index} is
+     * greater than or equal to {@code size()}, the list will grow to the new size and a default value calculated
+     * using the <code>initClosure</code> will be used to populate the missing value and returned.
+     * <p>
+     * If <code>lazyDefaultValues</code> is <code>true</code> any gaps when growing the list are filled
+     * with nulls. Subsequent attempts to retrieve items from the list from those gap index values
+     * will, upon finding null, call the <code>initClosure</code> to populate the list for the
+     * given list value. Hence, when in this mode, nulls cannot be stored in this list.
+     * If <code>lazyDefaultValues</code> is <code>false</code> any gaps when growing the list are filled
+     * eagerly by calling the <code>initClosure</code> for all gap indexes during list growth.
+     * No calls to <code>initClosure</code> are made except during list growth and it is ok to
+     * store null values in the list when in this mode.
+     * <p>
+     * This implementation breaks
+     * the contract of {@link java.util.List#get(int)} as it a) possibly modifies the underlying list and b) does
+     * NOT throw an {@link IndexOutOfBoundsException} when {@code index < 0 || index >= size()}.
+     *
+     * @param index an index (might be greater or equal to {@code size()}, or smaller than 0)
+     * @return the value at the given {@code index} or the default value
+     */
+    public T get(int index) {
+
+        final int size = size();
+        int normalisedIndex = normaliseIndex(index, size);
+        if (normalisedIndex < 0) {
+            throw new IndexOutOfBoundsException("Negative index [" + normalisedIndex + "] too large for list size " + size);
+        }
+
+        // either index >= size or the normalised index is negative
+        if (normalisedIndex >= size) {
+            // find out the number of gaps to fill with null/the default value
+            final int gapCount = normalisedIndex - size;
+
+            // fill all gaps
+            for (int i = 0; i < gapCount; i++) {
+                final int idx = size();
+
+                // if we lazily create default values, use 'null' as placeholder
+                if (lazyDefaultValues)
+                    delegate.add(idx, null);
+                else
+                    delegate.add(idx, getDefaultValue(idx));
+            }
+
+            // add the first/last element being always the default value
+            final int idx = normalisedIndex;
+            delegate.add(idx, getDefaultValue(idx));
+
+            // normalise index again to get positive index
+            normalisedIndex = normaliseIndex(index, size());
+        }
+
+        T item = delegate.get(normalisedIndex);
+        if (item == null && lazyDefaultValues) {
+            item = getDefaultValue(normalisedIndex);
+            delegate.set(normalisedIndex, item);
+        }
+
+        return item;
+    }
+
+    @SuppressWarnings("unchecked")
+    private T getDefaultValue(int idx) {
+        return (T) initClosure.call(new Object[]{idx});
+    }
+
+    private static int normaliseIndex(int index, int size) {
+        if (index < 0) {
+            index += size;
+        }
+        return index;
+    }
+
+    public T set(int i, T t) {
+        return delegate.set(i, t);
+    }
+
+    public void add(int i, T t) {
+        delegate.add(i, t);
+    }
+
+    public T remove(int i) {
+        return delegate.remove(i);
+    }
+
+    public int indexOf(Object o) {
+        return delegate.indexOf(o);
+    }
+
+    public int lastIndexOf(Object o) {
+        return delegate.lastIndexOf(o);
+    }
+
+    public ListIterator<T> listIterator() {
+        return delegate.listIterator();
+    }
+
+    public ListIterator<T> listIterator(int i) {
+        return delegate.listIterator(i);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return delegate.equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    /**
+     * Returns a view of a portion of this list. This method returns a list with the same
+     * lazy list settings as the original list.
+     *
+     * @param fromIndex low endpoint of the subList (inclusive)
+     * @param toIndex   upper endpoint of the subList (exclusive)
+     * @return a view of a specified range within this list, keeping all lazy list settings
+     */
+    public ListWithDefault<T> subList(int fromIndex, int toIndex) {
+        return new ListWithDefault<T>(delegate.subList(fromIndex, toIndex), lazyDefaultValues, (Closure) initClosure.clone());
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MapWithDefault.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MapWithDefault.java b/src/main/groovy/groovy/lang/MapWithDefault.java
new file mode 100644
index 0000000..166e06b
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MapWithDefault.java
@@ -0,0 +1,105 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A wrapper for Map which allows a default value to be specified.
+ *
+ * @author Paul King
+ * @since 1.7.1
+ */
+public final class MapWithDefault<K, V> implements Map<K, V> {
+
+    private final Map<K, V> delegate;
+    private final Closure initClosure;
+
+    private MapWithDefault(Map<K, V> m, Closure initClosure) {
+        delegate = m;
+        this.initClosure = initClosure;
+    }
+
+    public static <K, V> Map<K, V> newInstance(Map<K, V> m, Closure initClosure) {
+        return new MapWithDefault<K, V>(m, initClosure);
+    }
+
+    public int size() {
+        return delegate.size();
+    }
+
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    public boolean containsKey(Object key) {
+        return delegate.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return delegate.containsValue(value);
+    }
+
+    public V get(Object key) {
+        if (!delegate.containsKey(key)) {
+            delegate.put((K)key, (V)initClosure.call(new Object[]{key}));
+        }
+        return delegate.get(key);
+    }
+
+    public V put(K key, V value) {
+        return delegate.put(key, value);
+    }
+
+    public V remove(Object key) {
+        return delegate.remove(key);
+    }
+
+    public void putAll(Map<? extends K, ? extends V> m) {
+        delegate.putAll(m);
+    }
+
+    public void clear() {
+        delegate.clear();
+    }
+
+    public Set<K> keySet() {
+        return delegate.keySet();
+    }
+
+    public Collection<V> values() {
+        return delegate.values();
+    }
+
+    public Set<Map.Entry<K, V>> entrySet() {
+        return delegate.entrySet();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return delegate.equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaArrayLengthProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaArrayLengthProperty.java b/src/main/groovy/groovy/lang/MetaArrayLengthProperty.java
new file mode 100644
index 0000000..8310386
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaArrayLengthProperty.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 groovy.lang;
+
+
+/**
+ * Represents the length property of an array
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class MetaArrayLengthProperty extends MetaProperty {
+
+    /**
+     * Sole constructor setting name to "length" and type to int
+     */
+    public MetaArrayLengthProperty() {
+        super("length", int.class);
+    }
+
+    /**
+     * Get this property from the given object.
+     * @param object an array
+     * @return the length of the array object
+     * @throws IllegalArgumentException if object is not an array
+     */
+    public Object getProperty(Object object) {
+        return java.lang.reflect.Array.getLength(object);
+    }
+
+    /**
+     * Sets the property on the given object to the new value
+     *
+     * @param object   on which to set the property
+     * @param newValue the new value of the property
+     * @throws RuntimeException if the property could not be set
+     */
+    public void setProperty(Object object, Object newValue) {
+        throw new ReadOnlyPropertyException("length", object.getClass());
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaBeanProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaBeanProperty.java b/src/main/groovy/groovy/lang/MetaBeanProperty.java
new file mode 100644
index 0000000..89328af
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaBeanProperty.java
@@ -0,0 +1,156 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.reflection.CachedField;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Represents a property on a bean which may have a getter and/or a setter
+ */
+public class MetaBeanProperty extends MetaProperty {
+
+    private MetaMethod getter;
+    private MetaMethod setter;
+    private CachedField field;
+
+    /**
+     * Sole constructor setting name, type (class), getter and setter.
+     */
+    public MetaBeanProperty(String name, Class type, MetaMethod getter, MetaMethod setter) {
+        super(name, type);
+        this.getter = getter;
+        this.setter = setter;
+    }
+
+    /**
+     * Get the property of the given object.
+     *
+     * @param object which to be got
+     * @return the property of the given object
+     * @throws RuntimeException if the property could not be evaluated
+     */
+    public Object getProperty(Object object) {
+        MetaMethod getter = getGetter();
+        if (getter == null) {
+            if (field != null) return field.getProperty(object);
+            //TODO: create a WriteOnlyException class?
+            throw new GroovyRuntimeException("Cannot read write-only property: " + name);
+        }
+        return getter.invoke(object, MetaClassHelper.EMPTY_ARRAY);
+    }
+
+    /**
+     * Set the property on the given object to the new value.
+     *
+     * @param object   on which to set the property
+     * @param newValue the new value of the property
+     * @throws RuntimeException if the property could not be set
+     */
+    public void setProperty(Object object, Object newValue) {
+        MetaMethod setter = getSetter();
+        if (setter == null) {
+            if (field != null && !Modifier.isFinal(field.getModifiers())) {
+                field.setProperty(object, newValue);
+                return;
+            }
+            throw new GroovyRuntimeException("Cannot set read-only property: " + name);
+        }
+        newValue = DefaultTypeTransformation.castToType(newValue, getType());
+        setter.invoke(object, new Object[]{newValue});
+    }
+
+    /**
+     * Get the getter method.
+     *
+     * @return the getter method for this property.
+     */
+    public MetaMethod getGetter() {
+        return getter;
+    }
+
+    /**
+     * Get the setter method.
+     *
+     * @return the setter method for this property.
+     */
+    public MetaMethod getSetter() {
+        return setter;
+    }
+
+    /**
+     * This is for MetaClass to patch up the object later when looking for get*() methods.
+     *
+     * @param getter The getter for this property
+     */
+    void setGetter(MetaMethod getter) {
+        this.getter = getter;
+    }
+
+    /**
+     * This is for MetaClass to patch up the object later when looking for set*() methods.
+     *
+     * @param setter The setter for this property 
+     */
+    void setSetter(MetaMethod setter) {
+        this.setter = setter;
+    }
+
+    /**
+     * Gets the visibility modifiers for the property as defined by the getter and setter methods.
+     *
+     * @return the visibility modifier of the getter, the setter, or both depending on which exist
+     */
+    public int getModifiers() {
+        MetaMethod getter = getGetter();
+        MetaMethod setter = getSetter();
+        if (setter != null && getter == null) return setter.getModifiers();
+        if (getter != null && setter == null) return getter.getModifiers();
+        int modifiers = getter.getModifiers() | setter.getModifiers();
+        int visibility = 0;
+        if (Modifier.isPublic(modifiers)) visibility = Modifier.PUBLIC;
+        if (Modifier.isProtected(modifiers)) visibility = Modifier.PROTECTED;
+        if (Modifier.isPrivate(modifiers)) visibility = Modifier.PRIVATE;
+        int states = getter.getModifiers() & setter.getModifiers();
+        states &= ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);
+        states |= visibility;
+        return states;
+    }
+
+    /**
+     * Sets the field of this property
+     *
+     * @param field
+     */
+    public void setField(CachedField field) {
+        this.field = field;
+    }
+
+    /**
+     * Gets the field of this property
+     *
+     * @return The field of this property
+     */
+    public CachedField getField() {
+        return field;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaClass.java b/src/main/groovy/groovy/lang/MetaClass.java
new file mode 100644
index 0000000..42c6a83
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaClass.java
@@ -0,0 +1,207 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.ast.ClassNode;
+
+import java.util.List;
+
+/**
+ * A MetaClass within Groovy defines the behaviour of any given Groovy or Java class. The MetaClass
+ * interface defines two parts. The client API, which is defined via the extend MetaObjectProtocol interface
+ * and the contract with the Groovy runtime system.
+ *
+ * In general the compiler and Groovy runtime engine interact with methods on this class whilst MetaClass
+ * clients interact with the method defined by the MetaObjectProtocol interface
+ *
+ * @see MetaClassImpl
+ * @see groovy.lang.MetaObjectProtocol
+ * 
+ * @author John Wilson
+ * @author Graeme Rocher
+ */
+public interface MetaClass extends MetaObjectProtocol {
+
+    /**
+     * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
+     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
+     *
+     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
+     * to the super class if necessary
+     *
+     * @param sender The java.lang.Class instance that invoked the method
+     * @param receiver The object which the method was invoked on
+     * @param methodName The name of the method
+     * @param arguments The arguments to the method
+     * @param isCallToSuper Whether the method is a call to a super class method
+     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
+     *
+     * @return The return value of the method
+     */
+     Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass);
+
+    /**
+     * <p>Retrieves a property on the given receiver for the specified arguments. The sender is the class that is requesting the property from the object.
+     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
+     *
+     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
+     * to the super class if necessary
+     *
+     * @param sender The java.lang.Class instance that requested the property
+     * @param receiver The Object which the property is being retrieved from
+     * @param property The name of the property
+     * @param isCallToSuper Whether the call is to a super class property
+     * @param fromInsideClass ??
+     *
+     * @return The properties value
+     */
+     Object getProperty(Class sender, Object receiver, String property, boolean isCallToSuper, boolean fromInsideClass);
+
+    /**
+     * <p>Sets a property on the given receiver for the specified arguments. The sender is the class that is setting the property from the object.
+     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
+     *
+     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
+     * to the super class if necessary
+     *
+     * @param sender The java.lang.Class instance that is mutating the property
+     * @param receiver The Object which the property is being set on
+     * @param property The name of the property
+     * @param value The new value of the property to set
+     * @param isCallToSuper Whether the call is to a super class property
+     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
+     */
+     void setProperty(Class sender, Object receiver, String property, Object value, boolean isCallToSuper, boolean fromInsideClass);
+
+    /**
+     *
+     * <p>Attempts to invoke the methodMissing method otherwise throws a MissingMethodException
+     *
+     * @see groovy.lang.MissingMethodException
+     *
+     * @param instance The instance to invoke methodMissing on
+     * @param methodName The name of the method
+     * @param arguments The arguments to the method
+     * @return The results of methodMissing or throws MissingMethodException
+     */
+     Object invokeMissingMethod(Object instance, String methodName, Object[] arguments);
+
+    /**
+     * Invokes the propertyMissing method otherwise throws a MissingPropertyException
+     *
+     * @param instance The instance of the class
+     * @param propertyName The name of the property
+     * @param optionalValue The value of the property which could be null in the case of a getter
+     * @param isGetter Whether the missing property event was the result of a getter or a setter
+     * 
+     * @return The result of the propertyMissing method or throws MissingPropertyException
+     */
+     Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter);
+
+    /**
+     * Retrieves the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
+     *
+     * @param sender The class of the object that requested the attribute
+     * @param receiver The instance
+     * @param messageName The name of the attribute
+     * @param useSuper Whether to look-up on the super class or not
+     * @return The attribute value
+     */
+     Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper);
+
+    /**
+     * Sets the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
+     *
+     * @param sender The class of the object that requested the attribute
+     * @param receiver The instance
+     * @param messageName The name of the attribute
+     * @param messageValue The value of the attribute
+     * @param useSuper Whether to look-up on the super class or not
+     * @param fromInsideClass Whether the call happened from the inside or the outside of a class
+     */
+     void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass);
+    
+    /**
+     * Complete the initialisation process. After this method
+     * is called no methods should be added to the meta class.
+     * Invocation of methods or access to fields/properties is
+     * forbidden unless this method is called. This method 
+     * should contain any initialisation code, taking a longer
+     * time to complete. An example is the creation of the 
+     * Reflector. It is suggested to synchronize this 
+     * method.
+     */
+     void initialize();
+
+    /**
+     * Retrieves a list of MetaProperty instances that the MetaClass has
+     *
+     * @see MetaProperty
+     *
+     * @return A list of MetaProperty instances
+     */
+     List<MetaProperty> getProperties();
+
+    /**
+     * Retrieves a list of MetaMethods held by the class. This list does not include MetaMethods added by groovy.lang.ExpandoMetaClass.
+     *
+     * @return A list of MetaMethods
+     */
+     List<MetaMethod> getMethods();
+     
+     /**
+      * Obtains a reference to the original AST for the MetaClass if it is available at runtime
+      *
+      * @return The original AST or null if it cannot be returned
+      */
+     ClassNode getClassNode();
+
+     /**
+      * Retrieves a list of MetaMethods held by this class. This list includes MetaMethods added by groovy.lang.ExpandoMetaClass.
+      *
+      * @return A list of MetaMethods
+      */
+     List<MetaMethod> getMetaMethods();
+    
+     /**
+      *
+      * Internal method to support Groovy runtime. Not for client usage.
+      *
+      * @param numberOfConstructors The number of constructors
+      * @param arguments The arguments
+      *
+      * @return selected index
+      */
+     int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments);
+
+    /**
+     * Selects a method by name and argument classes. This method
+     * does not search for an exact match, it searches for a compatible
+     * method. For this the method selection mechanism is used as provided
+     * by the implementation of this MetaClass. pickMethod may or may
+     * not be used during the method selection process when invoking a method.
+     * There is no warranty for that.
+     *
+     * @return a matching MetaMethod or null
+     * @throws GroovyRuntimeException if there is more than one matching method
+     * @param methodName the name of the method to pick
+     * @param arguments the method arguments
+     */
+     MetaMethod pickMethod(String methodName, Class[] arguments);
+}


[24/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/GroovyScriptEngine.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/GroovyScriptEngine.java b/src/main/groovy/groovy/util/GroovyScriptEngine.java
new file mode 100644
index 0000000..92e2486
--- /dev/null
+++ b/src/main/groovy/groovy/util/GroovyScriptEngine.java
@@ -0,0 +1,694 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyCodeSource;
+import groovy.lang.GroovyResourceLoader;
+import groovy.lang.Script;
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.classgen.GeneratorContext;
+import org.codehaus.groovy.control.ClassNodeResolver;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.Phases;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.customizers.CompilationCustomizer;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.tools.gse.DependencyTracker;
+import org.codehaus.groovy.tools.gse.StringSetMap;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.ref.WeakReference;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Specific script engine able to reload modified scripts as well as dealing properly
+ * with dependent scripts.
+ *
+ * @author sam
+ * @author Marc Palmer
+ * @author Guillaume Laforge
+ * @author Jochen Theodorou
+ * @author Mattias Reichel
+ */
+public class GroovyScriptEngine implements ResourceConnector {
+    private static final ClassLoader CL_STUB = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+        public ClassLoader run() {
+            return new ClassLoader() {};
+        }
+    });
+
+    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+
+    private static class LocalData {
+        CompilationUnit cu;
+        final StringSetMap dependencyCache = new StringSetMap();
+        final Map<String, String> precompiledEntries = new HashMap<String, String>();
+    }
+
+    private static WeakReference<ThreadLocal<LocalData>> localData = new WeakReference<ThreadLocal<LocalData>>(null);
+
+    private static synchronized ThreadLocal<LocalData> getLocalData() {
+        ThreadLocal<LocalData> local = localData.get();
+        if (local != null) return local;
+        local = new ThreadLocal<LocalData>();
+        localData = new WeakReference<ThreadLocal<LocalData>>(local);
+        return local;
+    }
+
+    private final URL[] roots;
+    private final ResourceConnector rc;
+    private final ClassLoader parentLoader;
+    private GroovyClassLoader groovyLoader;
+    private final Map<String, ScriptCacheEntry> scriptCache = new ConcurrentHashMap<String, ScriptCacheEntry>();
+    private CompilerConfiguration config;
+
+    {
+        config = new CompilerConfiguration(CompilerConfiguration.DEFAULT);
+        config.setSourceEncoding(CompilerConfiguration.DEFAULT_SOURCE_ENCODING);
+    }
+
+
+    //TODO: more finals?
+
+    private static class ScriptCacheEntry {
+        private final Class scriptClass;
+        private final long lastModified, lastCheck;
+        private final Set<String> dependencies;
+        private final boolean sourceNewer;
+
+        public ScriptCacheEntry(Class clazz, long modified, long lastCheck, Set<String> depend, boolean sourceNewer) {
+            this.scriptClass = clazz;
+            this.lastModified = modified;
+            this.lastCheck = lastCheck;
+            this.dependencies = depend;
+            this.sourceNewer = sourceNewer;
+        }
+
+        public ScriptCacheEntry(ScriptCacheEntry old, long lastCheck, boolean sourceNewer) {
+            this(old.scriptClass, old.lastModified, lastCheck, old.dependencies, sourceNewer);
+        }
+    }
+
+    private class ScriptClassLoader extends GroovyClassLoader {
+
+
+        public ScriptClassLoader(GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public ScriptClassLoader(ClassLoader loader, CompilerConfiguration config) {
+            super(loader, config, false);
+            setResLoader();
+        }
+
+        private void setResLoader() {
+            final GroovyResourceLoader rl = getResourceLoader();
+            setResourceLoader(new GroovyResourceLoader() {
+                public URL loadGroovySource(String className) throws MalformedURLException {
+                    String filename;
+                    for (String extension : getConfig().getScriptExtensions()) {
+                        filename = className.replace('.', File.separatorChar) + "." + extension;
+                        try {
+                            URLConnection dependentScriptConn = rc.getResourceConnection(filename);
+                            return dependentScriptConn.getURL();
+                        } catch (ResourceException e) {
+                            //TODO: maybe do something here?
+                        }
+                    }
+                    return rl.loadGroovySource(className);
+                }
+            });
+        }
+
+        @Override
+        protected CompilationUnit createCompilationUnit(CompilerConfiguration configuration, CodeSource source) {
+            CompilationUnit cu = super.createCompilationUnit(configuration, source);
+            LocalData local = getLocalData().get();
+            local.cu = cu;
+            final StringSetMap cache = local.dependencyCache;
+            final Map<String, String> precompiledEntries = local.precompiledEntries;
+
+            // "." is used to transfer compilation dependencies, which will be
+            // recollected later during compilation
+            for (String depSourcePath : cache.get(".")) {
+                try {
+                    cache.get(depSourcePath);
+                    cu.addSource(getResourceConnection(depSourcePath).getURL());
+                } catch (ResourceException e) {
+                    /* ignore */
+                }
+            }
+
+            // remove all old entries including the "." entry
+            cache.clear();
+
+            cu.addPhaseOperation(new CompilationUnit.PrimaryClassNodeOperation() {
+                @Override
+                public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode)
+                        throws CompilationFailedException {
+                    // GROOVY-4013: If it is an inner class, tracking its dependencies doesn't really
+                    // serve any purpose and also interferes with the caching done to track dependencies
+                    if (classNode instanceof InnerClassNode) return;
+                    DependencyTracker dt = new DependencyTracker(source, cache, precompiledEntries);
+                    dt.visitClass(classNode);
+                }
+            }, Phases.CLASS_GENERATION);
+
+            cu.setClassNodeResolver(new ClassNodeResolver() {
+                @Override
+                public LookupResult findClassNode(String origName, CompilationUnit compilationUnit) {
+                    CompilerConfiguration cc = compilationUnit.getConfiguration();
+                    String name = origName.replace('.', '/');
+                    for (String ext : cc.getScriptExtensions()) {
+                        try {
+                            String finalName = name + "." + ext;
+                            URLConnection conn = rc.getResourceConnection(finalName);
+                            URL url = conn.getURL();
+                            String path = url.toExternalForm();
+                            ScriptCacheEntry entry = scriptCache.get(path);
+                            Class clazz = null;
+                            if (entry != null) clazz = entry.scriptClass;
+                            if (GroovyScriptEngine.this.isSourceNewer(entry)) {
+                                try {
+                                    SourceUnit su = compilationUnit.addSource(url);
+                                    return new LookupResult(su, null);
+                                } finally {
+                                    forceClose(conn);
+                                }
+                            } else {
+                                precompiledEntries.put(origName, path);
+                            }
+                            if (clazz != null) {
+                                ClassNode cn = new ClassNode(clazz);
+                                return new LookupResult(null, cn);
+                            }
+                        } catch (ResourceException re) {
+                            // skip
+                        }
+                    }
+                    return super.findClassNode(origName, compilationUnit);
+                }
+            });
+
+            return cu;
+        }
+
+        @Override
+        public Class parseClass(GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException {
+            synchronized (sourceCache) {
+                return doParseClass(codeSource);
+            }
+        }
+
+        private Class<?> doParseClass(GroovyCodeSource codeSource) {
+            // local is kept as hard reference to avoid garbage collection
+            ThreadLocal<LocalData> localTh = getLocalData();
+            LocalData localData = new LocalData();
+            localTh.set(localData);
+            StringSetMap cache = localData.dependencyCache;
+            Class<?> answer = null;
+            try {
+                updateLocalDependencyCache(codeSource, localData);
+                answer = super.parseClass(codeSource, false);
+                updateScriptCache(localData);
+            } finally {
+                cache.clear();
+                localTh.remove();
+            }
+            return answer;
+        }
+
+        private void updateLocalDependencyCache(GroovyCodeSource codeSource, LocalData localData) {
+            // we put the old dependencies into local cache so createCompilationUnit
+            // can pick it up. We put that entry under the name "."
+            ScriptCacheEntry origEntry = scriptCache.get(codeSource.getName());
+            Set<String> origDep = null;
+            if (origEntry != null) origDep = origEntry.dependencies;
+            if (origDep != null) {
+                Set<String> newDep = new HashSet<String>(origDep.size());
+                for (String depName : origDep) {
+                    ScriptCacheEntry dep = scriptCache.get(depName);
+                    try {
+                        if (origEntry == dep || GroovyScriptEngine.this.isSourceNewer(dep)) {
+                            newDep.add(depName);
+                        }
+                    } catch (ResourceException re) {
+
+                    }
+                }
+                StringSetMap cache = localData.dependencyCache;
+                cache.put(".", newDep);
+            }
+        }
+
+        private void updateScriptCache(LocalData localData) {
+            StringSetMap cache = localData.dependencyCache;
+            cache.makeTransitiveHull();
+            long time = getCurrentTime();
+            Set<String> entryNames = new HashSet<String>();
+            for (Map.Entry<String, Set<String>> entry : cache.entrySet()) {
+                String className = entry.getKey();
+                Class clazz = getClassCacheEntry(className);
+                if (clazz == null) continue;
+
+                String entryName = getPath(clazz, localData.precompiledEntries);
+                if (entryNames.contains(entryName)) continue;
+                entryNames.add(entryName);
+                Set<String> value = convertToPaths(entry.getValue(), localData.precompiledEntries);
+                long lastModified;
+                try {
+                    lastModified = getLastModified(entryName);
+                } catch (ResourceException e) {
+                    lastModified = time;
+                }
+                ScriptCacheEntry cacheEntry = new ScriptCacheEntry(clazz, lastModified, time, value, false);
+                scriptCache.put(entryName, cacheEntry);
+            }
+        }
+
+        private String getPath(Class clazz, Map<String, String> precompiledEntries) {
+            CompilationUnit cu = getLocalData().get().cu;
+            String name = clazz.getName();
+            ClassNode classNode = cu.getClassNode(name);
+            if (classNode == null) {
+                // this is a precompiled class!
+                String path = precompiledEntries.get(name);
+                if (path == null) throw new GroovyBugError("Precompiled class " + name + " should be available in precompiled entries map, but was not.");
+                return path;
+            } else {
+                return classNode.getModule().getContext().getName();
+            }
+        }
+
+        private Set<String> convertToPaths(Set<String> orig, Map<String, String> precompiledEntries) {
+            Set<String> ret = new HashSet<String>();
+            for (String className : orig) {
+                Class clazz = getClassCacheEntry(className);
+                if (clazz == null) continue;
+                ret.add(getPath(clazz, precompiledEntries));
+            }
+            return ret;
+        }
+    }
+
+    /**
+     * Simple testing harness for the GSE. Enter script roots as arguments and
+     * then input script names to run them.
+     *
+     * @param urls an array of URLs
+     * @throws Exception if something goes wrong
+     */
+    public static void main(String[] urls) throws Exception {
+        GroovyScriptEngine gse = new GroovyScriptEngine(urls);
+        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+        String line;
+        while (true) {
+            System.out.print("groovy> ");
+            if ((line = br.readLine()) == null || line.equals("quit")) {
+                break;
+            }
+            try {
+                System.out.println(gse.run(line, new Binding()));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Initialize a new GroovyClassLoader with a default or
+     * constructor-supplied parentClassLoader.
+     *
+     * @return the parent classloader used to load scripts
+     */
+    private GroovyClassLoader initGroovyLoader() {
+        GroovyClassLoader groovyClassLoader =
+                AccessController.doPrivileged(new PrivilegedAction<ScriptClassLoader>() {
+                    public ScriptClassLoader run() {
+                        if (parentLoader instanceof GroovyClassLoader) {
+                            return new ScriptClassLoader((GroovyClassLoader) parentLoader);
+                        } else {
+                            return new ScriptClassLoader(parentLoader, config);
+                        }
+                    }
+                });
+        for (URL root : roots) groovyClassLoader.addURL(root);
+        return groovyClassLoader;
+    }
+
+    /**
+     * Get a resource connection as a <code>URLConnection</code> to retrieve a script
+     * from the <code>ResourceConnector</code>.
+     *
+     * @param resourceName name of the resource to be retrieved
+     * @return a URLConnection to the resource
+     * @throws ResourceException
+     */
+    public URLConnection getResourceConnection(String resourceName) throws ResourceException {
+        // Get the URLConnection
+        URLConnection groovyScriptConn = null;
+
+        ResourceException se = null;
+        for (URL root : roots) {
+            URL scriptURL = null;
+            try {
+                scriptURL = new URL(root, resourceName);
+                groovyScriptConn = openConnection(scriptURL);
+
+                break; // Now this is a bit unusual
+            } catch (MalformedURLException e) {
+                String message = "Malformed URL: " + root + ", " + resourceName;
+                if (se == null) {
+                    se = new ResourceException(message);
+                } else {
+                    se = new ResourceException(message, se);
+                }
+            } catch (IOException e1) {
+                String message = "Cannot open URL: " + root + resourceName;
+                groovyScriptConn = null;
+                if (se == null) {
+                    se = new ResourceException(message);
+                } else {
+                    se = new ResourceException(message, se);
+                }
+            }
+        }
+
+        if (se == null) se = new ResourceException("No resource for " + resourceName + " was found");
+
+        // If we didn't find anything, report on all the exceptions that occurred.
+        if (groovyScriptConn == null) throw se;
+        return groovyScriptConn;
+    }
+
+    private static URLConnection openConnection(URL scriptURL) throws IOException {
+        URLConnection urlConnection = scriptURL.openConnection();
+        verifyInputStream(urlConnection);
+
+        return scriptURL.openConnection();
+    }
+
+    /**
+     * This method closes a {@link URLConnection} by getting its {@link InputStream} and calling the
+     * {@link InputStream#close()} method on it. The {@link URLConnection} doesn't have a close() method
+     * and relies on garbage collection to close the underlying connection to the file.
+     * Relying on garbage collection could lead to the application exhausting the number of files the
+     * user is allowed to have open at any one point in time and cause the application to crash
+     * ({@link java.io.FileNotFoundException} (Too many open files)).
+     * Hence the need for this method to explicitly close the underlying connection to the file.
+     *
+     * @param urlConnection the {@link URLConnection} to be "closed" to close the underlying file descriptors.
+     */
+    private static void forceClose(URLConnection urlConnection) {
+        if (urlConnection != null) {
+            // We need to get the input stream and close it to force the open
+            // file descriptor to be released. Otherwise, we will reach the limit
+            // for number of files open at one time.
+
+            try {
+                verifyInputStream(urlConnection);
+            } catch (Exception e) {
+                // Do nothing: We were not going to use it anyway.
+            }
+        }
+    }
+
+    private static void verifyInputStream(URLConnection urlConnection) throws IOException {
+        InputStream in = null;
+        try {
+            in = urlConnection.getInputStream();
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException ignore) {
+                }
+            }
+        }
+    }
+
+    /**
+     * The groovy script engine will run groovy scripts and reload them and
+     * their dependencies when they are modified. This is useful for embedding
+     * groovy in other containers like games and application servers.
+     *
+     * @param roots This an array of URLs where Groovy scripts will be stored. They should
+     *              be laid out using their package structure like Java classes
+     */
+    private GroovyScriptEngine(URL[] roots, ClassLoader parent, ResourceConnector rc) {
+        if (roots == null) roots = EMPTY_URL_ARRAY;
+        this.roots = roots;
+        if (rc == null) rc = this;
+        this.rc = rc;
+        if (parent == CL_STUB) parent = this.getClass().getClassLoader();
+        this.parentLoader = parent;
+        this.groovyLoader = initGroovyLoader();
+    }
+
+    public GroovyScriptEngine(URL[] roots) {
+        this(roots, CL_STUB, null);
+    }
+
+    public GroovyScriptEngine(URL[] roots, ClassLoader parentClassLoader) {
+        this(roots, parentClassLoader, null);
+    }
+
+    public GroovyScriptEngine(String[] urls) throws IOException {
+        this(createRoots(urls), CL_STUB, null);
+    }
+
+    private static URL[] createRoots(String[] urls) throws MalformedURLException {
+        if (urls == null) return null;
+        URL[] roots = new URL[urls.length];
+        for (int i = 0; i < roots.length; i++) {
+            if (urls[i].contains("://")) {
+                roots[i] = new URL(urls[i]);
+            } else {
+                roots[i] = new File(urls[i]).toURI().toURL();
+            }
+        }
+        return roots;
+    }
+
+    public GroovyScriptEngine(String[] urls, ClassLoader parentClassLoader) throws IOException {
+        this(createRoots(urls), parentClassLoader, null);
+    }
+
+    public GroovyScriptEngine(String url) throws IOException {
+        this(new String[]{url});
+    }
+
+    public GroovyScriptEngine(String url, ClassLoader parentClassLoader) throws IOException {
+        this(new String[]{url}, parentClassLoader);
+    }
+
+    public GroovyScriptEngine(ResourceConnector rc) {
+        this(null, CL_STUB, rc);
+    }
+
+    public GroovyScriptEngine(ResourceConnector rc, ClassLoader parentClassLoader) {
+        this(null, parentClassLoader, rc);
+    }
+
+    /**
+     * Get the <code>ClassLoader</code> that will serve as the parent ClassLoader of the
+     * {@link GroovyClassLoader} in which scripts will be executed. By default, this is the
+     * ClassLoader that loaded the <code>GroovyScriptEngine</code> class.
+     *
+     * @return the parent classloader used to load scripts
+     */
+    public ClassLoader getParentClassLoader() {
+        return parentLoader;
+    }
+
+    /**
+     * Get the class of the scriptName in question, so that you can instantiate
+     * Groovy objects with caching and reloading.
+     *
+     * @param scriptName resource name pointing to the script
+     * @return the loaded scriptName as a compiled class
+     * @throws ResourceException if there is a problem accessing the script
+     * @throws ScriptException   if there is a problem parsing the script
+     */
+    public Class loadScriptByName(String scriptName) throws ResourceException, ScriptException {
+        URLConnection conn = rc.getResourceConnection(scriptName);
+        String path = conn.getURL().toExternalForm();
+        ScriptCacheEntry entry = scriptCache.get(path);
+        Class clazz = null;
+        if (entry != null) clazz = entry.scriptClass;
+        try {
+            if (isSourceNewer(entry)) {
+                try {
+                    String encoding = conn.getContentEncoding() != null ? conn.getContentEncoding() : config.getSourceEncoding();
+                    String content = IOGroovyMethods.getText(conn.getInputStream(), encoding);
+                    clazz = groovyLoader.parseClass(content, path);
+                } catch (IOException e) {
+                    throw new ResourceException(e);
+                }
+            }
+        } finally {
+            forceClose(conn);
+        }
+        return clazz;
+    }
+
+    /**
+     * Run a script identified by name with a single argument.
+     *
+     * @param scriptName name of the script to run
+     * @param argument   a single argument passed as a variable named <code>arg</code> in the binding
+     * @return a <code>toString()</code> representation of the result of the execution of the script
+     * @throws ResourceException if there is a problem accessing the script
+     * @throws ScriptException   if there is a problem parsing the script
+     */
+    public String run(String scriptName, String argument) throws ResourceException, ScriptException {
+        Binding binding = new Binding();
+        binding.setVariable("arg", argument);
+        Object result = run(scriptName, binding);
+        return result == null ? "" : result.toString();
+    }
+
+    /**
+     * Run a script identified by name with a given binding.
+     *
+     * @param scriptName name of the script to run
+     * @param binding    the binding to pass to the script
+     * @return an object
+     * @throws ResourceException if there is a problem accessing the script
+     * @throws ScriptException   if there is a problem parsing the script
+     */
+    public Object run(String scriptName, Binding binding) throws ResourceException, ScriptException {
+        return createScript(scriptName, binding).run();
+    }
+
+    /**
+     * Creates a Script with a given scriptName and binding.
+     *
+     * @param scriptName name of the script to run
+     * @param binding    the binding to pass to the script
+     * @return the script object
+     * @throws ResourceException if there is a problem accessing the script
+     * @throws ScriptException   if there is a problem parsing the script
+     */
+    public Script createScript(String scriptName, Binding binding) throws ResourceException, ScriptException {
+        return InvokerHelper.createScript(loadScriptByName(scriptName), binding);
+    }
+
+    private long getLastModified(String scriptName) throws ResourceException {
+        URLConnection conn = rc.getResourceConnection(scriptName);
+        long lastMod = 0;
+        try {
+            lastMod = conn.getLastModified();
+        } finally {
+            // getResourceConnection() opening the inputstream, let's ensure all streams are closed
+            forceClose(conn);
+        }
+        return lastMod;
+    }
+
+    protected boolean isSourceNewer(ScriptCacheEntry entry) throws ResourceException {
+        if (entry == null) return true;
+
+        long mainEntryLastCheck = entry.lastCheck;
+        long now = 0;
+
+        boolean returnValue = false;
+        for (String scriptName : entry.dependencies) {
+            ScriptCacheEntry depEntry = scriptCache.get(scriptName);
+            if (depEntry.sourceNewer) return true;
+
+            // check if maybe dependency was recompiled, but this one here not
+            if (mainEntryLastCheck < depEntry.lastModified) {
+                returnValue = true;
+                continue;
+            }
+
+            if (now == 0) now = getCurrentTime();
+            long nextSourceCheck = depEntry.lastCheck + config.getMinimumRecompilationInterval();
+            if (nextSourceCheck > now) continue;
+
+            long lastMod = getLastModified(scriptName);
+            if (depEntry.lastModified < lastMod) {
+                depEntry = new ScriptCacheEntry(depEntry, lastMod, true);
+                scriptCache.put(scriptName, depEntry);
+                returnValue = true;
+            } else {
+                depEntry = new ScriptCacheEntry(depEntry, now, false);
+                scriptCache.put(scriptName, depEntry);
+            }
+        }
+
+        return returnValue;
+    }
+
+    /**
+     * Returns the GroovyClassLoader associated with this script engine instance.
+     * Useful if you need to pass the class loader to another library.
+     *
+     * @return the GroovyClassLoader
+     */
+    public GroovyClassLoader getGroovyClassLoader() {
+        return groovyLoader;
+    }
+
+    /**
+     * @return a non null compiler configuration
+     */
+    public CompilerConfiguration getConfig() {
+        return config;
+    }
+
+    /**
+     * sets a compiler configuration
+     *
+     * @param config - the compiler configuration
+     * @throws NullPointerException if config is null
+     */
+    public void setConfig(CompilerConfiguration config) {
+        if (config == null) throw new NullPointerException("configuration cannot be null");
+        this.config = config;
+        this.groovyLoader = initGroovyLoader();
+    }
+
+    protected long getCurrentTime() {
+        return System.currentTimeMillis();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/IFileNameFinder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/IFileNameFinder.java b/src/main/groovy/groovy/util/IFileNameFinder.java
new file mode 100644
index 0000000..35e9012
--- /dev/null
+++ b/src/main/groovy/groovy/util/IFileNameFinder.java
@@ -0,0 +1,26 @@
+/*
+ *  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 groovy.util;
+
+import java.util.List;
+
+public interface IFileNameFinder {
+    List<String> getFileNames(String basedir, String pattern);
+    List<String> getFileNames(String basedir, String pattern, String excludesPattern);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/IndentPrinter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/IndentPrinter.java b/src/main/groovy/groovy/util/IndentPrinter.java
new file mode 100644
index 0000000..df3d8c2
--- /dev/null
+++ b/src/main/groovy/groovy/util/IndentPrinter.java
@@ -0,0 +1,234 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.GroovyRuntimeException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * A helper class for printing indented text. This can be used stand-alone or, more commonly, from Builders.
+ * <p>
+ * By default, a PrintWriter to System.out is used as the Writer, but it is possible
+ * to change the Writer by passing a new one as a constructor argument.
+ * <p>
+ * Indention by default is 2 characters but can be changed by passing a
+ * different value as a constructor argument.
+ * <p>
+ * The following is an example usage. Note that within a "with" block you need to
+ * specify a parameter name so that this.println is not called instead of IndentPrinter.println:
+ * <pre>
+ * new IndentPrinter(new PrintWriter(out)).with { p ->
+ *     p.printIndent()
+ *     p.println('parent1')
+ *     p.incrementIndent()
+ *     p.printIndent()
+ *     p.println('child 1')
+ *     p.printIndent()
+ *     p.println('child 2')
+ *     p.decrementIndent()
+ *     p.printIndent()
+ *     p.println('parent2')
+ *     p.flush()
+ * }
+ * </pre>
+ * The above example prints this to standard output:
+ * <pre>
+ * parent1
+ *   child 1
+ *   child 2
+ * parent2
+ * </pre>
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class IndentPrinter {
+
+    private int indentLevel;
+    private final String indent;
+    private final Writer out;
+    private final boolean addNewlines;
+    private boolean autoIndent;
+
+    /**
+     * Creates an IndentPrinter backed by a PrintWriter pointing to System.out, with an indent of two spaces.
+     *
+     * @see #IndentPrinter(Writer, String)
+     */
+    public IndentPrinter() {
+        this(new PrintWriter(System.out), "  ");
+    }
+
+    /**
+     * Creates an IndentPrinter backed by the supplied Writer, with an indent of two spaces.
+     *
+     * @param out Writer to output to
+     * @see #IndentPrinter(Writer, String)
+     */
+    public IndentPrinter(Writer out) {
+        this(out, "  ");
+    }
+
+    /**
+     * Creates an IndentPrinter backed by the supplied Writer,
+     * with a user-supplied String to be used for indenting.
+     *
+     * @param out Writer to output to
+     * @param indent character(s) used to indent each line
+     */
+    public IndentPrinter(Writer out, String indent) {
+        this(out, indent, true);
+    }
+
+    /**
+     * Creates an IndentPrinter backed by the supplied Writer,
+     * with a user-supplied String to be used for indenting
+     * and the ability to override newline handling.
+     *
+     * @param out Writer to output to
+     * @param indent character(s) used to indent each line
+     * @param addNewlines set to false to gobble all new lines (default true)
+     */
+    public IndentPrinter(Writer out, String indent, boolean addNewlines) {
+       this(out, indent, addNewlines, false);
+    }
+
+    /**
+     * Create an IndentPrinter to the given PrintWriter
+     * @param out Writer to output to
+     * @param indent character(s) used to indent each line
+     * @param addNewlines set to false to gobble all new lines (default true)
+     * @param autoIndent set to true to make println() prepend the indent automatically (default false)
+     */
+    public IndentPrinter(Writer out, String indent, boolean addNewlines, boolean autoIndent) {
+        this.addNewlines = addNewlines;
+        if (out == null) {
+            throw new IllegalArgumentException("Must specify a Writer");
+        }
+        this.out = out;
+        this.indent = indent;
+        this.autoIndent = autoIndent;
+    }
+
+    /**
+     * Prints a string followed by an end of line character.
+     *
+     * @param  text String to be written
+     */
+    public void println(String text) {
+        try {
+            if(autoIndent) printIndent();
+            out.write(text);
+            println();
+        } catch(IOException ioe) {
+            throw new GroovyRuntimeException(ioe);
+        }
+    }
+
+    /**
+     * Prints a string.
+     *
+     * @param  text String to be written
+     */
+    public void print(String text) {
+        try {
+            out.write(text);
+        } catch(IOException ioe) {
+            throw new GroovyRuntimeException(ioe);
+        }
+    }
+
+    /**
+     * Prints a character.
+     *
+     * @param  c char to be written
+     */
+    public void print(char c) {
+        try {
+            out.write(c);
+        } catch(IOException ioe) {
+            throw new GroovyRuntimeException(ioe);
+        }
+    }
+
+    /**
+     * Prints the current indent level.
+     */
+    public void printIndent() {
+        for (int i = 0; i < indentLevel; i++) {
+            try {
+                out.write(indent);
+            } catch(IOException ioe) {
+                throw new GroovyRuntimeException(ioe);
+            }
+        }
+    }
+
+    /**
+     * Prints an end-of-line character (if enabled via addNewLines property).
+     * Defaults to outputting a single '\n' character but by using a custom
+     * Writer, e.g. PlatformLineWriter, you can get platform-specific
+     * end-of-line characters.
+     *
+     * @see #IndentPrinter(Writer, String, boolean)
+     */
+    public void println() {
+        if (addNewlines) {
+            try {
+                out.write("\n");
+            } catch(IOException ioe) {
+                throw new GroovyRuntimeException(ioe);
+            }
+        }
+    }
+
+    public void incrementIndent() {
+        ++indentLevel;
+    }
+
+    public void decrementIndent() {
+        --indentLevel;
+    }
+
+    public int getIndentLevel() {
+        return indentLevel;
+    }
+
+    public void setIndentLevel(int indentLevel) {
+        this.indentLevel = indentLevel;
+    }
+
+    public boolean getAutoIndent(){
+        return this.autoIndent;
+    }
+
+    public void setAutoIndent(boolean autoIndent){
+        this.autoIndent = autoIndent;
+    }
+
+    public void flush() {
+        try {
+            out.flush();
+        } catch(IOException ioe) {
+            throw new GroovyRuntimeException(ioe);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/MapEntry.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/MapEntry.java b/src/main/groovy/groovy/util/MapEntry.java
new file mode 100644
index 0000000..9190fcd
--- /dev/null
+++ b/src/main/groovy/groovy/util/MapEntry.java
@@ -0,0 +1,83 @@
+/*
+ *  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 groovy.util;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.Map;
+
+/**
+ * A Map.Entry implementation.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class MapEntry implements Map.Entry {
+
+    private Object key;
+    private Object value;
+
+    public MapEntry(Object key, Object value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public boolean equals(Object that) {
+        if (that instanceof MapEntry) {
+            return equals((MapEntry) that);
+        }
+        return false;
+    }
+
+    public boolean equals(MapEntry that) {
+        return DefaultTypeTransformation.compareEqual(this.key, that.key) && DefaultTypeTransformation.compareEqual(this.value, that.value);
+    }
+
+    public int hashCode() {
+        return hash(key) ^ hash(value);
+    }
+
+    public String toString() {
+        return "" + key + ":" + value;
+    }
+
+    public Object getKey() {
+        return key;
+    }
+
+    public void setKey(Object key) {
+        this.key = key;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public Object setValue(Object value) {
+        this.value = value;
+        return value;
+    }
+
+    /**
+     * Helper method to handle object hashes for possibly null values
+     */
+    protected int hash(Object object) {
+        return (object == null) ? 0xbabe : object.hashCode();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/Node.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/Node.java b/src/main/groovy/groovy/util/Node.java
new file mode 100644
index 0000000..e40b14a
--- /dev/null
+++ b/src/main/groovy/groovy/util/Node.java
@@ -0,0 +1,787 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.DelegatingMetaClass;
+import groovy.lang.GroovySystem;
+import groovy.lang.MetaClass;
+import groovy.lang.Tuple2;
+import groovy.xml.QName;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.util.ListHashMap;
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * Represents an arbitrary tree node which can be used for structured metadata or any arbitrary XML-like tree.
+ * A node can have a name, a value and an optional Map of attributes.
+ * Typically the name is a String and a value is either a String or a List of other Nodes,
+ * though the types are extensible to provide a flexible structure, e.g. you could use a
+ * QName as the name which includes a namespace URI and a local name. Or a JMX ObjectName etc.
+ * So this class can represent metadata like <code>{foo a=1 b="abc"}</code> or nested
+ * metadata like <code>{foo a=1 b="123" { bar x=12 text="hello" }}</code>
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Paul King
+ */
+public class Node implements Serializable, Cloneable {
+
+    static {
+        // wrap the standard MetaClass with the delegate
+        setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(Node.class), Node.class);
+    }
+
+    private static final long serialVersionUID = 4121134753270542643L;
+
+    private Node parent;
+
+    private final Object name;
+
+    private final Map attributes;
+
+    private Object value;
+
+    /**
+     * Creates a new Node with the same name, no parent, shallow cloned attributes
+     * and if the value is a NodeList, a (deep) clone of those nodes.
+     *
+     * @return the clone
+     */
+    @Override
+    public Object clone() {
+        Object newValue = value;
+        if (value != null && value instanceof NodeList) {
+            NodeList nodes = (NodeList) value;
+            newValue = nodes.clone();
+        }
+        return new Node(null, name, new HashMap(attributes), newValue);
+    }
+
+    /**
+     * Creates a new Node named <code>name</code> and if a parent is supplied, adds
+     * the newly created node as a child of the parent.
+     *
+     * @param parent the parent node or null if no parent
+     * @param name   the name of the node
+     */
+    public Node(Node parent, Object name) {
+        this(parent, name, new NodeList());
+    }
+
+    /**
+     * Creates a new Node named <code>name</code> with value <code>value</code> and
+     * if a parent is supplied, adds the newly created node as a child of the parent.
+     *
+     * @param parent the parent node or null if no parent
+     * @param name   the name of the node
+     * @param value  the Node value, e.g. some text but in general any Object
+     */
+    public Node(Node parent, Object name, Object value) {
+        this(parent, name, new HashMap(), value);
+    }
+
+    /**
+     * Creates a new Node named <code>name</code> with
+     * attributes specified in the <code>attributes</code> Map. If a parent is supplied,
+     * the newly created node is added as a child of the parent.
+     *
+     * @param parent     the parent node or null if no parent
+     * @param name       the name of the node
+     * @param attributes a Map of name-value pairs
+     */
+    public Node(Node parent, Object name, Map attributes) {
+        this(parent, name, attributes, new NodeList());
+    }
+
+    /**
+     * Creates a new Node named <code>name</code> with value <code>value</code> and
+     * with attributes specified in the <code>attributes</code> Map. If a parent is supplied,
+     * the newly created node is added as a child of the parent.
+     *
+     * @param parent     the parent node or null if no parent
+     * @param name       the name of the node
+     * @param attributes a Map of name-value pairs
+     * @param value      the Node value, e.g. some text but in general any Object
+     */
+    public Node(Node parent, Object name, Map attributes, Object value) {
+        this.parent = parent;
+        this.name = name;
+        this.attributes = attributes;
+        this.value = value;
+
+        if (parent != null) {
+            getParentList(parent).add(this);
+        }
+    }
+
+    private static List getParentList(Node parent) {
+        Object parentValue = parent.value();
+        List parentList;
+        if (parentValue instanceof List) {
+            parentList = (List) parentValue;
+        } else {
+            parentList = new NodeList();
+            parentList.add(parentValue);
+            parent.setValue(parentList);
+        }
+        return parentList;
+    }
+
+    /**
+     * Appends a child to the current node.
+     *
+     * @param child the child to append
+     * @return <code>true</code>
+     */
+    public boolean append(Node child) {
+        child.setParent(this);
+        return getParentList(this).add(child);
+    }
+
+    /**
+     * Removes a child of the current node.
+     *
+     * @param child the child to remove
+     * @return <code>true</code> if the param was a child of the current node
+     */
+    public boolean remove(Node child) {
+        child.setParent(null);
+        return getParentList(this).remove(child);
+    }
+
+    /**
+     * Creates a new node as a child of the current node.
+     *
+     * @param name the name of the new node
+     * @param attributes the attributes of the new node
+     * @return the newly created <code>Node</code>
+     */
+    public Node appendNode(Object name, Map attributes) {
+        return new Node(this, name, attributes);
+    }
+
+    /**
+     * Creates a new node as a child of the current node.
+     *
+     * @param name the name of the new node
+     * @return the newly created <code>Node</code>
+     */
+    public Node appendNode(Object name) {
+        return new Node(this, name);
+    }
+
+    /**
+     * Creates a new node as a child of the current node.
+     *
+     * @param name the name of the new node
+     * @param value the value of the new node
+     * @return the newly created <code>Node</code>
+     */
+    public Node appendNode(Object name, Object value) {
+        return new Node(this, name, value);
+    }
+
+    /**
+     * Creates a new node as a child of the current node.
+     *
+     * @param name the name of the new node
+     * @param attributes the attributes of the new node
+     * @param value the value of the new node
+     * @return the newly created <code>Node</code>
+     */
+    public Node appendNode(Object name, Map attributes, Object value) {
+        return new Node(this, name, attributes, value);
+    }
+
+    /**
+     * Replaces the current node with nodes defined using builder-style notation via a Closure.
+     *
+     * @param c A Closure defining the new nodes using builder-style notation.
+     * @return the original now replaced node
+     */
+    public Node replaceNode(Closure c) {
+        if (parent() == null) {
+            throw new UnsupportedOperationException("Replacing the root node is not supported");
+        }
+        appendNodes(c);
+        getParentList(parent()).remove(this);
+        this.setParent(null);
+        return this;
+    }
+
+    /**
+     * Replaces the current node with the supplied node.
+     *
+     * @param n the new Node
+     * @return the original now replaced node
+     */
+    public Node replaceNode(Node n) {
+        if (parent() == null) {
+            throw new UnsupportedOperationException("Replacing the root node is not supported");
+        }
+        List tail = getTail();
+        parent().appendNode(n.name(), n.attributes(), n.value());
+        parent().children().addAll(tail);
+        getParentList(parent()).remove(this);
+        this.setParent(null);
+        return this;
+    }
+
+    private List getTail() {
+        List list = parent().children();
+        int afterIndex = list.indexOf(this);
+        List tail = new ArrayList(list.subList(afterIndex + 1, list.size()));
+        list.subList(afterIndex + 1, list.size()).clear();
+        return tail;
+    }
+
+    /**
+     * Adds sibling nodes (defined using builder-style notation via a Closure) after the current node.
+     *
+     * @param c A Closure defining the new sibling nodes to add using builder-style notation.
+     */
+    public void plus(Closure c) {
+        if (parent() == null) {
+            throw new UnsupportedOperationException("Adding sibling nodes to the root node is not supported");
+        }
+        appendNodes(c);
+    }
+
+    private void appendNodes(Closure c) {
+        List tail = getTail();
+        for (Node child : buildChildrenFromClosure(c)) {
+            parent().appendNode(child.name(), child.attributes(), child.value());
+        }
+        parent().children().addAll(tail);
+    }
+
+    private static List<Node> buildChildrenFromClosure(Closure c) {
+        NodeBuilder b = new NodeBuilder();
+        Node newNode = (Node) b.invokeMethod("dummyNode", c);
+        return newNode.children();
+    }
+
+    /**
+     * Extension point for subclasses to override the metaclass. The default
+     * one supports the property and @ attribute notations.
+     *
+     * @param metaClass the original metaclass
+     * @param nodeClass the class whose metaclass we wish to override (this class or a subclass)
+     */
+    protected static void setMetaClass(final MetaClass metaClass, Class nodeClass) {
+        // TODO Is protected static a bit of a smell?
+        // TODO perhaps set nodeClass to be Class<? extends Node>
+        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
+            @Override
+            public Object getAttribute(final Object object, final String attribute) {
+                Node n = (Node) object;
+                return n.get("@" + attribute);
+            }
+
+            @Override
+            public void setAttribute(final Object object, final String attribute, final Object newValue) {
+                Node n = (Node) object;
+                n.attributes().put(attribute, newValue);
+            }
+
+            @Override
+            public Object getProperty(Object object, String property) {
+                if (object instanceof Node) {
+                    Node n = (Node) object;
+                    return n.get(property);
+                }
+                return super.getProperty(object, property);
+            }
+
+            @Override
+            public void setProperty(Object object, String property, Object newValue) {
+                if (property.startsWith("@")) {
+                    setAttribute(object, property.substring(1), newValue);
+                    return;
+                }
+                delegate.setProperty(object, property, newValue);
+            }
+
+        };
+        GroovySystem.getMetaClassRegistry().setMetaClass(nodeClass, newMetaClass);
+    }
+
+    /**
+     * Returns the textual representation of the current node and all its child nodes.
+     *
+     * @return the text value of the node including child text
+     */
+    public String text() {
+        if (value instanceof String) {
+            return (String) value;
+        }
+        if (value instanceof NodeList) {
+            return ((NodeList) value).text();
+        }
+        if (value instanceof Collection) {
+            Collection coll = (Collection) value;
+            String previousText = null;
+            StringBuilder sb = null;
+            for (Object child : coll) {
+                String childText = null;
+                if (child instanceof String) {
+                    childText = (String) child;
+                } else if (child instanceof Node) {
+                    childText = ((Node) child).text();
+                }
+                if (childText != null) {
+                    if (previousText == null) {
+                        previousText = childText;
+                    } else {
+                        if (sb == null) {
+                            sb = new StringBuilder();
+                            sb.append(previousText);
+                        }
+                        sb.append(childText);
+                    }
+                }
+            }
+            if (sb != null) {
+                return sb.toString();
+            } else {
+                if (previousText != null) {
+                    return previousText;
+                }
+                return "";
+            }
+        }
+        return "" + value;
+    }
+
+    /**
+     * Returns an <code>Iterator</code> of the children of the node.
+     *
+     * @return the iterator of the nodes children
+     */
+    public Iterator iterator() {
+        return children().iterator();
+    }
+
+    /**
+     * Returns a <code>List</code> of the nodes children.
+     *
+     * @return the nodes children
+     */
+    public List children() {
+        if (value == null) {
+            return new NodeList();
+        }
+        if (value instanceof List) {
+            return (List) value;
+        }
+        // we're probably just a String
+        List result = new NodeList();
+        result.add(value);
+        return result;
+    }
+
+    /**
+     * Returns a <code>Map</code> of the attributes of the node or an empty <code>Map</code>
+     * if the node does not have any attributes.
+     *
+     * @return the attributes of the node
+     */
+    public Map attributes() {
+        return attributes;
+    }
+
+    /**
+     * Provides lookup of attributes by key.
+     *
+     * @param key the key of interest
+     * @return the attribute matching the key or <code>null</code> if no match exists
+     */
+    public Object attribute(Object key) {
+        return (attributes != null) ? attributes.get(key) : null;
+    }
+
+    /**
+     * Returns an <code>Object</code> representing the name of the node.
+     *
+     * @return the name or <code>null</code> if name is empty
+     */
+    public Object name() {
+        return name;
+    }
+
+    /**
+     * Returns an <code>Object</code> representing the value of the node.
+     *
+     * @return the value or <code>null</code> if value is empty
+     */
+    public Object value() {
+        return value;
+    }
+
+    /**
+     * Adds or replaces the value of the node.
+     *
+     * @param value the new value of the node
+     */
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the parent of the node.
+     *
+     * @return the parent or <code>null</code> for the root node
+     */
+    public Node parent() {
+        return parent;
+    }
+
+    /**
+     * Adds or replaces the parent of the node.
+     *
+     * @param parent the new parent of the node
+     */
+    protected void setParent(Node parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Provides lookup of elements by non-namespaced name
+     *
+     * @param key the name (or shortcut key) of the node(s) of interest
+     * @return the nodes which match key
+     */
+    public Object get(String key) {
+        if (key != null && key.charAt(0) == '@') {
+            String attributeName = key.substring(1);
+            return attributes().get(attributeName);
+        }
+        if ("..".equals(key)) {
+            return parent();
+        }
+        if ("*".equals(key)) {
+            return children();
+        }
+        if ("**".equals(key)) {
+            return depthFirst();
+        }
+        return getByName(key);
+    }
+
+    /**
+     * Provides lookup of elements by QName.
+     *
+     * @param name the QName of interest
+     * @return the nodes matching name
+     */
+    public NodeList getAt(QName name) {
+        NodeList answer = new NodeList();
+        for (Object child : children()) {
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                Object childNodeName = childNode.name();
+                if (name.matches(childNodeName)) {
+                    answer.add(childNode);
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Provides lookup of elements by name.
+     *
+     * @param name the name of interest
+     * @return the nodes matching name
+     */
+    private NodeList getByName(String name) {
+        NodeList answer = new NodeList();
+        for (Object child : children()) {
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                Object childNodeName = childNode.name();
+                if (childNodeName instanceof QName) {
+                    QName qn = (QName) childNodeName;
+                    if (qn.matches(name)) {
+                        answer.add(childNode);
+                    }
+                } else if (name.equals(childNodeName)) {
+                    answer.add(childNode);
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a depth-first preorder traversal.
+     *
+     * @return the list of (depth-first) ordered nodes
+     */
+    public List depthFirst() {
+        return depthFirst(true);
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a depth-first traversal.
+     *
+     * @param preorder if false, a postorder depth-first traversal will be performed
+     * @return the list of (depth-first) ordered nodes
+     * @since 2.5.0
+     */
+    public List depthFirst(boolean preorder) {
+        List answer = new NodeList();
+        if (preorder) answer.add(this);
+        answer.addAll(depthFirstRest(preorder));
+        if (!preorder) answer.add(this);
+        return answer;
+    }
+
+    private List depthFirstRest(boolean preorder) {
+        List answer = new NodeList();
+        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
+            Object child = iter.next();
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                List children = childNode.depthFirstRest(preorder);
+                if (preorder) answer.add(childNode);
+                if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) answer.addAll(children);
+                if (!preorder) answer.add(childNode);
+            } else if (child instanceof String) {
+                answer.add(child);
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a depth-first preorder traversal.
+     *
+     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
+     *          closure will be passed the node, for a two param closure the second parameter will be the level).
+     * @since 2.5.0
+     */
+    public void depthFirst(Closure c) {
+        Map<String, Object> options = new ListHashMap<String, Object>();
+        options.put("preorder", true);
+        depthFirst(options, c);
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a depth-first traversal.
+     * A boolean 'preorder' options is supported.
+     *
+     * @param options map containing options
+     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
+     *          closure will be passed the node, for a two param closure the second parameter will be the level).
+     * @since 2.5.0
+     */
+    public void depthFirst(Map<String, Object> options, Closure c) {
+        boolean preorder = Boolean.valueOf(options.get("preorder").toString());
+        if (preorder) callClosureForNode(c, this, 1);
+        depthFirstRest(preorder, 2, c);
+        if (!preorder) callClosureForNode(c, this, 1);
+    }
+
+    private static <T> T callClosureForNode(Closure<T> closure, Object node, int level) {
+        if (closure.getMaximumNumberOfParameters() == 2) {
+            return closure.call(new Object[]{node, level});
+        }
+        return closure.call(node);
+    }
+
+    private void depthFirstRest(boolean preorder, int level, Closure c) {
+        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
+            Object child = iter.next();
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                if (preorder) callClosureForNode(c, childNode, level);
+                childNode.depthFirstRest(preorder, level + 1, c);
+                if (!preorder) callClosureForNode(c, childNode, level);
+            }
+        }
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a breadth-first preorder traversal.
+     *
+     * @return the list of (breadth-first) ordered nodes
+     */
+    public List breadthFirst() {
+        return breadthFirst(true);
+    }
+
+    /**
+     * Provides a collection of all the nodes in the tree
+     * using a breadth-first traversal.
+     *
+     * @param preorder if false, a postorder breadth-first traversal will be performed
+     * @return the list of (breadth-first) ordered nodes
+     * @since 2.5.0
+     */
+    public List breadthFirst(boolean preorder) {
+        List answer = new NodeList();
+        if (preorder) answer.add(this);
+        answer.addAll(breadthFirstRest(preorder));
+        if (!preorder) answer.add(this);
+        return answer;
+    }
+
+    private List breadthFirstRest(boolean preorder) {
+        List answer = new NodeList();
+        Stack stack = new Stack();
+        List nextLevelChildren = preorder ? getDirectChildren() : DefaultGroovyMethods.reverse(getDirectChildren());
+        while (!nextLevelChildren.isEmpty()) {
+            List working = new NodeList(nextLevelChildren);
+            nextLevelChildren = new NodeList();
+            for (Object child : working) {
+                if (preorder) {
+                    answer.add(child);
+                } else {
+                    stack.push(child);
+                }
+                if (child instanceof Node) {
+                    Node childNode = (Node) child;
+                    List children = childNode.getDirectChildren();
+                    if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) nextLevelChildren.addAll(preorder ? children : DefaultGroovyMethods.reverse(children));
+                }
+            }
+        }
+        while (!stack.isEmpty()) {
+            answer.add(stack.pop());
+        }
+        return answer;
+    }
+
+    /**
+     * Calls the provided closure for all the nodes in the tree
+     * using a breadth-first preorder traversal.
+     *
+     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
+     *          closure will be passed the node, for a two param closure the second parameter will be the level).
+     * @since 2.5.0
+     */
+    public void breadthFirst(Closure c) {
+        Map<String, Object> options = new ListHashMap<String, Object>();
+        options.put("preorder", true);
+        breadthFirst(options, c);
+    }
+
+    /**
+     * Calls the provided closure for all the nodes in the tree
+     * using a breadth-first traversal.
+     * A boolean 'preorder' options is supported.
+     *
+     * @param options map containing options
+     * @param c the closure to run for each node (a one or two parameter can be used; if one parameter is given the
+     *          closure will be passed the node, for a two param closure the second parameter will be the level).
+     * @since 2.5.0
+     */
+    public void breadthFirst(Map<String, Object> options, Closure c) {
+        boolean preorder = Boolean.valueOf(options.get("preorder").toString());
+        if (preorder) callClosureForNode(c, this, 1);
+        breadthFirstRest(preorder, 2, c);
+        if (!preorder) callClosureForNode(c, this, 1);
+    }
+
+    private void breadthFirstRest(boolean preorder, int level, Closure c) {
+        Stack<Tuple2<Object, Integer>> stack = new Stack<Tuple2<Object, Integer>>();
+        List nextLevelChildren = preorder ? getDirectChildren() : DefaultGroovyMethods.reverse(getDirectChildren());
+        while (!nextLevelChildren.isEmpty()) {
+            List working = new NodeList(nextLevelChildren);
+            nextLevelChildren = new NodeList();
+            for (Object child : working) {
+                if (preorder) {
+                    callClosureForNode(c, child, level);
+                } else {
+                    stack.push(new Tuple2<Object, Integer>(child, level));
+                }
+                if (child instanceof Node) {
+                    Node childNode = (Node) child;
+                    List children = childNode.getDirectChildren();
+                    if (children.size() > 1 || (children.size() == 1 && !(children.get(0) instanceof String))) nextLevelChildren.addAll(preorder ? children : DefaultGroovyMethods.reverse(children));
+                }
+            }
+            level++;
+        }
+        while (!stack.isEmpty()) {
+            Tuple2<Object, Integer> next = stack.pop();
+            callClosureForNode(c, next.getFirst(), next.getSecond());
+        }
+    }
+
+    /**
+     * Returns the list of any direct String nodes of this node.
+     *
+     * @return the list of String values from this node
+     * @since 2.3.0
+     */
+    public List<String> localText() {
+        List<String> answer = new ArrayList<String>();
+        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
+            Object child = iter.next();
+            if (!(child instanceof Node)) {
+                answer.add(child.toString());
+            }
+        }
+        return answer;
+    }
+
+    private List getDirectChildren() {
+        List answer = new NodeList();
+        for (Iterator iter = InvokerHelper.asIterator(value); iter.hasNext(); ) {
+            Object child = iter.next();
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                answer.add(childNode);
+            } else if (child instanceof String) {
+                answer.add(child);
+            }
+        }
+        return answer;
+    }
+
+    public String toString() {
+        return name + "[attributes=" + attributes + "; value=" + value + "]";
+    }
+
+    /**
+     * Writes the node to the specified <code>PrintWriter</code>.
+     *
+     * @param out the writer receiving the output
+     */
+    public void print(PrintWriter out) {
+        new NodePrinter(out).print(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/NodeBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/NodeBuilder.java b/src/main/groovy/groovy/util/NodeBuilder.java
new file mode 100644
index 0000000..babe5c3
--- /dev/null
+++ b/src/main/groovy/groovy/util/NodeBuilder.java
@@ -0,0 +1,57 @@
+/*
+ *  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 groovy.util;
+
+import java.util.Map;
+
+/**
+ * A helper class for creating nested trees of Node objects for 
+ * handling arbitrary data
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class NodeBuilder extends BuilderSupport {
+
+    public static NodeBuilder newInstance() {
+        return new NodeBuilder();
+    }
+
+    protected void setParent(Object parent, Object child) {
+    }
+
+    protected Object createNode(Object name) {
+        return new Node(getCurrentNode(), name);
+    }
+
+    protected Object createNode(Object name, Object value) {
+        return new Node(getCurrentNode(), name, value);
+    }
+
+    protected Object createNode(Object name, Map attributes) {
+        return new Node(getCurrentNode(), name, attributes);
+    }
+
+    protected Object createNode(Object name, Map attributes, Object value) {
+        return new Node(getCurrentNode(), name, attributes, value);
+    }
+
+    protected Node getCurrentNode() {
+        return (Node) getCurrent();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/NodeList.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/NodeList.java b/src/main/groovy/groovy/util/NodeList.java
new file mode 100644
index 0000000..e54009c
--- /dev/null
+++ b/src/main/groovy/groovy/util/NodeList.java
@@ -0,0 +1,202 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.DelegatingMetaClass;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.GroovySystem;
+import groovy.lang.MetaClass;
+import groovy.xml.QName;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A List implementation which is returned by queries on a {@link Node}
+ * which provides some XPath like helper methods for GPath.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Paul King
+ */
+public class NodeList extends ArrayList {
+    static {
+        // wrap the standard MetaClass with the delegate
+        setMetaClass(NodeList.class, GroovySystem.getMetaClassRegistry().getMetaClass(NodeList.class));
+    }
+
+    public NodeList() {
+    }
+
+    public NodeList(Collection collection) {
+        super(collection);
+    }
+
+    public NodeList(int size) {
+        super(size);
+    }
+
+    /**
+     * Creates a new NodeList containing the same elements as the
+     * original (but cloned in the case of Nodes).
+     *
+     * @return the clone
+     */
+    @Override
+    public Object clone() {
+        NodeList result = new NodeList(size());
+        for (int i = 0; i < size(); i++) {
+            Object next = get(i);
+            if (next instanceof Node) {
+                Node n = (Node) next;
+                result.add(n.clone());
+            } else {
+                result.add(next);
+            }
+        }
+        return result;
+    }
+
+    protected static void setMetaClass(final Class nodelistClass, final MetaClass metaClass) {
+        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
+            @Override
+            public Object getAttribute(final Object object, final String attribute) {
+                NodeList nl = (NodeList) object;
+                Iterator it = nl.iterator();
+                List result = new ArrayList();
+                while (it.hasNext()) {
+                    Node node = (Node) it.next();
+                    result.add(node.attributes().get(attribute));
+                }
+                return result;
+            }
+
+            @Override
+            public void setAttribute(final Object object, final String attribute, final Object newValue) {
+                for (Object o : (NodeList) object) {
+                    Node node = (Node) o;
+                    node.attributes().put(attribute, newValue);
+                }
+            }
+
+            @Override
+            public Object getProperty(Object object, String property) {
+                if (object instanceof NodeList) {
+                    NodeList nl = (NodeList) object;
+                    return nl.getAt(property);
+                }
+                return super.getProperty(object, property);
+            }
+        };
+        GroovySystem.getMetaClassRegistry().setMetaClass(nodelistClass, newMetaClass);
+    }
+
+    /**
+     * Provides lookup of elements by non-namespaced name.
+     *
+     * @param name the name or shortcut key for nodes of interest
+     * @return the nodes of interest which match name
+     */
+    public NodeList getAt(String name) {
+        NodeList answer = new NodeList();
+        for (Object child : this) {
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                Object temp = childNode.get(name);
+                if (temp instanceof Collection) {
+                    answer.addAll((Collection) temp);
+                } else {
+                    answer.add(temp);
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Provides lookup of elements by QName.
+     *
+     * @param name the name or shortcut key for nodes of interest
+     * @return the nodes of interest which match name
+     */
+    public NodeList getAt(QName name) {
+        NodeList answer = new NodeList();
+        for (Object child : this) {
+            if (child instanceof Node) {
+                Node childNode = (Node) child;
+                NodeList temp = childNode.getAt(name);
+                answer.addAll(temp);
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Returns the text value of all of the elements in the collection.
+     *
+     * @return the text value of all the elements in the collection or null
+     */
+    public String text() {
+        String previousText = null;
+        StringBuilder buffer = null;
+        for (Object child : this) {
+            String text = null;
+            if (child instanceof String) {
+                text = (String) child;
+            } else if (child instanceof Node) {
+                text = ((Node) child).text();
+            }
+            if (text != null) {
+                if (previousText == null) {
+                    previousText = text;
+                } else {
+                    if (buffer == null) {
+                        buffer = new StringBuilder();
+                        buffer.append(previousText);
+                    }
+                    buffer.append(text);
+                }
+            }
+        }
+        if (buffer != null) {
+            return buffer.toString();
+        }
+        if (previousText != null) {
+            return previousText;
+        }
+        return "";
+    }
+
+    public Node replaceNode(Closure c) {
+        if (size() <= 0 || size() > 1) {
+            throw new GroovyRuntimeException(
+                    "replaceNode() can only be used to replace a single node, but was applied to " + size() + " nodes");
+        }
+        return ((Node)get(0)).replaceNode(c);
+    }
+
+    public void plus(Closure c) {
+        for (Object o : this) {
+            ((Node) o).plus(c);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/NodePrinter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/NodePrinter.java b/src/main/groovy/groovy/util/NodePrinter.java
new file mode 100644
index 0000000..ca93bc7
--- /dev/null
+++ b/src/main/groovy/groovy/util/NodePrinter.java
@@ -0,0 +1,130 @@
+/*
+ *  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 groovy.util;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A helper class for creating nested trees of data
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Christian Stein
+ */
+public class NodePrinter {
+
+    protected final IndentPrinter out;
+
+    public NodePrinter() {
+        this(new IndentPrinter(new PrintWriter(new OutputStreamWriter(System.out))));
+    }
+
+    public NodePrinter(PrintWriter out) {
+        this(new IndentPrinter(out));
+    }
+
+    public NodePrinter(IndentPrinter out) {
+        if (out == null) {
+            throw new NullPointerException("IndentPrinter 'out' must not be null!");
+        }
+        this.out = out;
+    }
+
+    public void print(Node node) {
+        out.printIndent();
+        printName(node);
+        Map attributes = node.attributes();
+        boolean hasAttributes = attributes != null && !attributes.isEmpty();
+        if (hasAttributes) {
+            printAttributes(attributes);
+        }
+        Object value = node.value();
+        if (value instanceof List) {
+            if (!hasAttributes) {
+                out.print("()");
+            }
+            printList((List) value);
+        } else {
+            if (value instanceof String) {
+                out.print("('");
+                out.print((String) value);
+                out.println("')");
+            } else {
+                out.println("()");
+            }
+        }
+        out.flush();
+    }
+
+    protected void printName(Node node) {
+        Object name = node.name();
+        if (name != null) {
+            out.print(name.toString());
+        } else {
+            out.print("null");
+        }
+    }
+
+    protected void printList(List list) {
+        if (list.isEmpty()) {
+            out.println("");
+        } else {
+            out.println(" {");
+            out.incrementIndent();
+            for (Object value : list) {
+                if (value instanceof Node) {
+                    print((Node) value);
+                } else {
+                    out.printIndent();
+                    out.println(InvokerHelper.toString(value));
+                }
+            }
+            out.decrementIndent();
+            out.printIndent();
+            out.println("}");
+        }
+    }
+
+
+    protected void printAttributes(Map attributes) {
+        out.print("(");
+        boolean first = true;
+        for (Object o : attributes.entrySet()) {
+            Map.Entry entry = (Map.Entry) o;
+            if (first) {
+                first = false;
+            } else {
+                out.print(", ");
+            }
+            out.print(entry.getKey().toString());
+            out.print(":");
+            if (entry.getValue() instanceof String) {
+                out.print("'" + entry.getValue() + "'");
+            } else {
+                out.print(InvokerHelper.toString(entry.getValue()));
+            }
+        }
+        out.print(")");
+    }
+
+}


[43/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/grape/GrabAnnotationTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/grape/GrabAnnotationTransformation.java b/src/main/groovy/grape/GrabAnnotationTransformation.java
deleted file mode 100644
index dd55ff9..0000000
--- a/src/main/groovy/grape/GrabAnnotationTransformation.java
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- *  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 groovy.grape;
-
-import groovy.lang.Grab;
-import groovy.lang.GrabConfig;
-import groovy.lang.GrabExclude;
-import groovy.lang.GrabResolver;
-import groovy.lang.Grapes;
-import groovy.transform.CompilationUnitAware;
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ImportNode;
-import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.ListExpression;
-import org.codehaus.groovy.ast.expr.MapExpression;
-import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.io.StringReaderSource;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.tools.GrapeUtil;
-import org.codehaus.groovy.transform.ASTTransformation;
-import org.codehaus.groovy.transform.ASTTransformationVisitor;
-import org.codehaus.groovy.transform.AbstractASTTransformation;
-import org.codehaus.groovy.transform.GroovyASTTransformation;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.eqX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
-import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
-
-/**
- * Transformation for declarative dependency management.
- */
-@GroovyASTTransformation(phase=CompilePhase.CONVERSION)
-public class GrabAnnotationTransformation extends ClassCodeVisitorSupport implements ASTTransformation, CompilationUnitAware {
-    private static final String GRAB_CLASS_NAME = Grab.class.getName();
-    private static final String GRAB_DOT_NAME = GRAB_CLASS_NAME.substring(GRAB_CLASS_NAME.lastIndexOf("."));
-    private static final String GRAB_SHORT_NAME = GRAB_DOT_NAME.substring(1);
-
-    private static final String GRABEXCLUDE_CLASS_NAME = GrabExclude.class.getName();
-    private static final String GRABEXCLUDE_DOT_NAME = dotName(GRABEXCLUDE_CLASS_NAME);
-    private static final String GRABEXCLUDE_SHORT_NAME = shortName(GRABEXCLUDE_DOT_NAME);
-
-    private static final String GRABCONFIG_CLASS_NAME = GrabConfig.class.getName();
-    private static final String GRABCONFIG_DOT_NAME = dotName(GRABCONFIG_CLASS_NAME);
-    private static final String GRABCONFIG_SHORT_NAME = shortName(GRABCONFIG_DOT_NAME);
-
-    private static final String GRAPES_CLASS_NAME = Grapes.class.getName();
-    private static final String GRAPES_DOT_NAME = dotName(GRAPES_CLASS_NAME);
-    private static final String GRAPES_SHORT_NAME = shortName(GRAPES_DOT_NAME);
-
-    private static final String GRABRESOLVER_CLASS_NAME = GrabResolver.class.getName();
-    private static final String GRABRESOLVER_DOT_NAME = dotName(GRABRESOLVER_CLASS_NAME);
-    private static final String GRABRESOLVER_SHORT_NAME = shortName(GRABRESOLVER_DOT_NAME);
-
-    private static final ClassNode THREAD_CLASSNODE = ClassHelper.make(Thread.class);
-    private static final ClassNode SYSTEM_CLASSNODE = ClassHelper.make(System.class);
-
-    private static final List<String> GRABEXCLUDE_REQUIRED = Arrays.asList("group", "module");
-    private static final List<String> GRABRESOLVER_REQUIRED = Arrays.asList("name", "root");
-    private static final List<String> GRAB_REQUIRED = Arrays.asList("group", "module", "version");
-    private static final List<String> GRAB_OPTIONAL = Arrays.asList("classifier", "transitive", "conf", "ext", "type", "changing", "force", "initClass");
-    private static final List<String> GRAB_BOOLEAN = Arrays.asList("transitive", "changing", "force", "initClass");
-    private static final Collection<String> GRAB_ALL = DefaultGroovyMethods.plus(GRAB_REQUIRED, GRAB_OPTIONAL);
-    private static final Pattern IVY_PATTERN = Pattern.compile("([a-zA-Z0-9-/._+=]+)#([a-zA-Z0-9-/._+=]+)(;([a-zA-Z0-9-/.\\(\\)\\[\\]\\{\\}_+=,:@][a-zA-Z0-9-/.\\(\\)\\]\\{\\}_+=,:@]*))?(\\[([a-zA-Z0-9-/._+=,]*)\\])?");
-    private static final Pattern ATTRIBUTES_PATTERN = Pattern.compile("(.*;|^)([a-zA-Z0-9]+)=([a-zA-Z0-9.*\\[\\]\\-\\(\\),]*)$");
-
-    private static final String AUTO_DOWNLOAD_SETTING = Grape.AUTO_DOWNLOAD_SETTING;
-    private static final String DISABLE_CHECKSUMS_SETTING = Grape.DISABLE_CHECKSUMS_SETTING;
-    private static final String SYSTEM_PROPERTIES_SETTING = Grape.SYSTEM_PROPERTIES_SETTING;
-
-    private static String dotName(String className) {
-        return className.substring(className.lastIndexOf("."));
-    }
-
-    private static String shortName(String className) {
-        return className.substring(1);
-    }
-
-    boolean allowShortGrab;
-    Set<String> grabAliases;
-    List<AnnotationNode> grabAnnotations;
-
-    boolean allowShortGrabExcludes;
-    Set<String> grabExcludeAliases;
-    List<AnnotationNode> grabExcludeAnnotations;
-
-    boolean allowShortGrabConfig;
-    Set<String> grabConfigAliases;
-    List<AnnotationNode> grabConfigAnnotations;
-
-    boolean allowShortGrapes;
-    Set<String> grapesAliases;
-    List<AnnotationNode> grapesAnnotations;
-
-    boolean allowShortGrabResolver;
-    Set<String> grabResolverAliases;
-    List<AnnotationNode> grabResolverAnnotations;
-
-    CompilationUnit compilationUnit;
-    SourceUnit sourceUnit;
-    ClassLoader loader;
-    boolean initContextClassLoader;
-    Boolean autoDownload;
-    Boolean disableChecksums;
-    Map<String, String> systemProperties;
-
-    public SourceUnit getSourceUnit() {
-        return sourceUnit;
-    }
-
-    public void setCompilationUnit(final CompilationUnit compilationUnit) {
-        this.compilationUnit = compilationUnit;
-    }
-
-    public void visit(ASTNode[] nodes, SourceUnit source) {
-        sourceUnit = source;
-        loader = null;
-        initContextClassLoader = false;
-
-        ModuleNode mn = (ModuleNode) nodes[0];
-
-        allowShortGrab = true;
-        allowShortGrabExcludes = true;
-        allowShortGrabConfig = true;
-        allowShortGrapes = true;
-        allowShortGrabResolver = true;
-        grabAliases = new HashSet<String>();
-        grabExcludeAliases = new HashSet<String>();
-        grabConfigAliases = new HashSet<String>();
-        grapesAliases = new HashSet<String>();
-        grabResolverAliases = new HashSet<String>();
-        for (ImportNode im : mn.getImports()) {
-            String alias = im.getAlias();
-            String className = im.getClassName();
-            if ((className.endsWith(GRAB_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
-                || (GRAB_CLASS_NAME.equals(alias)))
-            {
-                allowShortGrab = false;
-            } else if (GRAB_CLASS_NAME.equals(className)) {
-                grabAliases.add(im.getAlias());
-            }
-            if ((className.endsWith(GRAPES_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
-                || (GRAPES_CLASS_NAME.equals(alias)))
-            {
-                allowShortGrapes = false;
-            } else if (GRAPES_CLASS_NAME.equals(className)) {
-                grapesAliases.add(im.getAlias());
-            }
-            if ((className.endsWith(GRABRESOLVER_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
-                || (GRABRESOLVER_CLASS_NAME.equals(alias)))
-            {
-                allowShortGrabResolver = false;
-            } else if (GRABRESOLVER_CLASS_NAME.equals(className)) {
-                grabResolverAliases.add(im.getAlias());
-            }
-        }
-
-        List<Map<String,Object>> grabMaps = new ArrayList<Map<String,Object>>();
-        List<Map<String,Object>> grabMapsInit = new ArrayList<Map<String,Object>>();
-        List<Map<String,Object>> grabExcludeMaps = new ArrayList<Map<String,Object>>();
-
-        for (ClassNode classNode : sourceUnit.getAST().getClasses()) {
-            grabAnnotations = new ArrayList<AnnotationNode>();
-            grabExcludeAnnotations = new ArrayList<AnnotationNode>();
-            grabConfigAnnotations = new ArrayList<AnnotationNode>();
-            grapesAnnotations = new ArrayList<AnnotationNode>();
-            grabResolverAnnotations = new ArrayList<AnnotationNode>();
-
-            visitClass(classNode);
-
-            ClassNode grapeClassNode = ClassHelper.make(Grape.class);
-
-            List<Statement> grabResolverInitializers = new ArrayList<Statement>();
-
-            if (!grapesAnnotations.isEmpty()) {
-                for (AnnotationNode node : grapesAnnotations) {
-                    Expression init = node.getMember("initClass");
-                    Expression value = node.getMember("value");
-                    if (value instanceof ListExpression) {
-                        for (Object o : ((ListExpression)value).getExpressions()) {
-                            if (o instanceof ConstantExpression) {
-                                extractGrab(init, (ConstantExpression) o);
-                            }
-                        }
-                    } else if (value instanceof ConstantExpression) {
-                        extractGrab(init, (ConstantExpression) value);
-                    }
-                    // don't worry if it's not a ListExpression, or AnnotationConstant, etc.
-                    // the rest of GroovyC will flag it as a syntax error later, so we don't
-                    // need to raise the error ourselves
-                }
-            }
-
-            if (!grabResolverAnnotations.isEmpty()) {
-                grabResolverAnnotationLoop:
-                for (AnnotationNode node : grabResolverAnnotations) {
-                    Map<String, Object> grabResolverMap = new HashMap<String, Object>();
-                    String sval = getMemberStringValue(node, "value");
-                    if (sval != null && sval.length() > 0) {
-                        for (String s : GRABRESOLVER_REQUIRED) {
-                            String mval = getMemberStringValue(node, s);
-                            if (mval != null && mval.isEmpty()) mval = null;
-                            if (mval != null) {
-                                addError("The attribute \"" + s + "\" conflicts with attribute 'value' in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                                continue grabResolverAnnotationLoop;
-                            }
-                        }
-                        grabResolverMap.put("name", sval);
-                        grabResolverMap.put("root", sval);
-                    } else {
-                        for (String s : GRABRESOLVER_REQUIRED) {
-                            String mval = getMemberStringValue(node, s);
-                            Expression member = node.getMember(s);
-                            if (member == null || (mval != null && mval.isEmpty())) {
-                                addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                                continue grabResolverAnnotationLoop;
-                            } else if (mval == null) {
-                                addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant String in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                                continue grabResolverAnnotationLoop;
-                            }
-                            grabResolverMap.put(s, mval);
-                        }
-                    }
-
-                    // If no scheme is specified for the repository root,
-                    // then turn it into a URI relative to that of the source file.
-                    String root = (String) grabResolverMap.get("root");
-                    if (root != null && !root.contains(":")) {
-                        URI sourceURI = null;
-                        // Since we use the data: scheme for StringReaderSources (which are fairly common)
-                        // and those are not hierarchical we can't use them for making an absolute URI.
-                        if (!(getSourceUnit().getSource() instanceof StringReaderSource)) {
-                            // Otherwise let's trust the source to know where it is from.
-                            // And actually InputStreamReaderSource doesn't know what to do and so returns null.
-                            sourceURI = getSourceUnit().getSource().getURI();
-                        }
-                        // If source doesn't know how to get a reference to itself,
-                        // then let's use the current working directory, since the repo can be relative to that.
-                        if (sourceURI == null) {
-                            sourceURI = new File(".").toURI();
-                        }
-                        try {
-                            URI rootURI = sourceURI.resolve(new URI(root));
-                            grabResolverMap.put("root", rootURI.toString());
-                        } catch (URISyntaxException e) {
-                            // We'll be silent here.
-                            // If the URI scheme is unknown or not hierarchical, then we just can't help them and shouldn't cause any trouble either.
-                            // addError("Attribute \"root\" has value '" + root + "' which can't be turned into a valid URI relative to it's source '" + getSourceUnit().getName() + "' @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                        }
-                    }
-
-                    Grape.addResolver(grabResolverMap);
-                    addGrabResolverAsStaticInitIfNeeded(grapeClassNode, node, grabResolverInitializers, grabResolverMap);
-                }
-            }
-
-            if (!grabConfigAnnotations.isEmpty()) {
-                for (AnnotationNode node : grabConfigAnnotations) {
-                    checkForClassLoader(node);
-                    checkForInitContextClassLoader(node);
-                    checkForAutoDownload(node);
-                    checkForSystemProperties(node);
-                    checkForDisableChecksums(node);
-                }
-                addInitContextClassLoaderIfNeeded(classNode);
-            }
-
-            if (!grabExcludeAnnotations.isEmpty()) {
-                grabExcludeAnnotationLoop:
-                for (AnnotationNode node : grabExcludeAnnotations) {
-                    Map<String, Object> grabExcludeMap = new HashMap<String, Object>();
-                    checkForConvenienceForm(node, true);
-                    for (String s : GRABEXCLUDE_REQUIRED) {
-                        Expression member = node.getMember(s);
-                        if (member == null) {
-                            addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                            continue grabExcludeAnnotationLoop;
-                        } else if (member != null && !(member instanceof ConstantExpression)) {
-                            addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                            continue grabExcludeAnnotationLoop;
-                        }
-                        grabExcludeMap.put(s, ((ConstantExpression)member).getValue());
-                    }
-                    grabExcludeMaps.add(grabExcludeMap);
-                }
-            }
-
-            if (!grabAnnotations.isEmpty()) {
-                grabAnnotationLoop:
-                for (AnnotationNode node : grabAnnotations) {
-                    Map<String, Object> grabMap = new HashMap<String, Object>();
-                    checkForConvenienceForm(node, false);
-                    for (String s : GRAB_ALL) {
-                        Expression member = node.getMember(s);
-                        String mval = getMemberStringValue(node, s);
-                        if (mval != null && mval.isEmpty()) member = null;
-                        if (member == null && !GRAB_OPTIONAL.contains(s)) {
-                            addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                            continue grabAnnotationLoop;
-                        } else if (member != null && !(member instanceof ConstantExpression)) {
-                            addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
-                            continue grabAnnotationLoop;
-                        }
-                        if (node.getMember(s) != null) {
-                            grabMap.put(s, ((ConstantExpression)member).getValue());
-                        }
-                    }
-                    grabMaps.add(grabMap);
-                    if ((node.getMember("initClass") == null) || (node.getMember("initClass") == ConstantExpression.TRUE)) {
-                        grabMapsInit.add(grabMap);
-                    }
-                }
-                callGrabAsStaticInitIfNeeded(classNode, grapeClassNode, grabMapsInit, grabExcludeMaps);
-            }
-
-            if (!grabResolverInitializers.isEmpty()) {
-                classNode.addStaticInitializerStatements(grabResolverInitializers, true);
-            }
-        }
-
-        if (!grabMaps.isEmpty()) {
-            Map<String, Object> basicArgs = new HashMap<String, Object>();
-            basicArgs.put("classLoader", loader != null ? loader : sourceUnit.getClassLoader());
-            if (!grabExcludeMaps.isEmpty()) basicArgs.put("excludes", grabExcludeMaps);
-            if (autoDownload != null) basicArgs.put(AUTO_DOWNLOAD_SETTING, autoDownload);
-            if (disableChecksums != null) basicArgs.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
-            if (systemProperties != null) basicArgs.put(SYSTEM_PROPERTIES_SETTING, systemProperties);
-
-            try {
-                Grape.grab(basicArgs, grabMaps.toArray(new Map[grabMaps.size()]));
-                // grab may have added more transformations through new URLs added to classpath, so do one more scan
-                if (compilationUnit!=null) {
-                    ASTTransformationVisitor.addGlobalTransformsAfterGrab(compilationUnit.getASTTransformationsContext());
-                }
-            } catch (RuntimeException re) {
-                // Decided against syntax exception since this is not a syntax error.
-                // The down side is we lose line number information for the offending
-                // @Grab annotation.
-                source.addException(re);
-            }
-        }
-    }
-
-    private void callGrabAsStaticInitIfNeeded(ClassNode classNode, ClassNode grapeClassNode, List<Map<String,Object>> grabMapsInit, List<Map<String, Object>> grabExcludeMaps) {
-        List<Statement> grabInitializers = new ArrayList<Statement>();
-        MapExpression basicArgs = new MapExpression();
-        if (autoDownload != null)  {
-            basicArgs.addMapEntryExpression(constX(AUTO_DOWNLOAD_SETTING), constX(autoDownload));
-        }
-
-        if (disableChecksums != null)  {
-            basicArgs.addMapEntryExpression(constX(DISABLE_CHECKSUMS_SETTING), constX(disableChecksums));
-        }
-
-        if (systemProperties != null && !systemProperties.isEmpty()) {
-            BlockStatement block = new BlockStatement();
-            for(Map.Entry e : systemProperties.entrySet()) {
-                block.addStatement(stmt(callX(SYSTEM_CLASSNODE, "setProperty", args(constX(e.getKey()), constX(e.getValue())))));
-            }
-            StaticMethodCallExpression enabled = callX(SYSTEM_CLASSNODE, "getProperty", args(constX("groovy.grape.enable"), constX("true")));
-            grabInitializers.add(ifS(eqX(enabled, constX("true")), block));
-        }
-
-        if (!grabExcludeMaps.isEmpty()) {
-            ListExpression list = new ListExpression();
-            for (Map<String, Object> map : grabExcludeMaps) {
-                Set<Map.Entry<String, Object>> entries = map.entrySet();
-                MapExpression inner = new MapExpression();
-                for (Map.Entry<String, Object> entry : entries) {
-                    inner.addMapEntryExpression(constX(entry.getKey()), constX(entry.getValue()));
-                }
-                list.addExpression(inner);
-            }
-            basicArgs.addMapEntryExpression(constX("excludes"), list);
-        }
-
-        List<Expression> argList = new ArrayList<Expression>();
-        argList.add(basicArgs);
-        if (grabMapsInit.isEmpty()) return;
-        for (Map<String, Object> grabMap : grabMapsInit) {
-            // add Grape.grab(excludeArgs, [group:group, module:module, version:version, classifier:classifier])
-            // or Grape.grab([group:group, module:module, version:version, classifier:classifier])
-            MapExpression dependencyArg = new MapExpression();
-            for (String s : GRAB_REQUIRED) {
-                dependencyArg.addMapEntryExpression(constX(s), constX(grabMap.get(s)));
-            }
-            for (String s : GRAB_OPTIONAL) {
-                if (grabMap.containsKey(s))
-                    dependencyArg.addMapEntryExpression(constX(s), constX(grabMap.get(s)));
-            }
-            argList.add(dependencyArg);
-        }
-        grabInitializers.add(stmt(callX(grapeClassNode, "grab", args(argList))));
-
-        // insert at beginning so we have the classloader set up before the class is called
-        classNode.addStaticInitializerStatements(grabInitializers, true);
-    }
-
-    private static void addGrabResolverAsStaticInitIfNeeded(ClassNode grapeClassNode, AnnotationNode node,
-                                                      List<Statement> grabResolverInitializers, Map<String, Object> grabResolverMap) {
-        if ((node.getMember("initClass") == null)
-            || (node.getMember("initClass") == ConstantExpression.TRUE))
-        {
-            MapExpression resolverArgs = new MapExpression();
-            for (Map.Entry<String, Object> next : grabResolverMap.entrySet()) {
-                resolverArgs.addMapEntryExpression(constX(next.getKey()), constX(next.getValue()));
-            }
-            grabResolverInitializers.add(stmt(callX(grapeClassNode, "addResolver", args(resolverArgs))));
-        }
-    }
-
-    private void addInitContextClassLoaderIfNeeded(ClassNode classNode) {
-        if (initContextClassLoader) {
-            Statement initStatement = stmt(callX(
-                            callX(THREAD_CLASSNODE, "currentThread"),
-                            "setContextClassLoader",
-                            callX(callThisX("getClass"), "getClassLoader")
-                    )
-            );
-            classNode.addObjectInitializerStatements(initStatement);
-        }
-    }
-
-    private void checkForClassLoader(AnnotationNode node) {
-        Object val = node.getMember("systemClassLoader");
-        if (val == null || !(val instanceof ConstantExpression)) return;
-        Object systemClassLoaderObject = ((ConstantExpression)val).getValue();
-        if (!(systemClassLoaderObject instanceof Boolean)) return;
-        Boolean systemClassLoader = (Boolean) systemClassLoaderObject;
-        if (systemClassLoader) loader = ClassLoader.getSystemClassLoader();
-    }
-
-    private void checkForInitContextClassLoader(AnnotationNode node) {
-        Object val = node.getMember("initContextClassLoader");
-        if (val == null || !(val instanceof ConstantExpression)) return;
-        Object initContextClassLoaderObject = ((ConstantExpression)val).getValue();
-        if (!(initContextClassLoaderObject instanceof Boolean)) return;
-        initContextClassLoader = (Boolean) initContextClassLoaderObject;
-    }
-
-    private void checkForAutoDownload(AnnotationNode node) {
-        Object val = node.getMember(AUTO_DOWNLOAD_SETTING);
-        if (val == null || !(val instanceof ConstantExpression)) return;
-        Object autoDownloadValue = ((ConstantExpression)val).getValue();
-        if (!(autoDownloadValue instanceof Boolean)) return;
-        autoDownload = (Boolean) autoDownloadValue;
-    }
-
-    private void checkForDisableChecksums(AnnotationNode node) {
-        Object val = node.getMember(DISABLE_CHECKSUMS_SETTING);
-        if (val == null || !(val instanceof ConstantExpression)) return;
-        Object disableChecksumsValue = ((ConstantExpression)val).getValue();
-        if (!(disableChecksumsValue instanceof Boolean)) return;
-        disableChecksums = (Boolean) disableChecksumsValue;
-    }
-
-    private void checkForSystemProperties(AnnotationNode node) {
-        systemProperties = new HashMap<String, String>();
-        List<String> nameValueList = AbstractASTTransformation.getMemberStringList(node, SYSTEM_PROPERTIES_SETTING);
-        if (nameValueList != null) {
-            for (String nameValue : nameValueList) {
-                int equalsDelim = nameValue.indexOf('=');
-                if (equalsDelim != -1) {
-                    systemProperties.put(nameValue.substring(0, equalsDelim), nameValue.substring(equalsDelim + 1));
-                }
-            }
-        }
-    }
-
-    private static void checkForConvenienceForm(AnnotationNode node, boolean exclude) {
-        Object val = node.getMember("value");
-        if (val == null || !(val instanceof ConstantExpression)) return;
-        Object allParts = ((ConstantExpression)val).getValue();
-        if (!(allParts instanceof String)) return;
-        String allstr = (String) allParts;
-
-        // strip off trailing attributes
-        boolean done = false;
-        while (!done) {
-            Matcher attrs = ATTRIBUTES_PATTERN.matcher(allstr);
-            if (attrs.find()) {
-                String attrName = attrs.group(2);
-                String attrValue = attrs.group(3);
-                if (attrName == null || attrValue == null) continue;
-                boolean isBool = GRAB_BOOLEAN.contains(attrName);
-                ConstantExpression value = constX(isBool ? Boolean.valueOf(attrValue) : attrValue);
-                value.setSourcePosition(node);
-                node.addMember(attrName, value);
-                int lastSemi = allstr.lastIndexOf(';');
-                if (lastSemi == -1) {
-                    allstr = "";
-                    break;
-                }
-                allstr = allstr.substring(0, lastSemi);
-            } else {
-                done = true;
-            }
-        }
-
-        if (allstr.contains("#")) {
-            // see: http://ant.apache.org/ivy/history/latest-milestone/textual.html
-            Matcher m = IVY_PATTERN.matcher(allstr);
-            if (!m.find()) return;
-            if (m.group(1) == null || m.group(2) == null) return;
-            node.addMember("module", constX(m.group(2)));
-            node.addMember("group", constX(m.group(1)));
-            if (m.group(6) != null) node.addMember("conf", constX(m.group(6)));
-            if (m.group(4) != null) node.addMember("version", constX(m.group(4)));
-            else if (!exclude && node.getMember("version") == null) node.addMember("version", constX("*"));
-            node.getMembers().remove("value");
-        } else if (allstr.contains(":")) {
-            // assume gradle syntax
-            // see: http://www.gradle.org/latest/docs/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
-            Map<String, Object> parts = GrapeUtil.getIvyParts(allstr);
-            for (Map.Entry<String, Object> entry : parts.entrySet()) {
-                String key = entry.getKey();
-                String value = entry.getValue().toString();
-                if (!key.equals("version") || !value.equals("*") || !exclude) {
-                    node.addMember(key, constX(value));
-                }
-            }
-            node.getMembers().remove("value");
-        }
-    }
-
-    private void extractGrab(Expression init, ConstantExpression ce) {
-        if (ce.getValue() instanceof AnnotationNode) {
-            AnnotationNode annotation = (AnnotationNode) ce.getValue();
-            if ((init != null) && (annotation.getMember("initClass") != null)) {
-                annotation.setMember("initClass", init);
-            }
-            String name = annotation.getClassNode().getName();
-            if ((GRAB_CLASS_NAME.equals(name))
-                    || (allowShortGrab && GRAB_SHORT_NAME.equals(name))
-                    || (grabAliases.contains(name))) {
-                grabAnnotations.add(annotation);
-            }
-            if ((GRABEXCLUDE_CLASS_NAME.equals(name))
-                    || (allowShortGrabExcludes && GRABEXCLUDE_SHORT_NAME.equals(name))
-                    || (grabExcludeAliases.contains(name))) {
-                grabExcludeAnnotations.add(annotation);
-            }
-            if ((GRABCONFIG_CLASS_NAME.equals(name))
-                    || (allowShortGrabConfig && GRABCONFIG_SHORT_NAME.equals(name))
-                    || (grabConfigAliases.contains(name))) {
-                grabConfigAnnotations.add(annotation);
-            }
-            if ((GRABRESOLVER_CLASS_NAME.equals(name))
-                    || (allowShortGrabResolver && GRABRESOLVER_SHORT_NAME.equals(name))
-                    || (grabResolverAliases.contains(name))) {
-                grabResolverAnnotations.add(annotation);
-            }
-        }
-    }
-
-    /**
-     * Adds the annotation to the internal target list if a match is found.
-     *
-     * @param node the AST node we are processing
-     */
-    public void visitAnnotations(AnnotatedNode node) {
-        super.visitAnnotations(node);
-        for (AnnotationNode an : node.getAnnotations()) {
-            String name = an.getClassNode().getName();
-            if ((GRAB_CLASS_NAME.equals(name))
-                    || (allowShortGrab && GRAB_SHORT_NAME.equals(name))
-                    || (grabAliases.contains(name))) {
-                grabAnnotations.add(an);
-            }
-            if ((GRABEXCLUDE_CLASS_NAME.equals(name))
-                    || (allowShortGrabExcludes && GRABEXCLUDE_SHORT_NAME.equals(name))
-                    || (grabExcludeAliases.contains(name))) {
-                grabExcludeAnnotations.add(an);
-            }
-            if ((GRABCONFIG_CLASS_NAME.equals(name))
-                    || (allowShortGrabConfig && GRABCONFIG_SHORT_NAME.equals(name))
-                    || (grabConfigAliases.contains(name))) {
-                grabConfigAnnotations.add(an);
-            }
-            if ((GRAPES_CLASS_NAME.equals(name))
-                    || (allowShortGrapes && GRAPES_SHORT_NAME.equals(name))
-                    || (grapesAliases.contains(name))) {
-                grapesAnnotations.add(an);
-            }
-            if ((GRABRESOLVER_CLASS_NAME.equals(name))
-                    || (allowShortGrabResolver && GRABRESOLVER_SHORT_NAME.equals(name))
-                    || (grabResolverAliases.contains(name))) {
-                grabResolverAnnotations.add(an);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/grape/Grape.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/grape/Grape.java b/src/main/groovy/grape/Grape.java
deleted file mode 100644
index c534ded..0000000
--- a/src/main/groovy/grape/Grape.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- *  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 groovy.grape;
-
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Facade to GrapeEngine.
- */
-public class Grape {
-
-    public static final String AUTO_DOWNLOAD_SETTING = "autoDownload";
-    public static final String DISABLE_CHECKSUMS_SETTING = "disableChecksums";
-    public static final String SYSTEM_PROPERTIES_SETTING = "systemProperties";
-
-    private static boolean enableGrapes = Boolean.valueOf(System.getProperty("groovy.grape.enable", "true"));
-    private static boolean enableAutoDownload = Boolean.valueOf(System.getProperty("groovy.grape.autoDownload", "true"));
-    private static boolean disableChecksums = Boolean.valueOf(System.getProperty("groovy.grape.disableChecksums", "false"));
-    protected static GrapeEngine instance;
-
-    /**
-     * This is a static access kill-switch.  All of the static shortcut
-     * methods in this class will not work if this property is set to false.
-     * By default it is set to true.
-     */
-    public static boolean getEnableGrapes() {
-        return enableGrapes;
-    }
-
-    /**
-     * This is a static access kill-switch.  All of the static shortcut
-     * methods in this class will not work if this property is set to false.
-     * By default it is set to true.
-     */
-    public static void setEnableGrapes(boolean enableGrapes) {
-        Grape.enableGrapes = enableGrapes;
-    }
-
-    /**
-     * This is a static access auto download enabler.  It will set the
-     * 'autoDownload' value to the passed in arguments map if not already set.
-     * If 'autoDownload' is set the value will not be adjusted.
-     * <p>
-     * This applies to the grab and resolve calls.
-     * <p>
-     * If it is set to false, only previously downloaded grapes
-     * will be used.  This may cause failure in the grape call
-     * if the library has not yet been downloaded
-     * <p>
-     * If it is set to true, then any jars not already downloaded will
-     * automatically be downloaded.  Also, any versions expressed as a range
-     * will be checked for new versions and downloaded (with dependencies)
-     * if found.
-     * <p>
-     * By default it is set to true.
-     */
-    public static boolean getEnableAutoDownload() {
-        return enableAutoDownload;
-    }
-
-    /**
-     * This is a static access auto download enabler.  It will set the
-     * 'autoDownload' value to the passed in arguments map if not already
-     * set.  If 'autoDownload' is set the value will not be adjusted.
-     * <p>
-     * This applies to the grab and resolve calls.
-     * <p>
-     * If it is set to false, only previously downloaded grapes
-     * will be used.  This may cause failure in the grape call
-     * if the library has not yet been downloaded.
-     * <p>
-     * If it is set to true, then any jars not already downloaded will
-     * automatically be downloaded.  Also, any versions expressed as a range
-     * will be checked for new versions and downloaded (with dependencies)
-     * if found. By default it is set to true.
-     */
-    public static void setEnableAutoDownload(boolean enableAutoDownload) {
-        Grape.enableAutoDownload = enableAutoDownload;
-    }
-
-    /**
-     * Global flag to ignore checksums.
-     * By default it is set to false.
-     */
-    public static boolean getDisableChecksums() {
-        return disableChecksums;
-    }
-
-    /**
-     * Set global flag to ignore checksums.
-     * By default it is set to false.
-     */
-    public static void setDisableChecksums(boolean disableChecksums) {
-        Grape.disableChecksums = disableChecksums;
-    }
-
-    public static synchronized GrapeEngine getInstance() {
-        if (instance == null) {
-            try {
-                // by default use GrapeIvy
-                //TODO META-INF/services resolver?
-                instance = (GrapeEngine) Class.forName("groovy.grape.GrapeIvy").newInstance();
-            } catch (InstantiationException e) {
-                //LOGME
-            } catch (IllegalAccessException e) {
-                //LOGME
-            } catch (ClassNotFoundException e) {
-                //LOGME
-            }
-        }
-        return instance;
-    }
-
-    public static void grab(String endorsed) {
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                instance.grab(endorsed);
-            }
-        }
-    }
-
-    public static void grab(Map<String, Object> dependency) {
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                if (!dependency.containsKey(AUTO_DOWNLOAD_SETTING)) {
-                    dependency.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
-                }
-                if (!dependency.containsKey(DISABLE_CHECKSUMS_SETTING)) {
-                    dependency.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
-                }
-                instance.grab(dependency);
-            }
-        }
-    }
-
-    public static void grab(Map<String, Object> args, Map... dependencies) {
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                if (!args.containsKey(AUTO_DOWNLOAD_SETTING)) {
-                    args.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
-                }
-                if (!args.containsKey(DISABLE_CHECKSUMS_SETTING)) {
-                    args.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
-                }
-                instance.grab(args, dependencies);
-            }
-        }
-    }
-
-    public static Map<String, Map<String, List<String>>> enumerateGrapes() {
-        Map<String, Map<String, List<String>>> grapes = null;
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                grapes = instance.enumerateGrapes();
-            }
-        }
-        if (grapes == null) {
-            return Collections.emptyMap();
-        } else {
-            return grapes;
-        }
-    }
-
-    public static URI[] resolve(Map<String, Object> args, Map... dependencies) {
-        return resolve(args, null, dependencies);
-    }
-    
-    public static URI[] resolve(Map<String, Object> args, List depsInfo, Map... dependencies) {
-        URI[] uris = null;
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                if (!args.containsKey(AUTO_DOWNLOAD_SETTING)) {
-                    args.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
-                }
-                if (!args.containsKey(DISABLE_CHECKSUMS_SETTING)) {
-                    args.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
-                }
-                uris = instance.resolve(args, depsInfo, dependencies);
-            }
-        }
-        if (uris == null) {
-            return new URI[0];
-        } else {
-            return uris;
-        }
-    }
-
-    public static Map[] listDependencies(ClassLoader cl) {
-        Map[] maps = null;
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                maps = instance.listDependencies(cl);
-            }
-        }
-        if (maps == null) {
-            return new Map[0];
-        } else {
-            return maps;
-        }
-
-    }
-    
-    public static void addResolver(Map<String, Object> args) {
-        if (enableGrapes) {
-            GrapeEngine instance = getInstance();
-            if (instance != null) {
-                instance.addResolver(args);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/grape/GrapeEngine.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/grape/GrapeEngine.java b/src/main/groovy/grape/GrapeEngine.java
deleted file mode 100644
index 4ce171f..0000000
--- a/src/main/groovy/grape/GrapeEngine.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  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 groovy.grape;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Danno Ferrin
- */
-public interface GrapeEngine {
-
-    Object grab(String endorsedModule);
-
-    Object grab(Map args);
-
-    Object grab(Map args, Map... dependencies);
-
-    Map<String, Map<String, List<String>>> enumerateGrapes();
-
-    URI[] resolve(Map args, Map... dependencies);
-
-    URI[] resolve(Map args, List depsInfo, Map... dependencies);
-
-    Map[] listDependencies(ClassLoader classLoader);
-
-    void addResolver(Map<String, Object> args);
-}
-

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/grape/GrapeIvy.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/grape/GrapeIvy.groovy b/src/main/groovy/grape/GrapeIvy.groovy
deleted file mode 100644
index a2c22a8..0000000
--- a/src/main/groovy/grape/GrapeIvy.groovy
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- *  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 groovy.grape
-
-import org.apache.groovy.plugin.GroovyRunner
-import org.apache.groovy.plugin.GroovyRunnerRegistry
-import org.apache.ivy.Ivy
-import org.apache.ivy.core.cache.ResolutionCacheManager
-import org.apache.ivy.core.event.IvyListener
-import org.apache.ivy.core.event.download.PrepareDownloadEvent
-import org.apache.ivy.core.event.resolve.StartResolveEvent
-import org.apache.ivy.core.module.descriptor.Configuration
-import org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor
-import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
-import org.apache.ivy.core.module.descriptor.DefaultExcludeRule
-import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
-import org.apache.ivy.core.module.id.ArtifactId
-import org.apache.ivy.core.module.id.ModuleId
-import org.apache.ivy.core.module.id.ModuleRevisionId
-import org.apache.ivy.core.report.ArtifactDownloadReport
-import org.apache.ivy.core.report.ResolveReport
-import org.apache.ivy.core.resolve.ResolveOptions
-import org.apache.ivy.core.settings.IvySettings
-import org.apache.ivy.plugins.matcher.ExactPatternMatcher
-import org.apache.ivy.plugins.matcher.PatternMatcher
-import org.apache.ivy.plugins.resolver.ChainResolver
-import org.apache.ivy.plugins.resolver.IBiblioResolver
-import org.apache.ivy.util.DefaultMessageLogger
-import org.apache.ivy.util.Message
-import org.codehaus.groovy.reflection.CachedClass
-import org.codehaus.groovy.reflection.ClassInfo
-import org.codehaus.groovy.reflection.ReflectionUtils
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl
-
-import javax.xml.parsers.DocumentBuilderFactory
-import java.util.jar.JarFile
-import java.util.regex.Pattern
-import java.util.zip.ZipEntry
-import java.util.zip.ZipException
-import java.util.zip.ZipFile
-
-/**
- * @author Danno Ferrin
- * @author Paul King
- * @author Roshan Dawrani (roshandawrani)
- */
-class GrapeIvy implements GrapeEngine {
-
-    static final int DEFAULT_DEPTH = 3
-
-    private static final String METAINF_PREFIX = 'META-INF/services/'
-    private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.class.getName()
-
-    private final exclusiveGrabArgs = [
-            ['group', 'groupId', 'organisation', 'organization', 'org'],
-            ['module', 'artifactId', 'artifact'],
-            ['version', 'revision', 'rev'],
-            ['conf', 'scope', 'configuration'],
-        ].inject([:], {m, g -> g.each {a -> m[a] = (g - a) as Set};  m})
-
-    boolean enableGrapes
-    Ivy ivyInstance
-    Set<String> resolvedDependencies
-    Set<String> downloadedArtifacts
-    // weak hash map so we don't leak loaders directly
-    Map<ClassLoader, Set<IvyGrabRecord>> loadedDeps = new WeakHashMap<ClassLoader, Set<IvyGrabRecord>>()
-    // set that stores the IvyGrabRecord(s) for all the dependencies in each grab() call
-    Set<IvyGrabRecord> grabRecordsForCurrDependencies = new LinkedHashSet<IvyGrabRecord>()
-    // we keep the settings so that addResolver can add to the resolver chain
-    IvySettings settings
-
-    public GrapeIvy() {
-        // if we are already initialized, quit
-        if (enableGrapes) return
-
-        // start ivy
-        Message.defaultLogger = new DefaultMessageLogger(System.getProperty("ivy.message.logger.level", "-1") as int)
-        settings = new IvySettings()
-
-        // configure settings
-        def grapeConfig = getLocalGrapeConfig()
-        if (!grapeConfig.exists()) {
-            grapeConfig = GrapeIvy.getResource("defaultGrapeConfig.xml")
-        }
-        try {
-            settings.load(grapeConfig) // exploit multi-methods for convenience
-        } catch (java.text.ParseException ex) {
-            def configLocation = grapeConfig instanceof File ? grapeConfig.canonicalPath : grapeConfig.toString()
-            System.err.println "Local Ivy config file '$configLocation' appears corrupt - ignoring it and using default config instead\nError was: " + ex.message
-            grapeConfig = GrapeIvy.getResource("defaultGrapeConfig.xml")
-            settings.load(grapeConfig)
-        }
-
-        // set up the cache dirs
-        settings.defaultCache = getGrapeCacheDir()
-
-        settings.setVariable("ivy.default.configuration.m2compatible", "true")
-        ivyInstance = Ivy.newInstance(settings)
-        org.apache.ivy.core.IvyContext.getContext().setIvy(ivyInstance);
-        resolvedDependencies = []
-        downloadedArtifacts = []
-
-        //TODO add grab to the DGM??
-
-        enableGrapes = true
-    }
-
-    public File getGroovyRoot() {
-        String root = System.getProperty("groovy.root")
-        def groovyRoot
-        if (root == null) {
-            groovyRoot = new File(System.getProperty("user.home"), ".groovy")
-        } else {
-            groovyRoot = new File(root)
-        }
-        try {
-            groovyRoot = groovyRoot.canonicalFile
-        } catch (IOException e) {
-            // skip canonicalization then, it may not exist yet
-        }
-        return groovyRoot
-    }
-
-    public File getLocalGrapeConfig() {
-        String grapeConfig = System.getProperty("grape.config")
-        if(grapeConfig) {
-            return new File(grapeConfig)
-        }
-        return new File(getGrapeDir(), 'grapeConfig.xml')
-    }
-
-    public File getGrapeDir() {
-        String root = System.getProperty("grape.root")
-        if(root == null) {
-            return getGroovyRoot()
-        }
-        File grapeRoot = new File(root)
-        try {
-            grapeRoot = grapeRoot.canonicalFile
-        } catch (IOException e) {
-            // skip canonicalization then, it may not exist yet
-        }
-        return grapeRoot
-    }
-
-    public File getGrapeCacheDir() {
-        File cache =  new File(getGrapeDir(), 'grapes')
-        if (!cache.exists()) {
-            cache.mkdirs()
-        } else if (!cache.isDirectory()) {
-            throw new RuntimeException("The grape cache dir $cache is not a directory")
-        }
-        return cache
-    }
-
-    public def chooseClassLoader(Map args) {
-        def loader = args.classLoader
-        if (!isValidTargetClassLoader(loader)) {
-            loader = (args.refObject?.class
-                        ?:ReflectionUtils.getCallingClass(args.calleeDepth?:1)
-                      )?.classLoader
-            while (loader && !isValidTargetClassLoader(loader)) {
-                loader = loader.parent
-            }
-            //if (!isValidTargetClassLoader(loader)) {
-            //    loader = Thread.currentThread().contextClassLoader
-            //}
-            //if (!isValidTargetClassLoader(loader)) {
-            //    loader = GrapeIvy.class.classLoader
-            //}
-            if (!isValidTargetClassLoader(loader)) {
-                throw new RuntimeException("No suitable ClassLoader found for grab")
-            }
-        }
-        return loader
-    }
-
-    private boolean isValidTargetClassLoader(loader) {
-        return isValidTargetClassLoaderClass(loader?.class)
-    }
-
-    private boolean isValidTargetClassLoaderClass(Class loaderClass) {
-        return (loaderClass != null) &&
-            (
-             (loaderClass.name == 'groovy.lang.GroovyClassLoader') ||
-             (loaderClass.name == 'org.codehaus.groovy.tools.RootLoader') ||
-             isValidTargetClassLoaderClass(loaderClass.superclass)
-            )
-    }
-
-    public IvyGrabRecord createGrabRecord(Map deps) {
-        // parse the actual dependency arguments
-        String module =  deps.module ?: deps.artifactId ?: deps.artifact
-        if (!module) {
-            throw new RuntimeException('grab requires at least a module: or artifactId: or artifact: argument')
-        }
-
-        String groupId = deps.group ?: deps.groupId ?: deps.organisation ?: deps.organization ?: deps.org ?: ''
-        String ext = deps.ext ?: deps.type ?: ''
-        String type = deps.type ?: ''
-
-        //TODO accept ranges and decode them?  except '1.0.0'..<'2.0.0' won't work in groovy
-        String version = deps.version ?: deps.revision ?: deps.rev ?: '*'
-        if ('*' == version) version = 'latest.default'
-
-        ModuleRevisionId mrid = ModuleRevisionId.newInstance(groupId, module, version)
-
-        boolean force      = deps.containsKey('force')      ? deps.force      : true
-        boolean changing   = deps.containsKey('changing')   ? deps.changing   : false
-        boolean transitive = deps.containsKey('transitive') ? deps.transitive : true
-        def conf = deps.conf ?: deps.scope ?: deps.configuration ?: ['default']
-        if (conf instanceof String) {
-            if (conf.startsWith("[") && conf.endsWith("]")) conf = conf[1..-2]
-            conf = conf.split(",").toList()
-        }
-        def classifier = deps.classifier ?: null
-
-        return new IvyGrabRecord(mrid:mrid, conf:conf, changing:changing, transitive:transitive, force:force, classifier:classifier, ext:ext, type:type)
-    }
-
-    public grab(String endorsedModule) {
-        return grab(group:'groovy.endorsed', module:endorsedModule, version:GroovySystem.version)
-    }
-
-    public grab(Map args) {
-        args.calleeDepth = args.calleeDepth?:DEFAULT_DEPTH + 1
-        return grab(args, args)
-    }
-
-    public grab(Map args, Map... dependencies) {
-        ClassLoader loader = null
-        grabRecordsForCurrDependencies.clear()
-
-        try {
-            // identify the target classloader early, so we fail before checking repositories
-            loader = chooseClassLoader(
-                classLoader:args.remove('classLoader'),
-                refObject:args.remove('refObject'),
-                calleeDepth:args.calleeDepth?:DEFAULT_DEPTH,
-            )
-
-            // check for non-fail null.
-            // If we were in fail mode we would have already thrown an exception
-            if (!loader) return
-
-            def uris = resolve(loader, args, dependencies)
-            for (URI uri in uris) {
-                loader.addURL(uri.toURL())
-            }
-            boolean runnerServicesFound = false
-            for (URI uri in uris) {
-                //TODO check artifact type, jar vs library, etc
-                File file = new File(uri)
-                processCategoryMethods(loader, file)
-                Collection<String> services = processMetaInfServices(loader, file)
-                if (!runnerServicesFound) {
-                    runnerServicesFound = services.contains(RUNNER_PROVIDER_CONFIG)
-                }
-            }
-            if (runnerServicesFound) {
-                GroovyRunnerRegistry.getInstance().load(loader)
-            }
-        } catch (Exception e) {
-            // clean-up the state first
-            Set<IvyGrabRecord> grabRecordsForCurrLoader = getLoadedDepsForLoader(loader)
-            grabRecordsForCurrLoader.removeAll(grabRecordsForCurrDependencies)
-            grabRecordsForCurrDependencies.clear()
-
-            if (args.noExceptions) {
-                return e
-            }
-            throw e
-        }
-        return null
-    }
-
-    private processCategoryMethods(ClassLoader loader, File file) {
-        // register extension methods if jar
-        if (file.name.toLowerCase().endsWith(".jar")) {
-            def mcRegistry = GroovySystem.metaClassRegistry
-            if (mcRegistry instanceof MetaClassRegistryImpl) {
-                try {
-                    JarFile jar = new JarFile(file)
-                    def entry = jar.getEntry(MetaClassRegistryImpl.MODULE_META_INF_FILE)
-                    if (entry) {
-                        Properties props = new Properties()
-                        props.load(jar.getInputStream(entry))
-                        Map<CachedClass, List<MetaMethod>> metaMethods = new HashMap<CachedClass, List<MetaMethod>>()
-                        mcRegistry.registerExtensionModuleFromProperties(props, loader, metaMethods)
-                        // add old methods to the map
-                        metaMethods.each { CachedClass c, List<MetaMethod> methods ->
-                            // GROOVY-5543: if a module was loaded using grab, there are chances that subclasses
-                            // have their own ClassInfo, and we must change them as well!
-                            Set<CachedClass> classesToBeUpdated = [c]
-                            ClassInfo.onAllClassInfo { ClassInfo info ->
-                                if (c.theClass.isAssignableFrom(info.cachedClass.theClass)) {
-                                    classesToBeUpdated << info.cachedClass
-                                }
-                            }
-                            classesToBeUpdated*.addNewMopMethods(methods)
-                        }
-                    }
-                }
-                catch(ZipException zipException) {
-                    throw new RuntimeException("Grape could not load jar '$file'", zipException)
-                }
-            }
-        }
-    }
-
-    void processOtherServices(ClassLoader loader, File f) {
-        processMetaInfServices(loader, f) // ignore result
-    }
-
-    /**
-     * Searches the given File for known service provider
-     * configuration files to process.
-     *
-     * @param loader used to locate service provider files
-     * @param f ZipFile in which to search for services
-     * @return a collection of service provider files that were found
-     */
-    private Collection<String> processMetaInfServices(ClassLoader loader, File f) {
-        List<String> services = new ArrayList<>()
-        try {
-            ZipFile zf = new ZipFile(f)
-            String providerConfig = 'org.codehaus.groovy.runtime.SerializedCategoryMethods'
-            ZipEntry serializedCategoryMethods = zf.getEntry(METAINF_PREFIX + providerConfig)
-            if (serializedCategoryMethods != null) {
-                services.add(providerConfig)
-                processSerializedCategoryMethods(zf.getInputStream(serializedCategoryMethods))
-            }
-            // TODO: remove in a future release (replaced by GroovyRunnerRegistry)
-            providerConfig = 'org.codehaus.groovy.plugins.Runners'
-            ZipEntry pluginRunners = zf.getEntry(METAINF_PREFIX + providerConfig)
-            if (pluginRunners != null) {
-                services.add(providerConfig)
-                processRunners(zf.getInputStream(pluginRunners), f.getName(), loader)
-            }
-            // GroovyRunners are loaded per ClassLoader using a ServiceLoader so here
-            // it only needs to be indicated that the service provider file was found
-            if (zf.getEntry(METAINF_PREFIX + RUNNER_PROVIDER_CONFIG) != null) {
-                services.add(RUNNER_PROVIDER_CONFIG)
-            }
-        } catch(ZipException ignore) {
-            // ignore files we can't process, e.g. non-jar/zip artifacts
-            // TODO log a warning
-        }
-        return services
-    }
-
-    void processSerializedCategoryMethods(InputStream is) {
-        is.text.readLines().each {
-            println it.trim() // TODO implement this or delete it
-        }
-    }
-
-    void processRunners(InputStream is, String name, ClassLoader loader) {
-        GroovyRunnerRegistry registry = GroovyRunnerRegistry.getInstance()
-        is.text.readLines()*.trim().findAll{ !it.isEmpty() && it[0] != '#' }.each {
-            try {
-                registry[name] = loader.loadClass(it).newInstance()
-            } catch (Exception ex) {
-                throw new IllegalStateException("Error registering runner class '" + it + "'", ex)
-            }
-        }
-    }
-
-    public ResolveReport getDependencies(Map args, IvyGrabRecord... grabRecords) {
-        ResolutionCacheManager cacheManager = ivyInstance.resolutionCacheManager
-
-        def millis = System.currentTimeMillis()
-        def md = new DefaultModuleDescriptor(ModuleRevisionId
-                .newInstance("caller", "all-caller", "working" + millis.toString()[-2..-1]), "integration", null, true)
-        md.addConfiguration(new Configuration('default'))
-        md.setLastModified(millis)
-
-        addExcludesIfNeeded(args, md)
-
-        for (IvyGrabRecord grabRecord : grabRecords) {
-            def conf = grabRecord.conf ?: ['*']
-            DefaultDependencyDescriptor dd = md.dependencies.find {it.dependencyRevisionId.equals(grabRecord.mrid)}
-            if (dd) {
-                createAndAddDependencyArtifactDescriptor(dd, grabRecord, conf)
-            } else {
-                dd = new DefaultDependencyDescriptor(md, grabRecord.mrid, grabRecord.force,
-                        grabRecord.changing, grabRecord.transitive)
-                conf.each {dd.addDependencyConfiguration('default', it)}
-                createAndAddDependencyArtifactDescriptor(dd, grabRecord, conf)
-                md.addDependency(dd)
-            }
-        }
-
-       // resolve grab and dependencies
-        ResolveOptions resolveOptions = new ResolveOptions()\
-            .setConfs(['default'] as String[])\
-            .setOutputReport(false)\
-            .setValidate(args.containsKey('validate') ? args.validate : false)
-
-        ivyInstance.settings.defaultResolver = args.autoDownload ? 'downloadGrapes' : 'cachedGrapes'
-        if (args.disableChecksums) {
-            ivyInstance.settings.setVariable('ivy.checksums', '')
-        }
-        boolean reportDownloads = System.getProperty('groovy.grape.report.downloads', 'false') == 'true'
-        if (reportDownloads) {
-            ivyInstance.eventManager.addIvyListener([progress:{ ivyEvent -> switch(ivyEvent) {
-                case StartResolveEvent:
-                    ivyEvent.moduleDescriptor.dependencies.each { it ->
-                        def name = it.toString()
-                        if (!resolvedDependencies.contains(name)) {
-                            resolvedDependencies << name
-                            System.err.println "Resolving " + name
-                        }
-                    }
-                    break
-                case PrepareDownloadEvent:
-                    ivyEvent.artifacts.each { it ->
-                        def name = it.toString()
-                        if (!downloadedArtifacts.contains(name)) {
-                            downloadedArtifacts << name
-                            System.err.println "Preparing to download artifact " + name
-                        }
-                    }
-                    break
-            } } ] as IvyListener)
-        }
-
-        ResolveReport report = null
-        int attempt = 8 // max of 8 times
-        while (true) {
-            try {
-                report = ivyInstance.resolve(md, resolveOptions)
-                break
-            } catch(IOException ioe) {
-                if (attempt--) {
-                    if (reportDownloads)
-                        System.err.println "Grab Error: retrying..."
-                    sleep attempt > 4 ? 350 : 1000
-                    continue
-                }
-                throw new RuntimeException("Error grabbing grapes -- $ioe.message")
-            }
-        }
-
-        if (report.hasError()) {
-            throw new RuntimeException("Error grabbing Grapes -- $report.allProblemMessages")
-        }
-        if (report.downloadSize && reportDownloads) {
-            System.err.println "Downloaded ${report.downloadSize >> 10} Kbytes in ${report.downloadTime}ms:\n  ${report.allArtifactsReports*.toString().join('\n  ')}"
-        }
-        md = report.moduleDescriptor
-
-        if (!args.preserveFiles) {
-            cacheManager.getResolvedIvyFileInCache(md.moduleRevisionId).delete()
-            cacheManager.getResolvedIvyPropertiesInCache(md.moduleRevisionId).delete()
-        }
-
-        return report
-    }
-
-    private void createAndAddDependencyArtifactDescriptor(DefaultDependencyDescriptor dd, IvyGrabRecord grabRecord, List<String> conf) {
-        // TODO: find out "unknown" reason and change comment below - also, confirm conf[0] check vs conf.contains('optional')
-        if (conf[0]!="optional" || grabRecord.classifier) {  // for some unknown reason optional dependencies should not have an artifactDescriptor
-            def dad = new DefaultDependencyArtifactDescriptor(dd,
-                    grabRecord.mrid.name, grabRecord.type ?: 'jar', grabRecord.ext ?: 'jar', null, grabRecord.classifier ? [classifier: grabRecord.classifier] : null)
-            conf.each { dad.addConfiguration(it) }
-            dd.addDependencyArtifact('default', dad)
-        }
-    }
-
-    public void uninstallArtifact(String group, String module, String rev) {
-        // TODO consider transitive uninstall as an option
-        Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
-        grapeCacheDir.eachDir { File groupDir ->
-            if (groupDir.name == group) groupDir.eachDir { File moduleDir ->
-                if (moduleDir.name == module) moduleDir.eachFileMatch(ivyFilePattern) { File ivyFile ->
-                    def m = ivyFilePattern.matcher(ivyFile.name)
-                    if (m.matches() && m.group(1) == rev) {
-                        // TODO handle other types? e.g. 'dlls'
-                        def jardir = new File(moduleDir, 'jars')
-                        if (!jardir.exists()) return
-                        def dbf = DocumentBuilderFactory.newInstance()
-                        def db = dbf.newDocumentBuilder()
-                        def root = db.parse(ivyFile).documentElement
-                        def publis = root.getElementsByTagName('publications')
-                        for (int i=0; i<publis.length;i++) {
-                            def artifacts = publis.item(i).getElementsByTagName('artifact')
-                            for (int j=0; j<artifacts.length; j++) {
-                                def artifact = artifacts.item(j)
-                                def attrs = artifact.attributes
-                                def name = attrs.getNamedItem('name').getTextContent() + "-$rev"
-                                def classifier = attrs.getNamedItemNS("m", "classifier")?.getTextContent()
-                                if (classifier) name += "-$classifier"
-                                name += ".${attrs.getNamedItem('ext').getTextContent()}"
-                                def jarfile = new File(jardir, name)
-                                if (jarfile.exists()) {
-                                    println "Deleting ${jarfile.name}"
-                                    jarfile.delete()
-                                }
-                            }
-                        }
-                        ivyFile.delete()
-                    }
-                }
-            }
-        }
-    }
-
-    private addExcludesIfNeeded(Map args, DefaultModuleDescriptor md) {
-        if (!args.containsKey('excludes')) return
-        args.excludes.each{ map ->
-            def excludeRule = new DefaultExcludeRule(new ArtifactId(
-                    new ModuleId(map.group, map.module), PatternMatcher.ANY_EXPRESSION,
-                    PatternMatcher.ANY_EXPRESSION,
-                    PatternMatcher.ANY_EXPRESSION),
-                    ExactPatternMatcher.INSTANCE, null)
-            excludeRule.addConfiguration('default')
-            md.addExcludeRule(excludeRule)
-        }
-    }
-
-    public Map<String, Map<String, List<String>>> enumerateGrapes() {
-        Map<String, Map<String, List<String>>> bunches = [:]
-        Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
-        grapeCacheDir.eachDir {File groupDir ->
-            Map<String, List<String>> grapes = [:]
-            bunches[groupDir.name] = grapes
-            groupDir.eachDir { File moduleDir ->
-                def versions = []
-                moduleDir.eachFileMatch(ivyFilePattern) {File ivyFile ->
-                    def m = ivyFilePattern.matcher(ivyFile.name)
-                    if (m.matches()) versions += m.group(1)
-                }
-                grapes[moduleDir.name] = versions
-            }
-        }
-        return bunches
-    }
-
-    public URI[] resolve(Map args, Map ... dependencies) {
-        resolve(args, null, dependencies)
-    }
-
-    public URI[] resolve(Map args, List depsInfo, Map ... dependencies) {
-        // identify the target classloader early, so we fail before checking repositories
-        def loader = chooseClassLoader(
-                classLoader: args.remove('classLoader'),
-                refObject: args.remove('refObject'),
-                calleeDepth: args.calleeDepth ?: DEFAULT_DEPTH,
-        )
-
-        // check for non-fail null.
-        // If we were in fail mode we would have already thrown an exception
-        if (!loader) return
-
-        resolve(loader, args, depsInfo, dependencies)
-    }
-
-    URI [] resolve(ClassLoader loader, Map args, Map... dependencies) {
-        return resolve(loader, args, null, dependencies)
-    }
-
-    URI [] resolve(ClassLoader loader, Map args, List depsInfo, Map... dependencies) {
-        // check for mutually exclusive arguments
-        Set keys = args.keySet()
-        keys.each {a ->
-            Set badArgs = exclusiveGrabArgs[a]
-            if (badArgs && !badArgs.disjoint(keys)) {
-                throw new RuntimeException("Mutually exclusive arguments passed into grab: ${keys.intersect(badArgs) + a}")
-            }
-        }
-
-        // check the kill switch
-        if (!enableGrapes) { return }
-
-        boolean populateDepsInfo = (depsInfo != null)
-
-        Set<IvyGrabRecord> localDeps = getLoadedDepsForLoader(loader)
-
-        dependencies.each {
-            IvyGrabRecord igr = createGrabRecord(it)
-            grabRecordsForCurrDependencies.add(igr)
-            localDeps.add(igr)
-        }
-        // the call to reverse ensures that the newest additions are in
-        // front causing existing dependencies to come last and thus
-        // claiming higher priority.  Thus when module versions clash we
-        // err on the side of using the class already loaded into the
-        // classloader rather than adding another jar of the same module
-        // with a different version
-        ResolveReport report = null
-        try {
-            report = getDependencies(args, *localDeps.asList().reverse())
-        } catch (Exception e) {
-            // clean-up the state first
-            localDeps.removeAll(grabRecordsForCurrDependencies)
-            grabRecordsForCurrDependencies.clear()
-            throw e
-        }
-
-        List<URI> results = []
-        for (ArtifactDownloadReport adl in report.allArtifactsReports) {
-            //TODO check artifact type, jar vs library, etc
-            if (adl.localFile) {
-                results += adl.localFile.toURI()
-            }
-        }
-
-        if (populateDepsInfo) {
-            def deps = report.dependencies
-            deps.each { depNode ->
-                def id = depNode.id
-                depsInfo << ['group' : id.organisation, 'module' : id.name, 'revision' : id.revision]
-            }
-        }
-
-        return results as URI[]
-    }
-
-    private Set<IvyGrabRecord> getLoadedDepsForLoader(ClassLoader loader) {
-        Set<IvyGrabRecord> localDeps = loadedDeps.get(loader)
-        if (localDeps == null) {
-            // use a linked set to preserve initial insertion order
-            localDeps = new LinkedHashSet<IvyGrabRecord>()
-            loadedDeps.put(loader, localDeps)
-        }
-        return localDeps
-    }
-
-    public Map[] listDependencies (ClassLoader classLoader) {
-        if (loadedDeps.containsKey(classLoader)) {
-            List<Map> results = []
-            loadedDeps[classLoader].each { IvyGrabRecord grabbed ->
-                def dep =  [
-                    group : grabbed.mrid.organisation,
-                    module : grabbed.mrid.name,
-                    version : grabbed.mrid.revision
-                ]
-                if (grabbed.conf != ['default']) {
-                    dep.conf = grabbed.conf
-                }
-                if (grabbed.changing) {
-                    dep.changing = grabbed.changing
-                }
-                if (!grabbed.transitive) {
-                    dep.transitive = grabbed.transitive
-                }
-                if (!grabbed.force) {
-                    dep.force = grabbed.force
-                }
-                if (grabbed.classifier) {
-                    dep.classifier = grabbed.classifier
-                }
-                if (grabbed.ext) {
-                    dep.ext = grabbed.ext
-                }
-                if (grabbed.type) {
-                    dep.type = grabbed.type
-                }
-                results << dep
-            }
-            return results
-        }
-        return null
-    }
-
-    public void addResolver(Map<String, Object> args) {
-        ChainResolver chainResolver = settings.getResolver("downloadGrapes")
-
-        IBiblioResolver resolver = new IBiblioResolver(name: args.name, root:args.root,
-              m2compatible:(args.m2Compatible ?: true), settings:settings)
-
-        chainResolver.add(resolver)
-
-        ivyInstance = Ivy.newInstance(settings)
-        resolvedDependencies = []
-        downloadedArtifacts = []
-    }
-}
-
-class IvyGrabRecord {
-    ModuleRevisionId mrid
-    List<String> conf
-    boolean changing
-    boolean transitive
-    boolean force
-    String classifier
-    String ext
-    String type
-
-    public int hashCode() {
-        return (mrid.hashCode() ^ conf.hashCode()
-            ^ (changing ? 0xaaaaaaaa : 0x55555555)
-            ^ (transitive ? 0xbbbbbbbb : 0x66666666)
-            ^ (force ? 0xcccccccc: 0x77777777)
-            ^ (classifier ? classifier.hashCode() : 0)
-            ^ (ext ? ext.hashCode() : 0)
-            ^ (type ? type.hashCode() : 0))
-    }
-
-    public boolean equals(Object o) {
-        return ((o.class == IvyGrabRecord)
-            && (changing == o.changing)
-            && (transitive == o.transitive)
-            && (force== o.force)
-            && (mrid == o.mrid)
-            && (conf == o.conf)
-            && (classifier == o.classifier)
-            && (ext == o.ext)
-            && (type == o.type))
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/Bindable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/Bindable.java b/src/main/groovy/groovy/beans/Bindable.java
new file mode 100644
index 0000000..e9bd292
--- /dev/null
+++ b/src/main/groovy/groovy/beans/Bindable.java
@@ -0,0 +1,116 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a groovy property or a class.
+ *
+ * When annotating a property it indicates that the property should be a
+ * bound property according to the JavaBeans spec, announcing to listeners
+ * that the value has changed.
+ * <p>
+ * When annotating a class it indicates that all groovy properties in that
+ * class should be bound as though each property had the annotation (even
+ * if it already has it explicitly).
+ * <p>
+ * It is a compilation error to place this annotation on a field (that is
+ * not a property, i.e. has scope visibility modifiers).
+ * <p>
+ * If a property with a user defined setter method is annotated the code
+ * block is wrapped with the needed code to fire off the event.
+ * <p>
+ * The following example shows how you can use this annotation on fields
+ * of a class: 
+ * <pre>
+ * class Person {
+ *    &#064;groovy.beans.Bindable
+ *    String firstName
+ *
+ *    &#064;groovy.beans.Bindable
+ *    def zipCode
+ * }
+ * </pre>
+ * The above example will generate code that is similar to the next snippet. 
+ * Notice the difference between a String property and a def/Object property: 
+ * <pre>
+ * public class Person { 
+ *     &#064;groovy.beans.Bindable
+ *     private java.lang.String firstName 
+ *     &#064;groovy.beans.Bindable
+ *     private java.lang.Object zipCode 
+ *     final private java.beans.PropertyChangeSupport this$propertyChangeSupport 
+ * 
+ *     public Person() {
+ *         this$propertyChangeSupport = new java.beans.PropertyChangeSupport(this)
+ *     }
+ * 
+ *     public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {
+ *         this$propertyChangeSupport.addPropertyChangeListener(listener)
+ *     }
+ * 
+ *     public void addPropertyChangeListener(java.lang.String name, java.beans.PropertyChangeListener listener) {
+ *         this$propertyChangeSupport.addPropertyChangeListener(name, listener)
+ *     }
+ * 
+ *     public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {
+ *         this$propertyChangeSupport.removePropertyChangeListener(listener)
+ *     }
+ * 
+ *     public void removePropertyChangeListener(java.lang.String name, java.beans.PropertyChangeListener listener) {
+ *         this$propertyChangeSupport.removePropertyChangeListener(name, listener)
+ *     }
+ * 
+ *     public void firePropertyChange(java.lang.String name, java.lang.Object oldValue, java.lang.Object newValue) {
+ *         this$propertyChangeSupport.firePropertyChange(name, oldValue, newValue)
+ *     }
+ * 
+ *     public java.beans.PropertyChangeListener[] getPropertyChangeListeners() {
+ *         return this$propertyChangeSupport.getPropertyChangeListeners()
+ *     }
+ * 
+ *     public java.beans.PropertyChangeListener[] getPropertyChangeListeners(java.lang.String name) {
+ *         return this$propertyChangeSupport.getPropertyChangeListeners(name)
+ *     }
+ * 
+ *     public void setFirstName(java.lang.String value) {
+ *         this.firePropertyChange('firstName', firstName, firstName = value )
+ *     }
+ * 
+ *     public void setZipCode(java.lang.Object value) {
+ *         this.firePropertyChange('zipCode', zipCode, zipCode = value )
+ *     }
+ * }
+ * </pre>
+ *
+ * @see BindableASTTransformation
+ * @author Danno Ferrin (shemnon)
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD, ElementType.TYPE})
+@GroovyASTTransformationClass("groovy.beans.BindableASTTransformation")
+public @interface Bindable {
+}


[38/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ExpandoMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ExpandoMetaClass.java b/src/main/groovy/groovy/lang/ExpandoMetaClass.java
new file mode 100644
index 0000000..d56f738
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ExpandoMetaClass.java
@@ -0,0 +1,1510 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.MixinInMetaClass;
+import org.codehaus.groovy.runtime.DefaultCachedMethodKey;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.runtime.MethodKey;
+import org.codehaus.groovy.runtime.callsite.CallSite;
+import org.codehaus.groovy.runtime.callsite.ConstructorMetaMethodSite;
+import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
+import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
+import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
+import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.DefaultMetaClassInfo;
+import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
+import org.codehaus.groovy.runtime.metaclass.MixedInMetaClass;
+import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.OwnedMetaClass;
+import org.codehaus.groovy.runtime.metaclass.ThreadManagedMetaBeanProperty;
+import org.codehaus.groovy.util.FastArray;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * ExpandoMetaClass is a MetaClass that behaves like an Expando, allowing the addition or replacement
+ * of methods, properties and constructors on the fly.
+ * <p>
+ * Some examples of usage:
+ * <pre>
+ * // defines or replaces instance method:
+ * metaClass.myMethod = { args -> }
+ *
+ * // defines a new instance method
+ * metaClass.myMethod << { args -> }
+ *
+ * // creates multiple overloaded methods of the same name
+ * metaClass.myMethod << { String s -> } << { Integer i -> }
+ *
+ * // defines or replaces a static method with the 'static' qualifier
+ * metaClass.'static'.myMethod = { args ->  }
+ *
+ * // defines a new static method with the 'static' qualifier
+ * metaClass.'static'.myMethod << { args ->  }
+ *
+ * // defines a new constructor
+ * metaClass.constructor << { String arg -> }
+ *
+ * // defines or replaces a constructor
+ * metaClass.constructor = { String arg -> }
+ *
+ * // defines a new property with an initial value of "blah"
+ * metaClass.myProperty = "blah"
+ * </pre>
+ * <p>
+ * ExpandoMetaClass also supports a DSL/builder like notation to combine multiple definitions together. So instead of this:
+ * <pre>
+ * Number.metaClass.multiply = { Amount amount -> amount.times(delegate) }
+ * Number.metaClass.div =      { Amount amount -> amount.inverse().times(delegate) }
+ * </pre>
+ * You can also now do this:
+ * <pre>
+ * Number.metaClass {
+ *     multiply { Amount amount -> amount.times(delegate) }
+ *     div      { Amount amount -> amount.inverse().times(delegate) }
+ * }
+ * </pre>
+ * <p>
+ * ExpandoMetaClass also supports runtime mixins. While {@code @Mixin} allows you to mix in new behavior
+ * to classes you own and are designing, you can not easily mixin anything to types you didn't own, e.g.
+ * from third party libraries or from JDK library classes.
+ * Runtime mixins let you add a mixin on any type at runtime.
+ * <pre>
+ * interface Vehicle {
+ *     String getName()
+ * }
+ *
+ * // Category annotation style
+ * {@code @Category}(Vehicle) class FlyingAbility {
+ *     def fly() { "I'm the ${name} and I fly!" }
+ * }
+ *
+ * // traditional category style
+ * class DivingAbility {
+ *     static dive(Vehicle self) { "I'm the ${self.name} and I dive!" }
+ * }
+ *
+ * // provided by a third-party, so can't augment using Mixin annotation
+ * class JamesBondVehicle implements Vehicle {
+ *     String getName() { "James Bond's vehicle" }
+ * }
+ *
+ * // Can be added via metaClass, e.g.:
+ * // JamesBondVehicle.metaClass.mixin DivingAbility, FlyingAbility
+ * // Or using shorthand through DGM method on Class
+ * JamesBondVehicle.mixin DivingAbility, FlyingAbility
+ *
+ * assert new JamesBondVehicle().fly() ==
+ *        "I'm the James Bond's vehicle and I fly!"
+ * assert new JamesBondVehicle().dive() ==
+ *        "I'm the James Bond's vehicle and I dive!"
+ * </pre>
+ * As another example, consider the following class definitions:
+ * <pre>
+ * class Student {
+ *     List<String> schedule = []
+ *     def addLecture(String lecture) { schedule << lecture }
+ * }
+ *
+ * class Worker {
+ *     List<String> schedule = []
+ *     def addMeeting(String meeting) { schedule << meeting }
+ * }
+ * </pre>
+ * We can mimic a form of multiple inheritance as follows:
+ * <pre>
+ * class CollegeStudent {
+ *     static { mixin Student, Worker }
+ * }
+ * new CollegeStudent().with {
+ *     addMeeting('Performance review with Boss')
+ *     addLecture('Learn about Groovy Mixins')
+ *     println schedule
+ *     println mixedIn[Student].schedule
+ *     println mixedIn[Worker].schedule
+ * }
+ * </pre>
+ * Which outputs these lines when run:
+ * <pre>
+ * [Performance review with Boss]
+ * [Learn about Groovy Mixins]
+ * [Performance review with Boss]
+ * </pre>
+ * Perhaps some explanation is required here. The methods and properties of Student and Worker are
+ * added to CollegeStudent. Worker is added last, so for overlapping methods, its methods will
+ * be used, e.g. when calling <code>schedule</code>, it will be the schedule property (getSchedule method)
+ * from Worker that is used. The schedule property from Student will be shadowed but the <code>mixedIn</code>
+ * notation allows us to get to that too if we need as the last two lines show.
+ * <p>
+ * We can also be a little more dynamic and not require the CollegeStudent class to
+ * be defined at all, e.g.:
+ * <pre>
+ * def cs = new Object()
+ * cs.metaClass {
+ *     mixin Student, Worker
+ *     getSchedule {
+ *         mixedIn[Student].schedule + mixedIn[Worker].schedule
+ *     }
+ * }
+ * cs.with {
+ *     addMeeting('Performance review with Boss')
+ *     addLecture('Learn about Groovy Mixins')
+ *     println schedule
+ * }
+ * </pre>
+ * Which outputs this line when run:
+ * <pre>
+ * [Learn about Groovy Mixins, Performance review with Boss]
+ * </pre>
+ * As another example, we can also define a no dup queue by mixing in some
+ * Queue and Set functionality as follows:
+ * <pre>
+ * def ndq = new Object()
+ * ndq.metaClass {
+ *     mixin ArrayDeque
+ *     mixin HashSet
+ *     leftShift = { Object o ->
+ *         if (!mixedIn[Set].contains(o)) {
+ *             mixedIn[Queue].push(o)
+ *             mixedIn[Set].add(o)
+ *         }
+ *     }
+ * }
+ * ndq << 1
+ * ndq << 2
+ * ndq << 1
+ * assert ndq.size() == 2
+ * </pre>
+ * As a final example, we sometimes need to pass such mixed in classes or objects
+ * into Java methods which require a given static type but the ExpandoMetaClass mixin approach uses a very dynamic
+ * approach based on duck typing rather than static interface definitions, so doesn't by default
+ * produce objects matching the required static type. Luckily, there is a mixins capability
+ * within ExpandoMetaClass which supports the use of Groovy's common 'as StaticType' notation to produce an object
+ * having the correct static type so that it can be passed to the Java method call in question.
+ * A slightly contrived example illustrating this feature:
+ * <pre>
+ * class CustomComparator implements Comparator {
+ *     int compare(Object a, b) { return a.size() - b.size() }
+ * }
+ *
+ * class CustomCloseable implements Closeable {
+ *     void close() { println 'Lights out - I am closing' }
+ * }
+ *
+ * import static mypackage.IOUtils.closeQuietly
+ * import static java.util.Collections.sort
+ * def o = new Object()
+ * o.metaClass.mixin CustomComparator, CustomCloseable
+ * def items = ['a', 'bbb', 'cc']
+ * sort(items, o as Comparator)
+ * println items                // => [a, cc, bbb]
+ * closeQuietly(o as Closeable) // => Lights out - I am closing
+ * </pre>
+ * <p>
+ * <b>Further details</b>
+ * <p>
+ * When using the default implementations of MetaClass, methods are only allowed to be added before initialize() is called.
+ * In other words you create a new MetaClass, add some methods and then call initialize(). If you attempt to add new methods
+ * after initialize() has been called, an error will be thrown. This is to ensure that the MetaClass can operate appropriately
+ * in multi-threaded environments as it forces you to do all method additions at the beginning, before using the MetaClass.
+ * <p>
+ * ExpandoMetaClass differs here from the default in that it allows you to add methods after initialize has been called.
+ * This is done by setting the initialize flag internally to false and then add the methods. Since this is not thread
+ * safe it has to be done in a synchronized block. The methods to check for modification and initialization are
+ * therefore synchronized as well. Any method call done through this meta class will first check if the it is
+ * synchronized. Should this happen during a modification, then the method cannot be selected or called unless the
+ * modification is completed.
+ * <p>
+ *
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public class ExpandoMetaClass extends MetaClassImpl implements GroovyObject {
+
+    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+    private static final String META_CLASS = "metaClass";
+    private static final String CLASS = "class";
+    private static final String META_METHODS = "metaMethods";
+    private static final String METHODS = "methods";
+    private static final String PROPERTIES = "properties";
+    public static final String STATIC_QUALIFIER = "static";
+    public static final String CONSTRUCTOR = "constructor";
+
+    private static final String CLASS_PROPERTY = "class";
+    private static final String META_CLASS_PROPERTY = "metaClass";
+    private static final String GROOVY_CONSTRUCTOR = "<init>";
+
+    // These two properties are used when no ExpandoMetaClassCreationHandle is present
+
+    private MetaClass myMetaClass;
+    private boolean initialized;
+    private volatile boolean modified;
+
+    private boolean initCalled;
+    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+    private final Lock readLock = rwl.readLock();
+    private final Lock writeLock = rwl.writeLock();
+    
+    private final boolean allowChangesAfterInit;
+    public boolean inRegistry;
+    
+    private final Set<MetaMethod> inheritedMetaMethods = new HashSet<MetaMethod>();
+    private final Map<String, MetaProperty> beanPropertyCache = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
+    private final Map<String, MetaProperty> staticBeanPropertyCache = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
+    private final Map<MethodKey, MetaMethod> expandoMethods = new ConcurrentHashMap<MethodKey, MetaMethod>(16, 0.75f, 1);
+
+    public Collection getExpandoSubclassMethods() {
+        return expandoSubclassMethods.values();
+    }
+
+    private final ConcurrentHashMap expandoSubclassMethods = new ConcurrentHashMap(16, 0.75f, 1);
+    private final Map<String, MetaProperty> expandoProperties = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
+    private ClosureStaticMetaMethod invokeStaticMethodMethod;
+    private final Set<MixinInMetaClass> mixinClasses = new LinkedHashSet<MixinInMetaClass>();
+
+    public ExpandoMetaClass(Class theClass, boolean register, boolean allowChangesAfterInit, MetaMethod[] add) {
+        this(GroovySystem.getMetaClassRegistry(), theClass, register, allowChangesAfterInit, add);
+    }
+    
+    public ExpandoMetaClass(MetaClassRegistry registry, Class theClass, boolean register, boolean allowChangesAfterInit, MetaMethod[] add) {
+        super(registry, theClass, add);
+        this.myMetaClass = InvokerHelper.getMetaClass(getClass());
+        this.inRegistry = register;
+        this.allowChangesAfterInit = allowChangesAfterInit;
+    }
+    
+    /**
+     * Constructs a new ExpandoMetaClass instance for the given class
+     *
+     * @param theClass The class that the MetaClass applies to
+     */
+    public ExpandoMetaClass(Class theClass) {
+        this(theClass,false,false,null);
+    }
+
+    public ExpandoMetaClass(Class theClass, MetaMethod [] add) {
+        this(theClass,false,false,add);
+    }
+
+    /**
+     * Constructs a new ExpandoMetaClass instance for the given class optionally placing the MetaClass
+     * in the MetaClassRegistry automatically
+     *
+     * @param theClass The class that the MetaClass applies to
+     * @param register True if the MetaClass should be registered inside the MetaClassRegistry. This defaults to true and ExpandoMetaClass will effect all instances if changed
+     */
+    public ExpandoMetaClass(Class theClass, boolean register) {
+        this(theClass,register,false,null);
+    }
+
+    public ExpandoMetaClass(Class theClass, boolean register, MetaMethod [] add) {
+        this(theClass, register, false, add);
+    }
+
+    /**
+     * Constructs a new ExpandoMetaClass instance for the given class optionally placing the MetaClass
+     * in the MetaClassRegistry automatically
+     *
+     * @param theClass The class that the MetaClass applies to
+     * @param register True if the MetaClass should be registered inside the MetaClassRegistry. This defaults to true and ExpandoMetaClass will effect all instances if changed
+     * @param allowChangesAfterInit Should the meta class be modifiable after initialization. Default is false.
+     */
+    public ExpandoMetaClass(Class theClass, boolean register, boolean allowChangesAfterInit) {
+        this(theClass, register, allowChangesAfterInit, null);
+    }
+
+    public MetaMethod findMixinMethod(String methodName, Class[] arguments) {
+        for (MixinInMetaClass mixin : mixinClasses) {
+            final CachedClass mixinClass = mixin.getMixinClass();
+            MetaClass metaClass = mixinClass.classInfo.getMetaClassForClass();
+            if (metaClass == null) {
+                metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(mixinClass.getTheClass());
+            }
+
+            MetaMethod metaMethod = metaClass.pickMethod(methodName, arguments);
+            if (metaMethod == null && metaClass instanceof MetaClassImpl) {
+                MetaClassImpl mc = (MetaClassImpl) metaClass;
+                for (CachedClass cl = mc.getTheCachedClass().getCachedSuperClass(); cl != null; cl = cl.getCachedSuperClass()) {
+                    metaMethod = mc.getMethodWithoutCaching(cl.getTheClass(), methodName, arguments, false);
+                    if (metaMethod != null)
+                        break;
+                }
+            }
+            if (metaMethod != null) {
+                MetaMethod method = new MixinInstanceMetaMethod(metaMethod, mixin);
+
+                if (method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].isPrimitive) {
+                    MetaMethod noParam = pickMethod(methodName, EMPTY_CLASS_ARRAY);
+                    // if the current call itself is with empty arg class array, no need to recurse with 'new Class[0]'
+                    if (noParam == null && arguments.length != 0) {
+                        try {
+                            findMixinMethod(methodName, EMPTY_CLASS_ARRAY);
+                        } catch (MethodSelectionException msex) {
+                            /*
+                             * Here we just additionally tried to find another no-arg mixin method of the same name and register that as well, if found.
+                             * Safe to ignore a MethodSelectionException in this additional exercise. (GROOVY-4999)
+                             */
+                        }
+                    }
+                }
+
+                registerInstanceMethod(method);
+                return method;
+            }
+        }
+        return null;
+    }
+
+    protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
+        this.invokeMethodMethod = method;
+    }
+
+    protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
+        addSuperMethodIfNotOverridden(method);
+    }
+
+    protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
+        addMetaBeanProperty(property);
+    }
+
+    protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
+        this.setPropertyMethod = method;
+    }
+
+    protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
+        this.getPropertyMethod = method;
+    }
+
+    public boolean isModified() {
+        return this.modified;
+    }
+
+    public void registerSubclassInstanceMethod(String name, Class klazz, Closure closure) {
+        final List<MetaMethod> list = ClosureMetaMethod.createMethodList(name, klazz, closure);
+        for (MetaMethod metaMethod : list) {
+            registerSubclassInstanceMethod(metaMethod);
+        }
+    }
+
+    public void registerSubclassInstanceMethod(MetaMethod metaMethod) {
+        modified = true;
+
+        final String name = metaMethod.getName();
+        Object methodOrList = expandoSubclassMethods.get(name);
+        if (methodOrList == null) {
+            expandoSubclassMethods.put(name, metaMethod);
+        } else {
+            if (methodOrList instanceof MetaMethod) {
+                FastArray arr = new FastArray(2);
+                arr.add(methodOrList);
+                arr.add(metaMethod);
+                expandoSubclassMethods.put(name, arr);
+            } else {
+                ((FastArray) methodOrList).add(metaMethod);
+            }
+        }
+    }
+
+    public void addMixinClass(MixinInMetaClass mixin) {
+        mixinClasses.add(mixin);
+    }
+
+    public Object castToMixedType(Object obj, Class type) {
+        for (MixinInMetaClass mixin : mixinClasses) {
+            if (type.isAssignableFrom(mixin.getMixinClass().getTheClass()))
+                return mixin.getMixinInstance(obj);
+        }
+        return null;
+    }
+
+    /**
+     * For simulating closures in Java
+     */
+    private interface Callable {
+        void call();
+    }
+
+    /**
+     * Call to enable global use of ExpandoMetaClass within the registry.
+     * This has the advantage that inheritance will function correctly and 
+     * metaclass modifications will also apply to existing objects,
+     * but has a higher memory usage on the JVM than normal Groovy
+     */
+    public static void enableGlobally() {
+        DefaultMetaClassInfo.setWithoutCustomMetaclassCreationHandle(false);
+        ExpandoMetaClassCreationHandle.enable();
+    }
+
+    /**
+     * Call to disable the global use of ExpandoMetaClass
+     */
+    public static void disableGlobally() {
+        DefaultMetaClassInfo.setWithoutCustomMetaclassCreationHandle(true);
+        ExpandoMetaClassCreationHandle.disable();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClassImpl#initialize()
+     */
+
+    public void initialize() {
+        try {
+            writeLock.lock();
+            if (!isInitialized()) {
+                super.initialize();
+                setInitialized(true);
+                this.initCalled = true;
+            }
+        } finally {
+            // downgrade to readlock before releasing just in case
+            readLock.lock();
+            writeLock.unlock();
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Checks if the meta class is initialized.
+     * @see groovy.lang.MetaClassImpl#isInitialized()
+     */
+    protected boolean isInitialized() {
+        try {
+            readLock.lock();
+            return this.initialized;
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    protected void setInitialized(boolean b) {
+        this.initialized = b;
+    }
+
+    private void addSuperMethodIfNotOverridden(final MetaMethod metaMethodFromSuper) {
+        performOperationOnMetaClass(new Callable() {
+            public void call() {
+
+                MetaMethod existing = null;
+                try {
+                    existing = pickMethod(metaMethodFromSuper.getName(), metaMethodFromSuper.getNativeParameterTypes());
+                } catch ( GroovyRuntimeException e) {
+                    // ignore, this happens with overlapping method definitions
+                }
+
+                if (existing == null) {
+                    addMethodWithKey(metaMethodFromSuper);
+                } else {
+                    boolean isGroovyMethod = getMetaMethods().contains(existing);
+
+                    if (isGroovyMethod) {
+                        addMethodWithKey(metaMethodFromSuper);
+                    } else if (inheritedMetaMethods.contains(existing)) {
+                        inheritedMetaMethods.remove(existing);
+                        addMethodWithKey(metaMethodFromSuper);
+                    }
+                }
+            }
+
+            private void addMethodWithKey(final MetaMethod metaMethodFromSuper) {
+                inheritedMetaMethods.add(metaMethodFromSuper);
+                if (metaMethodFromSuper instanceof ClosureMetaMethod) {
+                    ClosureMetaMethod closureMethod = (ClosureMetaMethod)metaMethodFromSuper;
+                    String name = metaMethodFromSuper.getName();
+                    final Class declaringClass = metaMethodFromSuper.getDeclaringClass().getTheClass();
+                    ClosureMetaMethod localMethod = ClosureMetaMethod.copy(closureMethod);
+                    addMetaMethod(localMethod);
+
+                    MethodKey key = new DefaultCachedMethodKey(declaringClass, name, localMethod.getParameterTypes(), false);
+
+                    checkIfGroovyObjectMethod(localMethod);
+                    expandoMethods.put(key, localMethod);
+
+                }
+            }
+        });
+    }
+
+    /**
+     * Instances of this class are returned when using the << left shift operator.
+     * <p>
+     * Example:
+     * <p>
+     * metaClass.myMethod << { String args -> }
+     * <p>
+     * This allows callbacks to the ExpandoMetaClass for registering appending methods
+     *
+     * @author Graeme Rocher
+     */
+    protected class ExpandoMetaProperty extends GroovyObjectSupport {
+
+        protected String propertyName;
+        protected boolean isStatic;
+
+        protected ExpandoMetaProperty(String name) {
+            this(name, false);
+        }
+
+        protected ExpandoMetaProperty(String name, boolean isStatic) {
+            this.propertyName = name;
+            this.isStatic = isStatic;
+        }
+
+        public String getPropertyName() {
+            return this.propertyName;
+        }
+
+        public boolean isStatic() {
+            return this.isStatic;
+        }
+
+        public Object leftShift(Object arg) {
+            registerIfClosure(arg, false);
+            return this;
+        }
+
+        private void registerIfClosure(Object arg, boolean replace) {
+            if (arg instanceof Closure) {
+                Closure callable = (Closure) arg;
+                final List<MetaMethod> list = ClosureMetaMethod.createMethodList(propertyName, theClass, callable);
+                if (list.isEmpty() && this.isStatic) {
+                    Class[] paramTypes = callable.getParameterTypes();
+                    registerStatic(callable, replace, paramTypes);
+                    return;
+                }
+                for (MetaMethod method : list) {
+                    Class[] paramTypes = method.getNativeParameterTypes();
+                    if (this.isStatic) {
+                        registerStatic(callable, replace, paramTypes);
+                    } else {
+                        registerInstance(method, replace, paramTypes);
+                    }
+                }
+            }
+        }
+
+        private void registerStatic(Closure callable, boolean replace, Class[] paramTypes) {
+            Method foundMethod = checkIfMethodExists(theClass, propertyName, paramTypes, true);
+            if (foundMethod != null && !replace)
+                throw new GroovyRuntimeException("Cannot add new static method [" + propertyName + "] for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
+            registerStaticMethod(propertyName, callable, paramTypes);
+        }
+
+        private void registerInstance(MetaMethod method, boolean replace, Class[] paramTypes) {
+            Method foundMethod = checkIfMethodExists(theClass, propertyName, paramTypes, false);
+            if (foundMethod != null && !replace)
+                throw new GroovyRuntimeException("Cannot add new method [" + propertyName + "] for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
+            registerInstanceMethod(method);
+        }
+
+        private Method checkIfMethodExists(Class methodClass, String methodName, Class[] paramTypes, boolean staticMethod) {
+            Method foundMethod = null;
+            Method[] methods = methodClass.getMethods();
+            for (Method method : methods) {
+                if (method.getName().equals(methodName) && Modifier.isStatic(method.getModifiers()) == staticMethod) {
+                    if (MetaClassHelper.parametersAreCompatible(paramTypes, method.getParameterTypes())) {
+                        foundMethod = method;
+                        break;
+                    }
+                }
+            }
+            return foundMethod;
+        }
+
+        /* (non-Javadoc)
+           * @see groovy.lang.GroovyObjectSupport#getProperty(java.lang.String)
+           */
+
+        public Object getProperty(String property) {
+            this.propertyName = property;
+            return this;
+        }
+        /* (non-Javadoc)
+           * @see groovy.lang.GroovyObjectSupport#setProperty(java.lang.String, java.lang.Object)
+           */
+
+        public void setProperty(String property, Object newValue) {
+            this.propertyName = property;
+            registerIfClosure(newValue, true);
+        }
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.MetaClassImpl#invokeConstructor(java.lang.Object[])
+      */
+
+    public Object invokeConstructor(Object[] arguments) {
+
+        // TODO This is the only area where this MetaClass needs to do some interception because Groovy's current
+        // MetaClass uses hard coded references to the java.lang.reflect.Constructor class so you can't simply
+        // inject Constructor like you can do properties, methods and fields. When Groovy's MetaClassImpl is
+        // refactored we can fix this
+        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, argClasses);
+        if (method != null && method.getParameterTypes().length == arguments.length) {
+            return method.invoke(theClass, arguments);
+        }
+        return super.invokeConstructor(arguments);
+    }
+
+    /**
+     * Handles the ability to use the left shift operator to append new constructors
+     *
+     * @author Graeme Rocher
+     */
+    protected class ExpandoMetaConstructor extends GroovyObjectSupport {
+        public Object leftShift(Closure c) {
+            if (c != null) {
+                final List<MetaMethod> list = ClosureMetaMethod.createMethodList(GROOVY_CONSTRUCTOR, theClass, c);
+                for (MetaMethod method : list) {
+                    Class[] paramTypes = method.getNativeParameterTypes();
+                    Constructor ctor = retrieveConstructor(paramTypes);
+                    if (ctor != null)
+                        throw new GroovyRuntimeException("Cannot add new constructor for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
+
+                    registerInstanceMethod(method);
+                }
+            }
+
+            return this;
+        }
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.GroovyObject#getMetaClass()
+      */
+
+    public MetaClass getMetaClass() {
+        return myMetaClass;
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
+      */
+
+    public Object getProperty(String property) {
+        if (isValidExpandoProperty(property)) {
+            if (property.equals(STATIC_QUALIFIER)) {
+                return new ExpandoMetaProperty(property, true);
+            } else if (property.equals(CONSTRUCTOR)) {
+                return new ExpandoMetaConstructor();
+            } else {
+                if (myMetaClass.hasProperty(this, property) == null)
+                    return new ExpandoMetaProperty(property);
+                else
+                    return myMetaClass.getProperty(this, property);
+            }
+        } else {
+            return myMetaClass.getProperty(this, property);
+        }
+    }
+
+    public static boolean isValidExpandoProperty(String property) {
+        return !(property.equals(META_CLASS) || property.equals(CLASS) || property.equals(META_METHODS) || property.equals(METHODS) || property.equals(PROPERTIES));
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
+      */
+
+    public Object invokeMethod(String name, Object args) {
+        final Object[] argsArr = args instanceof Object[] ? (Object[]) args : new Object[]{args};
+        MetaMethod metaMethod = myMetaClass.getMetaMethod(name, argsArr);
+        if (metaMethod != null) {
+            // we have to use doMethodInvoke here instead of simply invoke,
+            // because getMetaMethod may provide a method that can not be called
+            // without further argument transformation, which is done only in 
+            // doMethodInvoke
+            return metaMethod.doMethodInvoke(this, argsArr);
+        }
+
+        if (argsArr.length == 2 && argsArr[0] instanceof Class && argsArr[1] instanceof Closure) {
+            if (argsArr[0] == theClass)
+                registerInstanceMethod(name, (Closure) argsArr[1]);
+            else {
+                registerSubclassInstanceMethod(name, (Class) argsArr[0], (Closure) argsArr[1]);
+            }
+            return null;
+        }
+
+        if (argsArr.length == 1 && argsArr[0] instanceof Closure) {
+            registerInstanceMethod(name, (Closure) argsArr[0]);
+            return null;
+        }
+
+        throw new MissingMethodException(name, getClass(), argsArr);
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.GroovyObject#setMetaClass(groovy.lang.MetaClass)
+      */
+
+    public void setMetaClass(MetaClass metaClass) {
+        this.myMetaClass = metaClass;
+    }
+
+    /* (non-Javadoc)
+      * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
+      */
+
+    public void setProperty(String property, Object newValue) {
+        if (newValue instanceof Closure) {
+            if (property.equals(CONSTRUCTOR)) {
+                property = GROOVY_CONSTRUCTOR;
+            }
+            Closure callable = (Closure) newValue;
+            final List<MetaMethod> list = ClosureMetaMethod.createMethodList(property, theClass, callable);
+            for (MetaMethod method : list) {
+                // here we don't care if the method exists or not we assume the
+                // developer is responsible and wants to override methods where necessary
+                registerInstanceMethod(method);
+            }
+        } else {
+            registerBeanProperty(property, newValue);
+        }
+    }
+
+    public ExpandoMetaClass define(Closure closure) {
+        final DefiningClosure definer = new DefiningClosure();
+        Object delegate = closure.getDelegate();
+        closure.setDelegate(definer);
+        closure.setResolveStrategy(Closure.DELEGATE_ONLY);
+        closure.call((Object)null);
+        closure.setDelegate(delegate);
+        closure.setResolveStrategy(Closure.DELEGATE_FIRST);
+        definer.definition = false;
+        return this;
+    }
+
+    protected synchronized void performOperationOnMetaClass(Callable c) {
+        try {
+            writeLock.lock();
+            if (allowChangesAfterInit) {
+                setInitialized(false);
+            }
+            c.call();
+        }
+        finally {
+            if (initCalled) {
+                setInitialized(true);
+            }
+            // downgrade to readlock before releasing just in case
+            readLock.lock();
+            writeLock.unlock();
+            readLock.unlock();
+        }
+    }
+    
+    protected void checkInitalised() {
+        try {
+            readLock.lock();
+            super.checkInitalised();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Registers a new bean property
+     *
+     * @param property The property name
+     * @param newValue The properties initial value
+     */
+    public void registerBeanProperty(final String property, final Object newValue) {
+        performOperationOnMetaClass(new Callable() {
+            public void call() {
+                Class type = newValue == null ? Object.class : newValue.getClass();
+
+                MetaBeanProperty mbp = newValue instanceof MetaBeanProperty ? (MetaBeanProperty) newValue : new ThreadManagedMetaBeanProperty(theClass, property, type, newValue);
+
+                final MetaMethod getter = mbp.getGetter();
+                final MethodKey getterKey = new DefaultCachedMethodKey(theClass, getter.getName(), CachedClass.EMPTY_ARRAY, false);
+                final MetaMethod setter = mbp.getSetter();
+                final MethodKey setterKey = new DefaultCachedMethodKey(theClass, setter.getName(), setter.getParameterTypes(), false);
+                addMetaMethod(getter);
+                addMetaMethod(setter);
+
+                expandoMethods.put(setterKey, setter);
+                expandoMethods.put(getterKey, getter);
+                expandoProperties.put(mbp.getName(), mbp);
+
+                addMetaBeanProperty(mbp);
+                performRegistryCallbacks();
+            }
+
+        });
+    }
+
+    /**
+     * Registers a new instance method for the given method name and closure on this MetaClass
+     *
+     * @param metaMethod
+     */
+    public void registerInstanceMethod(final MetaMethod metaMethod) {
+        final boolean inited = this.initCalled;
+        performOperationOnMetaClass(new Callable() {
+            public void call() {
+                String methodName = metaMethod.getName();
+                checkIfGroovyObjectMethod(metaMethod);
+                MethodKey key = new DefaultCachedMethodKey(theClass, methodName, metaMethod.getParameterTypes(), false);
+
+                if (isInitialized()) {
+                    throw new RuntimeException("Already initialized, cannot add new method: " + metaMethod);
+                }
+                // we always adds meta methods to class itself
+                addMetaMethodToIndex(metaMethod, metaMethodIndex.getHeader(theClass));
+
+                dropMethodCache(methodName);
+                expandoMethods.put(key, metaMethod);
+
+                if (inited && isGetter(methodName, metaMethod.getParameterTypes())) {
+                    String propertyName = getPropertyForGetter(methodName);
+                    registerBeanPropertyForMethod(metaMethod, propertyName, true, false);
+
+                } else if (inited && isSetter(methodName, metaMethod.getParameterTypes())) {
+                    String propertyName = getPropertyForSetter(methodName);
+                    registerBeanPropertyForMethod(metaMethod, propertyName, false, false);
+                }
+                performRegistryCallbacks();
+            }
+
+        });
+    }
+
+    public void registerInstanceMethod(String name, Closure closure) {
+        final List<MetaMethod> list = ClosureMetaMethod.createMethodList(name, theClass, closure);
+        for (MetaMethod method : list) {
+            registerInstanceMethod(method);
+        }
+    }
+
+    /**
+     * Overrides the behavior of parent getMethods() method to make MetaClass aware of added Expando methods
+     *
+     * @return A list of MetaMethods
+     * @see MetaObjectProtocol#getMethods()
+     */
+    public List<MetaMethod> getMethods() {
+        List<MetaMethod> methodList = new ArrayList<MetaMethod>();
+        methodList.addAll(this.expandoMethods.values());
+        methodList.addAll(super.getMethods());
+        return methodList;
+    }
+
+    public List<MetaProperty> getProperties() {
+        List<MetaProperty> propertyList = new ArrayList<MetaProperty>();
+        propertyList.addAll(super.getProperties());
+        return propertyList;
+    }
+
+
+    private void performRegistryCallbacks() {
+        MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
+        incVersion();
+        if (!modified) {
+            modified = true;
+            // Implementation note: By default Groovy uses soft references to store MetaClass
+            // this insures the registry doesn't grow and get out of hand. By doing this we're
+            // saying this this EMC will be a hard reference in the registry. As we're only
+            // going have a small number of classes that have modified EMC this is ok
+            if (inRegistry) {
+                MetaClass currMetaClass = registry.getMetaClass(theClass);
+                if (!(currMetaClass instanceof ExpandoMetaClass) && currMetaClass instanceof AdaptingMetaClass) {
+                    ((AdaptingMetaClass) currMetaClass).setAdaptee(this);
+                } else {
+                    registry.setMetaClass(theClass, this);
+                }
+            }
+
+        }
+    }
+
+    private void registerBeanPropertyForMethod(MetaMethod metaMethod, String propertyName, boolean getter, boolean isStatic) {
+        Map<String, MetaProperty> propertyCache = isStatic ? staticBeanPropertyCache : beanPropertyCache;
+        MetaBeanProperty beanProperty = (MetaBeanProperty) propertyCache.get(propertyName);
+        if (beanProperty==null) {
+            MetaProperty metaProperty = super.getMetaProperty(propertyName);
+            if (metaProperty instanceof MetaBeanProperty) {
+                boolean staticProp = Modifier.isStatic(metaProperty.getModifiers());
+                if (isStatic==staticProp) {
+                    beanProperty = (MetaBeanProperty) metaProperty;
+                }
+            }
+        }
+        if (beanProperty == null) {
+            if (getter)
+                beanProperty = new MetaBeanProperty(propertyName, Object.class, metaMethod, null);
+            else
+                beanProperty = new MetaBeanProperty(propertyName, Object.class, null, metaMethod);
+
+            propertyCache.put(propertyName, beanProperty);
+        } else {
+            if (getter) {
+                MetaMethod setterMethod = beanProperty.getSetter();
+                Class type = setterMethod != null ? setterMethod.getParameterTypes()[0].getTheClass() : Object.class;
+                beanProperty = new MetaBeanProperty(propertyName, type, metaMethod, setterMethod);
+                propertyCache.put(propertyName, beanProperty);
+            } else {
+                MetaMethod getterMethod = beanProperty.getGetter();
+                beanProperty = new MetaBeanProperty(propertyName, metaMethod.getParameterTypes()[0].getTheClass(), getterMethod, metaMethod);
+                propertyCache.put(propertyName, beanProperty);
+            }
+        }
+        expandoProperties.put(beanProperty.getName(), beanProperty);
+        addMetaBeanProperty(beanProperty);
+    }
+
+    protected void registerStaticMethod(final String name, final Closure callable) {
+        registerStaticMethod(name, callable, null);
+    }
+
+    /**
+     * Registers a new static method for the given method name and closure on this MetaClass
+     *
+     * @param name     The method name
+     * @param callable The callable Closure
+     */
+    protected void registerStaticMethod(final String name, final Closure callable, final Class[] paramTypes) {
+        performOperationOnMetaClass(new Callable() {
+            public void call() {
+                String methodName;
+                if (name.equals(METHOD_MISSING))
+                    methodName = STATIC_METHOD_MISSING;
+                else if (name.equals(PROPERTY_MISSING))
+                    methodName = STATIC_PROPERTY_MISSING;
+                else
+                    methodName = name;
+
+                ClosureStaticMetaMethod metaMethod = null;
+
+                if (paramTypes != null) {
+                    metaMethod = new ClosureStaticMetaMethod(methodName, theClass, callable, paramTypes);
+                } else {
+                    metaMethod = new ClosureStaticMetaMethod(methodName, theClass, callable);
+                }
+
+                if (methodName.equals(INVOKE_METHOD_METHOD) && callable.getParameterTypes().length == 2) {
+                    invokeStaticMethodMethod = metaMethod;
+                } else {
+                    if (methodName.equals(METHOD_MISSING)) {
+                        methodName = STATIC_METHOD_MISSING;
+                    }
+                    MethodKey key = new DefaultCachedMethodKey(theClass, methodName, metaMethod.getParameterTypes(), false);
+
+                    addMetaMethod(metaMethod);
+                    dropStaticMethodCache(methodName);
+//                    cacheStaticMethod(key,metaMethod);
+
+                    if (isGetter(methodName, metaMethod.getParameterTypes())) {
+                        String propertyName = getPropertyForGetter(methodName);
+                        registerBeanPropertyForMethod(metaMethod, propertyName, true, true);
+
+                    } else if (isSetter(methodName, metaMethod.getParameterTypes())) {
+                        String propertyName = getPropertyForSetter(methodName);
+                        registerBeanPropertyForMethod(metaMethod, propertyName, false, true);
+                    }
+                    performRegistryCallbacks();
+                    expandoMethods.put(key, metaMethod);
+                }
+            }
+
+        });
+    }
+
+    protected Object getSubclassMetaMethods(String methodName) {
+        if (!isModified())
+            return null;
+
+        return expandoSubclassMethods.get(methodName);
+    }
+
+    /**
+     * @return The Java class enhanced by this MetaClass
+     */
+    public Class getJavaClass() {
+        return theClass;
+    }
+
+    /**
+     * Called from ExpandoMetaClassCreationHandle in the registry if it exists to
+     * set up inheritance handling
+     *
+     * @param modifiedSuperExpandos A list of modified super ExpandoMetaClass
+     */
+    public void refreshInheritedMethods(Set modifiedSuperExpandos) {
+        for (Iterator i = modifiedSuperExpandos.iterator(); i.hasNext();) {
+            ExpandoMetaClass superExpando = (ExpandoMetaClass) i.next();
+            if (superExpando != this) {
+                refreshInheritedMethods(superExpando);
+            }
+        }
+    }
+
+    private void refreshInheritedMethods(ExpandoMetaClass superExpando) {
+        List<MetaMethod> metaMethods = superExpando.getExpandoMethods();
+        for (MetaMethod metaMethod : metaMethods) {
+            if (metaMethod.isStatic()) {
+                if (superExpando.getTheClass() != getTheClass())
+                    continue; // don't inherit static methods except our own
+                registerStaticMethod(metaMethod.getName(), (Closure) ((ClosureStaticMetaMethod) metaMethod).getClosure().clone());
+            } else
+                addSuperMethodIfNotOverridden(metaMethod);
+        }
+        Collection<MetaProperty> metaProperties = superExpando.getExpandoProperties();
+        for (Object metaProperty : metaProperties) {
+            MetaBeanProperty property = (MetaBeanProperty) metaProperty;
+            expandoProperties.put(property.getName(), property);
+            addMetaBeanProperty(property);
+        }
+    }
+
+
+    /**
+     * Returns a list of expando MetaMethod instances added to this ExpandoMetaClass
+     *
+     * @return the expandoMethods
+     */
+    public List<MetaMethod> getExpandoMethods() {
+        return Collections.unmodifiableList(DefaultGroovyMethods.toList(expandoMethods.values()));
+    }
+
+
+    /**
+     * Returns a list of MetaBeanProperty instances added to this ExpandoMetaClass
+     *
+     * @return the expandoProperties
+     */
+    public Collection<MetaProperty> getExpandoProperties() {
+        return Collections.unmodifiableCollection(expandoProperties.values());
+    }
+
+    /**
+     * Overrides default implementation just in case invokeMethod has been overridden by ExpandoMetaClass
+     *
+     * @see groovy.lang.MetaClassImpl#invokeMethod(Class, Object, String, Object[], boolean, boolean)
+     */
+    public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
+        if (invokeMethodMethod != null) {
+            MetaClassHelper.unwrap(originalArguments);
+            return invokeMethodMethod.invoke(object, new Object[]{methodName, originalArguments});
+        }
+        return super.invokeMethod(sender, object, methodName, originalArguments, isCallToSuper, fromInsideClass);
+    }
+
+    /**
+     * Overrides default implementation just in case a static invoke method has been set on ExpandoMetaClass
+     *
+     * @see MetaClassImpl#invokeStaticMethod(Object, String, Object[])
+     */
+    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
+        if (invokeStaticMethodMethod != null) {
+            MetaClassHelper.unwrap(arguments);
+            return invokeStaticMethodMethod.invoke(object, new Object[]{methodName, arguments});
+        }
+        return super.invokeStaticMethod(object, methodName, arguments);
+    }
+
+    /**
+     * Overrides default implementation just in case getProperty method has been overridden by ExpandoMetaClass
+     *
+     * @see MetaClassImpl#getProperty(Class, Object, String, boolean, boolean)
+     */
+    public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {
+        if (hasOverrideGetProperty(name) && getJavaClass().isInstance(object)) {
+            return getPropertyMethod.invoke(object, new Object[]{name});
+        }
+
+        if ("mixedIn".equals(name)) {
+            return new MixedInAccessor(object, mixinClasses);
+        }
+
+        return super.getProperty(sender, object, name, useSuper, fromInsideClass);
+    }
+
+    /**
+     * Overrides default implementation just in case getProperty method has been overridden by ExpandoMetaClass
+     *
+     * @see MetaClassImpl#getProperty(Object, String)
+     */
+    public Object getProperty(Object object, String name) {
+        if (hasOverrideGetProperty(name) && getJavaClass().isInstance(object)) {
+            return getPropertyMethod.invoke(object, new Object[]{name});
+        }
+        return super.getProperty(object, name);
+    }
+
+    private boolean hasOverrideGetProperty(String name) {
+        return getPropertyMethod != null && !name.equals(META_CLASS_PROPERTY) && !name.equals(CLASS_PROPERTY);
+    }
+
+    /**
+     * Overrides default implementation just in case setProperty method has been overridden by ExpandoMetaClass
+     *
+     * @see MetaClassImpl#setProperty(Class, Object, String, Object, boolean, boolean)
+     */
+
+    public void setProperty(Class sender, Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
+        if (setPropertyMethod != null && !name.equals(META_CLASS_PROPERTY) && getJavaClass().isInstance(object)) {
+            setPropertyMethod.invoke(object, new Object[]{name, newValue});
+            return;
+        }
+        super.setProperty(sender, object, name, newValue, useSuper, fromInsideClass);
+    }
+
+    /**
+     * Looks up an existing MetaProperty by name
+     *
+     * @param name The name of the MetaProperty
+     * @return The MetaProperty or null if it doesn't exist
+     */
+    public MetaProperty getMetaProperty(String name) {
+        MetaProperty mp = this.expandoProperties.get(name);
+        if (mp != null) return mp;
+        return super.getMetaProperty(name);
+    }
+
+    /**
+     * Returns true if the MetaClass has the given property
+     *
+     * @param name The name of the MetaProperty
+     * @return True it exists as a MetaProperty
+     */
+    public boolean hasMetaProperty(String name) {
+        return getMetaProperty(name) != null;
+    }
+
+    /**
+     * Checks whether a MetaMethod for the given name and arguments exists
+     *
+     * @param name The name of the MetaMethod
+     * @param args The arguments to the meta method
+     * @return True if the method exists otherwise null
+     */
+    public boolean hasMetaMethod(String name, Class[] args) {
+        return super.pickMethod(name, args) != null;
+    }
+
+    /**
+     * Determine if this method name suffix is a legitimate bean property name.
+     * Either the first or second letter must be upperCase for that to be true.
+     */
+    private static boolean isPropertyName(String name) {
+        return ((name.length() > 0) && Character.isUpperCase(name.charAt(0))) || ((name.length() > 1) && Character.isUpperCase(name.charAt(1)));
+    }
+
+    /**
+     * Returns true if the name of the method specified and the number of arguments make it a javabean property
+     *
+     * @param name True if its a Javabean property
+     * @param args The arguments
+     * @return True if it is a javabean property method
+     */
+    private boolean isGetter(String name, CachedClass[] args) {
+        if (name == null || name.length() == 0 || args == null) return false;
+        if (args.length != 0) return false;
+
+        if (name.startsWith("get")) {
+            name = name.substring(3);
+            return isPropertyName(name);
+        } else if (name.startsWith("is")) {
+            name = name.substring(2);
+            return isPropertyName(name);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a property name equivalent for the given getter name or null if it is not a getter
+     *
+     * @param getterName The getter name
+     * @return The property name equivalent
+     */
+    private String getPropertyForGetter(String getterName) {
+        if (getterName == null || getterName.length() == 0) return null;
+
+        if (getterName.startsWith("get")) {
+            String prop = getterName.substring(3);
+            return MetaClassHelper.convertPropertyName(prop);
+        } else if (getterName.startsWith("is")) {
+            String prop = getterName.substring(2);
+            return MetaClassHelper.convertPropertyName(prop);
+        }
+        return null;
+    }
+
+    /**
+     * Returns a property name equivalent for the given setter name or null if it is not a getter
+     *
+     * @param setterName The setter name
+     * @return The property name equivalent
+     */
+    public String getPropertyForSetter(String setterName) {
+        if (setterName == null || setterName.length() == 0) return null;
+
+        if (setterName.startsWith("set")) {
+            String prop = setterName.substring(3);
+            return MetaClassHelper.convertPropertyName(prop);
+        }
+        return null;
+    }
+
+    public boolean isSetter(String name, CachedClass[] args) {
+        if (name == null || name.length() == 0 || args == null) return false;
+
+        if (name.startsWith("set")) {
+            if (args.length != 1) return false;
+            name = name.substring(3);
+            return isPropertyName(name);
+        }
+
+        return false;
+    }
+
+    public CallSite createPojoCallSite(CallSite site, Object receiver, Object[] args) {
+        if (invokeMethodMethod != null)
+            return new PojoMetaClassSite(site, this);
+
+        return super.createPojoCallSite(site, receiver, args);
+    }
+
+    public CallSite createStaticSite(CallSite site, Object[] args) {
+        if (invokeStaticMethodMethod != null)
+            return new StaticMetaClassSite(site, this);
+
+        return super.createStaticSite(site, args);
+    }
+
+    public boolean hasCustomStaticInvokeMethod() {return invokeStaticMethodMethod!=null; }
+
+    public CallSite createPogoCallSite(CallSite site, Object[] args) {
+        if (invokeMethodMethod != null)
+            return new PogoMetaClassSite(site, this);
+        return super.createPogoCallSite(site, args);
+    }
+
+    public CallSite createPogoCallCurrentSite(CallSite site, Class sender, String name, Object[] args) {
+        if (invokeMethodMethod != null)
+            return new PogoMetaClassSite(site, this);
+        return super.createPogoCallCurrentSite(site, sender, args);
+    }
+    
+    @Override
+    public MetaMethod retrieveConstructor(Object[] args) {
+        Class[] params = MetaClassHelper.convertToTypeArray(args);
+        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, params);
+        if (method!=null) return method;
+        return super.retrieveConstructor(args);
+    }
+
+    public CallSite createConstructorSite(CallSite site, Object[] args) {
+        Class[] params = MetaClassHelper.convertToTypeArray(args);
+        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, params);
+        if (method != null && method.getParameterTypes().length == args.length) {
+            if (method.getDeclaringClass().getTheClass().equals(getTheClass())) {
+                return new ConstructorMetaMethodSite(site, this, method, params);
+            }
+        }
+
+        return super.createConstructorSite(site, args);
+    }
+
+    private class SubClassDefiningClosure extends GroovyObjectSupport {
+        private final Class klazz;
+
+        public SubClassDefiningClosure(Class klazz) {
+            this.klazz = klazz;
+        }
+
+        public Object invokeMethod(String name, Object obj) {
+            if (obj instanceof Object[]) {
+                Object args[] = (Object[]) obj;
+                if (args.length == 1 && args[0] instanceof Closure) {
+                    registerSubclassInstanceMethod(name, klazz, (Closure) args[0]);
+                    return null;
+                }
+            }
+
+            throw new MissingMethodException(name, getClass(), new Object[]{obj});
+        }
+    }
+
+    private class DefiningClosure extends GroovyObjectSupport {
+        boolean definition = true;
+
+        public void mixin(Class category) {
+            mixin(Collections.singletonList(category));
+        }
+
+        public void mixin(List categories) {
+            DefaultGroovyMethods.mixin(ExpandoMetaClass.this, categories);
+        }
+
+        public void mixin(Class[] categories) {
+            DefaultGroovyMethods.mixin(ExpandoMetaClass.this, categories);
+        }
+
+        public void define(Class subClass, Closure closure) {
+            final SubClassDefiningClosure definer = new SubClassDefiningClosure(subClass);
+            closure.setDelegate(definer);
+            closure.setResolveStrategy(Closure.DELEGATE_FIRST);
+            closure.call((Object)null);
+        }
+
+        public Object invokeMethod(String name, Object obj) {
+            try {
+                return getMetaClass().invokeMethod(this, name, obj);
+            }
+            catch (MissingMethodException mme) {
+                if (obj instanceof Object[]) {
+                    if (STATIC_QUALIFIER.equals(name)) {
+                        final StaticDefiningClosure staticDef = new StaticDefiningClosure();
+                        Closure c = (Closure) ((Object[]) obj)[0];
+                        c.setDelegate(staticDef);
+                        c.setResolveStrategy(Closure.DELEGATE_ONLY);
+                        c.call((Object)null);
+                        return null;
+                    }
+                    Object args[] = (Object[]) obj;
+                    if (args.length == 1 && args[0] instanceof Closure) {
+                        registerInstanceMethod(name, (Closure) args[0]);
+                    } else if (args.length == 2 && args[0] instanceof Class && args[1] instanceof Closure)
+                        registerSubclassInstanceMethod(name, (Class) args[0], (Closure) args[1]);
+                    else
+                        ExpandoMetaClass.this.setProperty(name, ((Object[]) obj)[0]);
+
+                    return null;
+                }
+
+                throw mme;
+            }
+        }
+
+        public void setProperty(String property, Object newValue) {
+            ExpandoMetaClass.this.setProperty(property, newValue);
+        }
+
+        public Object getProperty(String property) {
+            if (STATIC_QUALIFIER.equals(property))
+                return new StaticDefiningClosure();
+
+            if (definition)
+                return new ExpandoMetaProperty(property);
+            else
+                throw new MissingPropertyException(property, getClass());
+        }
+    }
+
+    private class StaticDefiningClosure extends ExpandoMetaProperty {
+        protected StaticDefiningClosure() {
+            super(STATIC_QUALIFIER, true);
+        }
+
+        public Object invokeMethod(String name, Object obj) {
+            if (obj instanceof Object[]) {
+                final Object[] args = (Object[]) obj;
+                if (args.length == 1 && args[0] instanceof Closure) {
+                    registerStaticMethod(name, (Closure) args[0]);
+                    return null;
+                }
+            }
+
+            throw new MissingMethodException(name, getClass(), obj instanceof Object[] ? (Object[]) obj : new Object[]{obj});
+        }
+    }
+
+    private static class MixedInAccessor {
+        private final Object object;
+        private final Set<MixinInMetaClass> mixinClasses;
+
+        public MixedInAccessor(Object object, Set<MixinInMetaClass> mixinClasses) {
+            this.object = object;
+            this.mixinClasses = mixinClasses;
+        }
+
+        public Object getAt(Class key) {
+            if (key.isAssignableFrom(object.getClass())) {
+                return new GroovyObjectSupport() {
+                    {
+                        final MetaClass ownMetaClass = InvokerHelper.getMetaClass(object.getClass());
+                        setMetaClass(new OwnedMetaClass(ownMetaClass) {
+                            protected Object getOwner() {
+                                return object;
+                            }
+
+                            protected MetaClass getOwnerMetaClass(Object owner) {
+                                return getAdaptee();
+                            }
+                        });
+                    }
+                };
+            }
+
+            for (final MixinInMetaClass mixin : mixinClasses) {
+                if (key.isAssignableFrom(mixin.getMixinClass().getTheClass())) {
+                    return new GroovyObjectSupport() {
+                        {
+                            final Object mixedInInstance = mixin.getMixinInstance(object);
+                            setMetaClass(new OwnedMetaClass(InvokerHelper.getMetaClass(mixedInInstance)) {
+                                @Override
+                                protected Object getOwner() {
+                                    return mixedInInstance;
+                                }
+
+                                @Override
+                                protected MetaClass getOwnerMetaClass(Object owner) {
+                                    return ((MixedInMetaClass) getAdaptee()).getAdaptee();
+                                }
+                            });
+                        }
+                    };
+                }
+            }
+
+            throw new RuntimeException("Class " + key + " isn't mixed in " + object.getClass());
+        }
+
+        public void putAt(Class key, Object value) {
+            for (MixinInMetaClass mixin : mixinClasses)
+                if (mixin.getMixinClass().getTheClass() == key) {
+                    mixin.setMixinInstance(object, value);
+                    return;
+                }
+
+            throw new RuntimeException("Class " + key + " isn't mixed in " + object.getClass());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ExpandoMetaClassCreationHandle.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ExpandoMetaClassCreationHandle.java b/src/main/groovy/groovy/lang/ExpandoMetaClassCreationHandle.java
new file mode 100644
index 0000000..6e411a5
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ExpandoMetaClassCreationHandle.java
@@ -0,0 +1,95 @@
+/*
+ *  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 groovy.lang;
+
+import groovy.lang.MetaClassRegistry.MetaClassCreationHandle;
+import org.codehaus.groovy.reflection.ClassInfo;
+
+/**
+ * <p>A handle for the MetaClassRegistry that changes all classes loaded into the Grails VM
+ * to use ExpandoMetaClass instances
+ *
+ * <p>The handle should be registered with the Groovy runtime <strong>before</strong> Groovy loads, for example
+ * in your main method.
+ *
+ * <code>GroovySystem.metaClassRegistry.metaClassCreationHandle = new ExpandoMetaClassCreationHandle()</code>
+ *
+ * @see groovy.lang.MetaClassRegistry
+ * @see groovy.lang.MetaClassRegistry.MetaClassCreationHandle
+ * @see org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl#setMetaClassCreationHandle(groovy.lang.MetaClassRegistry.MetaClassCreationHandle)
+ *
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public class ExpandoMetaClassCreationHandle extends MetaClassCreationHandle {
+
+    public static final ExpandoMetaClassCreationHandle instance = new ExpandoMetaClassCreationHandle();
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClassRegistry.MetaClassCreationHandle#create(java.lang.Class, groovy.lang.MetaClassRegistry)
+     */
+    protected MetaClass createNormalMetaClass(Class theClass, MetaClassRegistry registry) {
+        if(theClass != ExpandoMetaClass.class) {
+            return new ExpandoMetaClass(theClass, true, true);
+        }
+        else {
+            return super.createNormalMetaClass(theClass, registry);
+        }
+    }
+
+    /**
+     * Registers a modified ExpandoMetaClass with the creation handle
+     *
+     * @param emc The EMC
+     */
+    public void registerModifiedMetaClass(ExpandoMetaClass emc) {
+        final Class klazz = emc.getJavaClass();
+        GroovySystem.getMetaClassRegistry().setMetaClass(klazz,emc);
+    }
+
+    public boolean hasModifiedMetaClass(ExpandoMetaClass emc) {
+        return emc.getClassInfo().getModifiedExpando() != null;
+    }
+
+    /**
+     * <p>Enables the ExpandoMetaClassCreationHandle with the registry
+     *
+     * <code>ExpandoMetaClassCreationHandle.enable();</code>
+     *
+     */
+    public static void enable() {
+        final MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
+        synchronized (metaClassRegistry) {
+            if (metaClassRegistry.getMetaClassCreationHandler() != instance) {
+                ClassInfo.clearModifiedExpandos();
+                metaClassRegistry.setMetaClassCreationHandle(instance);
+            }
+        }
+    }
+
+    public static void disable() {
+        final MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
+        synchronized (metaClassRegistry) {
+            if (metaClassRegistry.getMetaClassCreationHandler() == instance) {
+                ClassInfo.clearModifiedExpandos();
+                metaClassRegistry.setMetaClassCreationHandle(new MetaClassCreationHandle());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GString.java b/src/main/groovy/groovy/lang/GString.java
new file mode 100644
index 0000000..8323bf2
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GString.java
@@ -0,0 +1,245 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.GStringImpl;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Represents a String which contains embedded values such as "hello there
+ * ${user} how are you?" which can be evaluated lazily. Advanced users can
+ * iterate over the text and values to perform special processing, such as for
+ * performing SQL operations, the values can be substituted for ? and the
+ * actual value objects can be bound to a JDBC statement. The lovely name of
+ * this class was suggested by Jules Gosnell and was such a good idea, I
+ * couldn't resist :)
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public abstract class GString extends GroovyObjectSupport implements Comparable, CharSequence, Writable, Buildable, Serializable {
+
+    static final long serialVersionUID = -2638020355892246323L;
+
+    /**
+     * A GString containing a single empty String and no values.
+     */
+    public static final GString EMPTY = new GString(new Object[0]) {
+        @Override
+        public String[] getStrings() {
+            return new String[]{""};
+        }
+    };
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
+    private final Object[] values;
+
+    public GString(Object values) {
+        this.values = (Object[]) values;
+    }
+
+    public GString(Object[] values) {
+        this.values = values;
+    }
+
+    // will be static in an instance
+
+    public abstract String[] getStrings();
+
+    /**
+     * Overloaded to implement duck typing for Strings
+     * so that any method that can't be evaluated on this
+     * object will be forwarded to the toString() object instead.
+     */
+    @Override
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return super.invokeMethod(name, args);
+        }
+        catch (MissingMethodException e) {
+            // lets try invoke the method on the real String
+            return InvokerHelper.invokeMethod(toString(), name, args);
+        }
+    }
+
+    public Object[] getValues() {
+        return values;
+    }
+
+    public GString plus(GString that) {
+        List<String> stringList = new ArrayList<String>(Arrays.asList(getStrings()));
+        List<Object> valueList = new ArrayList<Object>(Arrays.asList(getValues()));
+
+        List<String> thatStrings = Arrays.asList(that.getStrings());
+
+        int stringListSize = stringList.size();
+        if (stringListSize > valueList.size()) {
+            thatStrings = new ArrayList<String>(thatStrings);
+            // merge onto end of previous GString to avoid an empty bridging value
+            int lastIndexOfStringList = stringListSize - 1;
+            String s = stringList.get(lastIndexOfStringList);
+            s += thatStrings.remove(0);
+            stringList.set(lastIndexOfStringList, s);
+        }
+
+        stringList.addAll(thatStrings);
+        valueList.addAll(Arrays.asList(that.getValues()));
+
+        final String[] newStrings = stringList.toArray(EMPTY_STRING_ARRAY);
+        final Object[] newValues = valueList.toArray();
+
+        return new GStringImpl(newValues, newStrings);
+    }
+
+    public GString plus(String that) {
+        return plus(new GStringImpl(EMPTY_OBJECT_ARRAY, new String[] { that }));
+    }
+
+    public int getValueCount() {
+        return values.length;
+    }
+
+    public Object getValue(int idx) {
+        return values[idx];
+    }
+
+    @Override
+    public String toString() {
+        StringWriter buffer = new StringWriter();
+        try {
+            writeTo(buffer);
+        }
+        catch (IOException e) {
+            throw new StringWriterIOException(e);
+        }
+        return buffer.toString();
+    }
+
+    @Override
+    public Writer writeTo(Writer out) throws IOException {
+        String[] s = getStrings();
+        int numberOfValues = values.length;
+        for (int i = 0, size = s.length; i < size; i++) {
+            out.write(s[i]);
+            if (i < numberOfValues) {
+                final Object value = values[i];
+
+                if (value instanceof Closure) {
+                    final Closure c = (Closure) value;
+
+                    if (c.getMaximumNumberOfParameters() == 0) {
+                        InvokerHelper.write(out, c.call());
+                    } else if (c.getMaximumNumberOfParameters() == 1) {
+                        c.call(out);
+                    } else {
+                        throw new GroovyRuntimeException("Trying to evaluate a GString containing a Closure taking "
+                                + c.getMaximumNumberOfParameters() + " parameters");
+                    }
+                } else {
+                    InvokerHelper.write(out, value);
+                }
+            }
+        }
+        return out;
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.Buildable#build(groovy.lang.GroovyObject)
+     */
+
+    @Override
+    public void build(final GroovyObject builder) {
+        final String[] s = getStrings();
+        final int numberOfValues = values.length;
+
+        for (int i = 0, size = s.length; i < size; i++) {
+            builder.getProperty("mkp");
+            builder.invokeMethod("yield", new Object[]{s[i]});
+            if (i < numberOfValues) {
+                builder.getProperty("mkp");
+                builder.invokeMethod("yield", new Object[]{values[i]});
+            }
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return 37 + toString().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        if (that instanceof GString) {
+            return equals((GString) that);
+        }
+        return false;
+    }
+
+    public boolean equals(GString that) {
+        return toString().equals(that.toString());
+    }
+
+    @Override
+    public int compareTo(Object that) {
+        return toString().compareTo(that.toString());
+    }
+
+    @Override
+    public char charAt(int index) {
+        return toString().charAt(index);
+    }
+
+    @Override
+    public int length() {
+        return toString().length();
+    }
+
+    @Override
+    public CharSequence subSequence(int start, int end) {
+        return toString().subSequence(start, end);
+    }
+
+    /**
+     * Turns a String into a regular expression pattern
+     *
+     * @return the regular expression pattern
+     */
+    public Pattern negate() {
+        return StringGroovyMethods.bitwiseNegate(toString());
+    }
+
+    public byte[] getBytes() {
+        return toString().getBytes();
+    }
+
+    public byte[] getBytes(String charset) throws UnsupportedEncodingException {
+       return toString().getBytes(charset);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GeneratedGroovyProxy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GeneratedGroovyProxy.java b/src/main/groovy/groovy/lang/GeneratedGroovyProxy.java
new file mode 100644
index 0000000..55b25b5
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GeneratedGroovyProxy.java
@@ -0,0 +1,34 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * An interface implemented by some Groovy proxies which gives access to the proxied object. In particular, dynamically
+ * generated proxies that implement traits will implement this interface in order to give access to the proxied
+ * instance.
+ *
+ * @author Cedric Champeau
+ * @since 2.3.0
+ */
+public interface GeneratedGroovyProxy {
+    /**
+     * @return the proxy target.
+     */
+    Object getProxyTarget();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Grab.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Grab.java b/src/main/groovy/groovy/lang/Grab.java
new file mode 100644
index 0000000..89be8b3
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Grab.java
@@ -0,0 +1,143 @@
+/*
+ *  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 groovy.lang;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to grab the referenced artifact and its dependencies and make it available on the Classpath.
+ * <p>
+ * Some examples:
+ * <pre>
+ * {@code @Grab}(group='commons-lang', module='commons-lang', version='2.4')
+ * import org.apache.commons.lang.WordUtils
+ * println "Hello ${WordUtils.capitalize('world')}"
+ * </pre>
+ * Or using the compact Gradle-inspired syntax:
+ * <pre>
+ * {@code @Grab}('commons-lang:commons-lang:2.4')
+ * import org.apache.commons.lang.WordUtils
+ * println "Hello ${WordUtils.capitalize('world')}"
+ * </pre>
+ * or the same thing again using the Ivy-inspired syntax variant:
+ * <pre>
+ * {@code @Grab}('commons-lang#commons-lang;2.4')
+ * import org.apache.commons.lang.WordUtils
+ * println "Hello ${WordUtils.capitalize('world')}"
+ * </pre>
+ * Further information such as where artifacts are downloaded to, how to add additional resolvers,
+ * how to customise artifact resolution etc., can be found on the Grape documentation page:
+ * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+        ElementType.CONSTRUCTOR,
+        ElementType.FIELD,
+        ElementType.LOCAL_VARIABLE,
+        ElementType.METHOD,
+        ElementType.PARAMETER,
+        ElementType.TYPE})
+public @interface Grab {
+    /**
+     * The organisation or group, e.g.: "org.apache.ant". A non-empty value is required unless value() is used.
+     */
+    String group() default "";
+
+    /**
+     * The module or artifact, e.g.: "ant-junit". A non-empty value is required unless value() is used.
+     */
+    String module() default "";
+
+    /**
+     * The revision or version, e.g.: "1.7.1". A non-empty value is required unless value() is used.
+     */
+    String version() default "";
+
+    /**
+     * The classifier if in use, e.g.: "jdk14"
+     */
+    String classifier() default "";
+
+    /**
+     * Defaults to {@code true} but set to {@code false} if you don't want transitive dependencies also to be downloaded.
+     * You may then need additional {@code @Grab} statements for any required dependencies.
+     */
+    boolean transitive() default true;
+
+    /**
+     * Defaults to {@code false} but set to {@code true} to indicate to the underlying Ivy conflict manager that this
+     * dependency should be forced to the given revision. Otherwise, depending on the conflict manager in play, a later
+     * compatible version might be used instead.
+     */
+    boolean force() default false;
+
+    /**
+     * Defaults to {@code false} but set to {@code true} if the dependency artifacts may change without a corresponding
+     * revision change. Not normally recommended but may be useful for certain kinds of snapshot artifacts.
+     * May reduce the amount of underlying Ivy caching. Proper behavior may be dependent on the resolver in use.
+     */
+    boolean changing() default false;
+
+    /**
+     * The configuration if in use (normally only used by internal ivy repositories).
+     * One or more comma separated values with or without square brackets,
+     * e.g.&#160;for hibernate you might have "default,proxool,oscache" or "[default,dbcp,swarmcache]".
+     * This last hibernate example assumes you have set up such configurations in your local Ivy repo
+     * and have changed your grape config (using grapeConfig.xml) or the {@code @GrabConfig} annotation
+     * to point to that repo.
+     */
+    String conf() default "";
+
+    /**
+     * The extension of the artifact (normally safe to leave at default value of "jar" but other values like "zip"
+     * are sometimes useful).
+     */
+    String ext() default "";
+
+    /**
+     * The type of the artifact (normally safe to leave at default value of "jar" but other values like "sources" and "javadoc" are sometimes useful).
+     * But see also the "classifier" attribute which is also sometimes used for "sources" and "javadoc".
+     */
+    String type() default "";
+
+    /**
+     * Allows a more compact convenience form in one of two formats with optional appended attributes.
+     * Must not be used if group(), module() or version() are used.
+     * <p>
+     * You can choose either format but not mix-n-match:<br>
+     * {@code group:module:version:classifier@ext} (where only group and module are required)<br>
+     * {@code group#module;version[confs]} (where only group and module are required and confs,
+     * if used, is one or more comma separated configuration names)<br>
+     * In addition, you can add any valid Ivy attributes at the end of your string value using
+     * semi-colon separated name = value pairs, e.g.:<br>
+     * {@code @Grab('junit:junit:*;transitive=false')}<br>
+     * {@code @Grab('group=junit;module=junit;version=4.8.2;classifier=javadoc')}<br>
+     */
+    String value() default "";
+
+    /**
+     * By default, when a {@code @Grab} annotation is used, a {@code Grape.grab()} call is added
+     * to the static initializers of the class the annotatable node appears in.
+     * If you wish to disable this, add {@code initClass=false} to the annotation.
+     */
+    boolean initClass() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GrabConfig.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GrabConfig.java b/src/main/groovy/groovy/lang/GrabConfig.java
new file mode 100644
index 0000000..e6b8980
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GrabConfig.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 groovy.lang;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to modify the grape configuration for grab requests.
+ * <p>
+ * An example involving databases:
+ * <pre>
+ * {@code @Grab}('mysql:mysql-connector-java:5.1.6'),
+ * {@code @GrabConfig}(systemClassLoader=true)
+ * import groovy.sql.Sql
+ *
+ * def sql=Sql.newInstance("jdbc:mysql://localhost/test", "user", "password", "com.mysql.jdbc.Driver")
+ * println sql.firstRow('SELECT * FROM INFORMATION_SCHEMA.COLUMNS')
+ * </pre>
+ * Another example involving XStream:
+ * <pre>
+ * {@code @Grab}('com.thoughtworks.xstream:xstream:1.4.9'),
+ * {@code @Grab}('xpp3:xpp3_min:1.1.4c'),
+ * {@code @GrabConfig}(systemClassLoader=true, initContextClassLoader=true)
+ * import com.thoughtworks.xstream.*
+ *
+ * class Staff {
+ *     String firstname, lastname, position
+ * }
+ *
+ * def xstream = new XStream()
+ * def john1 = new Staff(firstname:'John',
+ *                      lastname:'Connor',
+ *                      position:'Resistance Leader')
+ *
+ * // write out to XML file
+ * new File("john.xml").withOutputStream { out ->
+ *     xstream.toXML(john1, out)
+ * }
+ *
+ * // now read back in
+ * def john2
+ * new File("john.xml").withInputStream { ins ->
+ *     john2 = xstream.fromXML(ins)
+ * }
+ *
+ * println john2.dump()
+ * </pre>
+ * <p>
+ * Further information about customising grape behavior can be found on the Grape documentation page:
+ * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+        ElementType.CONSTRUCTOR,
+        ElementType.FIELD,
+        ElementType.LOCAL_VARIABLE,
+        ElementType.METHOD,
+        ElementType.PARAMETER,
+        ElementType.TYPE})
+public @interface GrabConfig {
+    /**
+     * Set to true if you want to use the system classloader when loading the grape.
+     * This is normally only required when a core Java class needs to reference the grabbed
+     * classes, e.g. for a database driver accessed using DriverManager.
+     */
+    boolean systemClassLoader() default false;
+
+    /**
+     * Define any system properties which must be set before invoking the grab - useful for
+     * declaring SSL certificates or proxy settings. Currently, this only affects the generated
+     * class or script. You may need to also set those same properties for the Groovy compiler.
+     * For convenience, a String with comma separated name=value pairs
+     * can be used in addition to an array (using Groovy's literal list notation) of String name=value items.
+     * The single String shorthand form can't be used if value part of a property contains a comma.
+     *
+     * @since 2.4.5
+     */
+    String[] systemProperties() default "";
+
+    /**
+     * Set to true if you want the context classloader to be initialised to the classloader
+     * of the current class or script. This is useful for libraries or frameworks that assume
+     * that the context classloader has been set. But be careful when using this flag as your
+     * script or class might behave differently when called directly (from the command line or
+     * from an IDE) versus when called from within a container, e.g. a web container or a JEE container.
+     */
+    boolean initContextClassLoader() default false;
+
+    /**
+     * Set to false if you want to disable automatic downloading of locally missing jars.
+     */
+    boolean autoDownload() default true;
+
+    /**
+     * Set to true if you want to disable checksum checking.
+     */
+    boolean disableChecksums() default false;
+}
\ No newline at end of file


[05/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/BuilderSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/BuilderSupport.java b/src/main/groovy/util/BuilderSupport.java
deleted file mode 100644
index f634f1f..0000000
--- a/src/main/groovy/util/BuilderSupport.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.MissingMethodException;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * An abstract base class for creating arbitrary nested trees of objects
- * or events
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public abstract class BuilderSupport extends GroovyObjectSupport {
-
-    private Object current;
-    private Closure nameMappingClosure;
-    private final BuilderSupport proxyBuilder;
-
-    public BuilderSupport() {
-        this.proxyBuilder = this;
-    }
-
-    public BuilderSupport(BuilderSupport proxyBuilder) {
-        this(null, proxyBuilder);
-    }
-
-    public BuilderSupport(Closure nameMappingClosure, BuilderSupport proxyBuilder) {
-        this.nameMappingClosure = nameMappingClosure;
-        this.proxyBuilder = proxyBuilder;
-    }
-
-    /**
-     * Convenience method when no arguments are required
-     *
-     * @param methodName the name of the method to invoke
-     * @return the result of the call
-     */
-    public Object invokeMethod(String methodName) {
-        return invokeMethod(methodName, null);
-    }
-
-    public Object invokeMethod(String methodName, Object args) {
-        Object name = getName(methodName);
-        return doInvokeMethod(methodName, name, args);
-    }
-
-    protected Object doInvokeMethod(String methodName, Object name, Object args) {
-        Object node = null;
-        Closure closure = null;
-        List list = InvokerHelper.asList(args);
-
-        //System.out.println("Called invokeMethod with name: " + name + " arguments: " + list);
-
-        switch (list.size()) {
-            case 0:
-                node = proxyBuilder.createNode(name);
-                break;
-            case 1: {
-                Object object = list.get(0);
-                if (object instanceof Map) {
-                    node = proxyBuilder.createNode(name, (Map) object);
-                } else if (object instanceof Closure) {
-                    closure = (Closure) object;
-                    node = proxyBuilder.createNode(name);
-                } else {
-                    node = proxyBuilder.createNode(name, object);
-                }
-            }
-            break;
-            case 2: {
-                Object object1 = list.get(0);
-                Object object2 = list.get(1);
-                if (object1 instanceof Map) {
-                    if (object2 instanceof Closure) {
-                        closure = (Closure) object2;
-                        node = proxyBuilder.createNode(name, (Map) object1);
-                    } else {
-                        node = proxyBuilder.createNode(name, (Map) object1, object2);
-                    }
-                } else {
-                    if (object2 instanceof Closure) {
-                        closure = (Closure) object2;
-                        node = proxyBuilder.createNode(name, object1);
-                    } else if (object2 instanceof Map) {
-                        node = proxyBuilder.createNode(name, (Map) object2, object1);
-                    } else {
-                        throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
-                    }
-                }
-            }
-            break;
-            case 3: {
-                Object arg0 = list.get(0);
-                Object arg1 = list.get(1);
-                Object arg2 = list.get(2);
-                if (arg0 instanceof Map && arg2 instanceof Closure) {
-                    closure = (Closure) arg2;
-                    node = proxyBuilder.createNode(name, (Map) arg0, arg1);
-                } else if (arg1 instanceof Map && arg2 instanceof Closure) {
-                    closure = (Closure) arg2;
-                    node = proxyBuilder.createNode(name, (Map) arg1, arg0);
-                } else {
-                    throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
-                }
-            }
-            break;
-            default: {
-                throw new MissingMethodException(name.toString(), getClass(), list.toArray(), false);
-            }
-
-        }
-
-        if (current != null) {
-            proxyBuilder.setParent(current, node);
-        }
-
-        if (closure != null) {
-            // push new node on stack
-            Object oldCurrent = getCurrent();
-            setCurrent(node);
-            // let's register the builder as the delegate
-            setClosureDelegate(closure, node);
-            try {
-                closure.call();
-            } catch (Exception e) {
-                throw new GroovyRuntimeException(e);
-            }
-            setCurrent(oldCurrent);
-        }
-
-        proxyBuilder.nodeCompleted(current, node);
-        return proxyBuilder.postNodeCompletion(current, node);
-    }
-
-    /**
-     * A strategy method to allow derived builders to use
-     * builder-trees and switch in different kinds of builders.
-     * This method should call the setDelegate() method on the closure
-     * which by default passes in this but if node is-a builder
-     * we could pass that in instead (or do something wacky too)
-     *
-     * @param closure the closure on which to call setDelegate()
-     * @param node    the node value that we've just created, which could be
-     *                a builder
-     */
-    protected void setClosureDelegate(Closure closure, Object node) {
-        closure.setDelegate(this);
-    }
-
-    protected abstract void setParent(Object parent, Object child);
-
-    protected abstract Object createNode(Object name);
-
-    protected abstract Object createNode(Object name, Object value);
-
-    protected abstract Object createNode(Object name, Map attributes);
-
-    protected abstract Object createNode(Object name, Map attributes, Object value);
-
-    /**
-     * A hook to allow names to be converted into some other object
-     * such as a QName in XML or ObjectName in JMX.
-     *
-     * @param methodName the name of the desired method
-     * @return the object representing the name
-     */
-    protected Object getName(String methodName) {
-        if (nameMappingClosure != null) {
-            return nameMappingClosure.call(methodName);
-        }
-        return methodName;
-    }
-
-
-    /**
-     * A hook to allow nodes to be processed once they have had all of their
-     * children applied.
-     *
-     * @param node   the current node being processed
-     * @param parent the parent of the node being processed
-     */
-    protected void nodeCompleted(Object parent, Object node) {
-    }
-
-    /**
-     * A hook to allow nodes to be processed once they have had all of their
-     * children applied and allows the actual node object that represents
-     * the Markup element to be changed
-     *
-     * @param node   the current node being processed
-     * @param parent the parent of the node being processed
-     * @return the node, possibly new, that represents the markup element
-     */
-    protected Object postNodeCompletion(Object parent, Object node) {
-        return node;
-    }
-
-    protected Object getCurrent() {
-        return current;
-    }
-
-    protected void setCurrent(Object current) {
-        this.current = current;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/CharsetToolkit.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/CharsetToolkit.java b/src/main/groovy/util/CharsetToolkit.java
deleted file mode 100644
index e127459..0000000
--- a/src/main/groovy/util/CharsetToolkit.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- *  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 groovy.util;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.nio.charset.Charset;
-import java.util.Collection;
-
-/**
- * Utility class to guess the encoding of a given text file.
- * <p>
- * Unicode files encoded in UTF-16 (low or big endian) or UTF-8 files
- * with a Byte Order Marker are correctly discovered. For UTF-8 files with no BOM, if the buffer
- * is wide enough, the charset should also be discovered.
- * <p>
- * A byte buffer of 4KB is used to be able to guess the encoding.
- * <p>
- * Usage:
- * <pre>
- * CharsetToolkit toolkit = new CharsetToolkit(file);
- *
- * // guess the encoding
- * Charset guessedCharset = toolkit.getCharset();
- *
- * // create a reader with the correct charset
- * BufferedReader reader = toolkit.getReader();
- *
- * // read the file content
- * String line;
- * while ((line = br.readLine())!= null)
- * {
- *     System.out.println(line);
- * }
- * </pre>
- *
- * @author Guillaume Laforge
- */
-public class CharsetToolkit {
-    private final byte[] buffer;
-    private Charset defaultCharset;
-    private Charset charset;
-    private boolean enforce8Bit = true;
-    private final File file;
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-
-    /**
-     * Constructor of the <code>CharsetToolkit</code> utility class.
-     *
-     * @param file of which we want to know the encoding.
-     */
-    public CharsetToolkit(File file) throws IOException {
-        this.file = file;
-        this.defaultCharset = getDefaultSystemCharset();
-        this.charset = null;
-        InputStream input = new FileInputStream(file);
-        try {
-            byte[] bytes = new byte[4096];
-            int bytesRead = input.read(bytes);
-            if (bytesRead == -1) {
-                this.buffer = EMPTY_BYTE_ARRAY;
-            }
-            else if (bytesRead < 4096) {
-                byte[] bytesToGuess = new byte[bytesRead];
-                System.arraycopy(bytes, 0, bytesToGuess, 0, bytesRead);
-                this.buffer = bytesToGuess;
-            }
-            else {
-                this.buffer = bytes;
-            }
-        } finally {
-            try {input.close();} catch (IOException e){
-                // IGNORE
-            }
-        }
-    }
-
-    /**
-     * Defines the default <code>Charset</code> used in case the buffer represents
-     * an 8-bit <code>Charset</code>.
-     *
-     * @param defaultCharset the default <code>Charset</code> to be returned
-     * if an 8-bit <code>Charset</code> is encountered.
-     */
-    public void setDefaultCharset(Charset defaultCharset) {
-        if (defaultCharset != null)
-            this.defaultCharset = defaultCharset;
-        else
-            this.defaultCharset = getDefaultSystemCharset();
-    }
-
-    public Charset getCharset() {
-        if (this.charset == null)
-            this.charset = guessEncoding();
-        return charset;
-    }
-
-    /**
-     * If US-ASCII is recognized, enforce to return the default encoding, rather than US-ASCII.
-     * It might be a file without any special character in the range 128-255, but that may be or become
-     * a file encoded with the default <code>charset</code> rather than US-ASCII.
-     *
-     * @param enforce a boolean specifying the use or not of US-ASCII.
-     */
-    public void setEnforce8Bit(boolean enforce) {
-        this.enforce8Bit = enforce;
-    }
-
-    /**
-     * Gets the enforce8Bit flag, in case we do not want to ever get a US-ASCII encoding.
-     *
-     * @return a boolean representing the flag of use of US-ASCII.
-     */
-    public boolean getEnforce8Bit() {
-        return this.enforce8Bit;
-    }
-
-    /**
-     * Retrieves the default Charset
-     */
-    public Charset getDefaultCharset() {
-        return defaultCharset;
-    }
-
-    /**
-     * Guess the encoding of the provided buffer.
-     * If Byte Order Markers are encountered at the beginning of the buffer, we immediately
-     * return the charset implied by this BOM. Otherwise, the file would not be a human
-     * readable text file.
-     * <p>
-     * If there is no BOM, this method tries to discern whether the file is UTF-8 or not.
-     * If it is not UTF-8, we assume the encoding is the default system encoding
-     * (of course, it might be any 8-bit charset, but usually, an 8-bit charset is the default one).
-     * <p>
-     * It is possible to discern UTF-8 thanks to the pattern of characters with a multi-byte sequence.
-     * <pre>
-     * UCS-4 range (hex.)        UTF-8 octet sequence (binary)
-     * 0000 0000-0000 007F       0xxxxxxx
-     * 0000 0080-0000 07FF       110xxxxx 10xxxxxx
-     * 0000 0800-0000 FFFF       1110xxxx 10xxxxxx 10xxxxxx
-     * 0001 0000-001F FFFF       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * 0020 0000-03FF FFFF       111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * 0400 0000-7FFF FFFF       1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * </pre>
-     * With UTF-8, 0xFE and 0xFF never appear.
-     *
-     * @return the Charset recognized.
-     */
-    private Charset guessEncoding() {
-        // if the file has a Byte Order Marker, we can assume the file is in UTF-xx
-        // otherwise, the file would not be human readable
-        if (hasUTF8Bom())
-            return Charset.forName("UTF-8");
-        if (hasUTF16LEBom())
-            return Charset.forName("UTF-16LE");
-        if (hasUTF16BEBom())
-            return Charset.forName("UTF-16BE");
-
-        // if a byte has its most significant bit set, the file is in UTF-8 or in the default encoding
-        // otherwise, the file is in US-ASCII
-        boolean highOrderBit = false;
-
-        // if the file is in UTF-8, high order bytes must have a certain value, in order to be valid
-        // if it's not the case, we can assume the encoding is the default encoding of the system
-        boolean validU8Char = true;
-
-        // TODO the buffer is not read up to the end, but up to length - 6
-
-        int length = buffer.length;
-        int i = 0;
-        while (i < length - 6) {
-            byte b0 = buffer[i];
-            byte b1 = buffer[i + 1];
-            byte b2 = buffer[i + 2];
-            byte b3 = buffer[i + 3];
-            byte b4 = buffer[i + 4];
-            byte b5 = buffer[i + 5];
-            if (b0 < 0) {
-                // a high order bit was encountered, thus the encoding is not US-ASCII
-                // it may be either an 8-bit encoding or UTF-8
-                highOrderBit = true;
-                // a two-bytes sequence was encountered
-                if (isTwoBytesSequence(b0)) {
-                    // there must be one continuation byte of the form 10xxxxxx,
-                    // otherwise the following character is is not a valid UTF-8 construct
-                    if (!isContinuationChar(b1))
-                        validU8Char = false;
-                    else
-                        i++;
-                }
-                // a three-bytes sequence was encountered
-                else if (isThreeBytesSequence(b0)) {
-                    // there must be two continuation bytes of the form 10xxxxxx,
-                    // otherwise the following character is is not a valid UTF-8 construct
-                    if (!(isContinuationChar(b1) && isContinuationChar(b2)))
-                        validU8Char = false;
-                    else
-                        i += 2;
-                }
-                // a four-bytes sequence was encountered
-                else if (isFourBytesSequence(b0)) {
-                    // there must be three continuation bytes of the form 10xxxxxx,
-                    // otherwise the following character is is not a valid UTF-8 construct
-                    if (!(isContinuationChar(b1) && isContinuationChar(b2) && isContinuationChar(b3)))
-                        validU8Char = false;
-                    else
-                        i += 3;
-                }
-                // a five-bytes sequence was encountered
-                else if (isFiveBytesSequence(b0)) {
-                    // there must be four continuation bytes of the form 10xxxxxx,
-                    // otherwise the following character is is not a valid UTF-8 construct
-                    if (!(isContinuationChar(b1)
-                        && isContinuationChar(b2)
-                        && isContinuationChar(b3)
-                        && isContinuationChar(b4)))
-                        validU8Char = false;
-                    else
-                        i += 4;
-                }
-                // a six-bytes sequence was encountered
-                else if (isSixBytesSequence(b0)) {
-                    // there must be five continuation bytes of the form 10xxxxxx,
-                    // otherwise the following character is is not a valid UTF-8 construct
-                    if (!(isContinuationChar(b1)
-                        && isContinuationChar(b2)
-                        && isContinuationChar(b3)
-                        && isContinuationChar(b4)
-                        && isContinuationChar(b5)))
-                        validU8Char = false;
-                    else
-                        i += 5;
-                }
-                else
-                    validU8Char = false;
-            }
-            if (!validU8Char)
-                break;
-            i++;
-        }
-        // if no byte with an high order bit set, the encoding is US-ASCII
-        // (it might have been UTF-7, but this encoding is usually internally used only by mail systems)
-        if (!highOrderBit) {
-            // returns the default charset rather than US-ASCII if the enforce8Bit flag is set.
-            if (this.enforce8Bit)
-                return this.defaultCharset;
-            else
-                return Charset.forName("US-ASCII");
-        }
-        // if no invalid UTF-8 were encountered, we can assume the encoding is UTF-8,
-        // otherwise the file would not be human readable
-        if (validU8Char)
-            return Charset.forName("UTF-8");
-        // finally, if it's not UTF-8 nor US-ASCII, let's assume the encoding is the default encoding
-        return this.defaultCharset;
-    }
-
-    /**
-     * If the byte has the form 10xxxxx, then it's a continuation byte of a multiple byte character;
-     *
-     * @param b a byte.
-     * @return true if it's a continuation char.
-     */
-    private static boolean isContinuationChar(byte b) {
-        return -128 <= b && b <= -65;
-    }
-
-    /**
-     * If the byte has the form 110xxxx, then it's the first byte of a two-bytes sequence character.
-     *
-     * @param b a byte.
-     * @return true if it's the first byte of a two-bytes sequence.
-     */
-    private static boolean isTwoBytesSequence(byte b) {
-        return -64 <= b && b <= -33;
-    }
-
-    /**
-     * If the byte has the form 1110xxx, then it's the first byte of a three-bytes sequence character.
-     *
-     * @param b a byte.
-     * @return true if it's the first byte of a three-bytes sequence.
-     */
-    private static boolean isThreeBytesSequence(byte b) {
-        return -32 <= b && b <= -17;
-    }
-
-    /**
-     * If the byte has the form 11110xx, then it's the first byte of a four-bytes sequence character.
-     *
-     * @param b a byte.
-     * @return true if it's the first byte of a four-bytes sequence.
-     */
-    private static boolean isFourBytesSequence(byte b) {
-        return -16 <= b && b <= -9;
-    }
-
-    /**
-     * If the byte has the form 11110xx, then it's the first byte of a five-bytes sequence character.
-     *
-     * @param b a byte.
-     * @return true if it's the first byte of a five-bytes sequence.
-     */
-    private static boolean isFiveBytesSequence(byte b) {
-        return -8 <= b && b <= -5;
-    }
-
-    /**
-     * If the byte has the form 1110xxx, then it's the first byte of a six-bytes sequence character.
-     *
-     * @param b a byte.
-     * @return true if it's the first byte of a six-bytes sequence.
-     */
-    private static boolean isSixBytesSequence(byte b) {
-        return -4 <= b && b <= -3;
-    }
-
-    /**
-     * Retrieve the default charset of the system.
-     *
-     * @return the default <code>Charset</code>.
-     */
-    public static Charset getDefaultSystemCharset() {
-        return Charset.forName(System.getProperty("file.encoding"));
-    }
-
-    /**
-     * Has a Byte Order Marker for UTF-8 (Used by Microsoft's Notepad and other editors).
-     *
-     * @return true if the buffer has a BOM for UTF8.
-     */
-    public boolean hasUTF8Bom() {
-        if (buffer.length >= 3)
-            return (buffer[0] == -17 && buffer[1] == -69 && buffer[2] == -65);
-        else
-            return false;
-    }
-
-    /**
-     * Has a Byte Order Marker for UTF-16 Low Endian
-     * (ucs-2le, ucs-4le, and ucs-16le).
-     *
-     * @return true if the buffer has a BOM for UTF-16 Low Endian.
-     */
-    public boolean hasUTF16LEBom() {
-        if (buffer.length >= 2)
-            return (buffer[0] == -1 && buffer[1] == -2);
-        else
-            return false;
-    }
-
-    /**
-     * Has a Byte Order Marker for UTF-16 Big Endian
-     * (utf-16 and ucs-2).
-     *
-     * @return true if the buffer has a BOM for UTF-16 Big Endian.
-     */
-    public boolean hasUTF16BEBom() {
-        if (buffer.length >= 2)
-            return (buffer[0] == -2 && buffer[1] == -1);
-        else
-            return false;
-    }
-
-    /**
-     * Gets a <code>BufferedReader</code> (indeed a <code>LineNumberReader</code>) from the <code>File</code>
-     * specified in the constructor of <code>CharsetToolkit</code> using the charset discovered or the default
-     * charset if an 8-bit <code>Charset</code> is encountered.
-     *
-     * @return a <code>BufferedReader</code>
-     * @throws FileNotFoundException if the file is not found.
-     */
-    public BufferedReader getReader() throws FileNotFoundException {
-        LineNumberReader reader = new LineNumberReader(new InputStreamReader(new FileInputStream(file), getCharset()));
-        if (hasUTF8Bom() || hasUTF16LEBom() || hasUTF16BEBom()) {
-            try {
-                reader.read();
-            }
-            catch (IOException e) {
-                // should never happen, as a file with no content
-                // but with a BOM has at least one char
-            }
-        }
-        return reader;
-    }
-
-    /**
-     * Retrieves all the available <code>Charset</code>s on the platform,
-     * among which the default <code>charset</code>.
-     *
-     * @return an array of <code>Charset</code>s.
-     */
-    public static Charset[] getAvailableCharsets() {
-        Collection collection = Charset.availableCharsets().values();
-        return (Charset[]) collection.toArray(new Charset[collection.size()]);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/CliBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/CliBuilder.groovy b/src/main/groovy/util/CliBuilder.groovy
deleted file mode 100644
index bc7d44a..0000000
--- a/src/main/groovy/util/CliBuilder.groovy
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- *  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 groovy.util
-
-import groovy.cli.CliBuilderException
-import groovy.cli.Option
-import groovy.cli.TypedOption
-import groovy.cli.Unparsed
-import groovy.transform.Undefined
-import org.apache.commons.cli.CommandLine
-import org.apache.commons.cli.CommandLineParser
-import org.apache.commons.cli.DefaultParser
-import org.apache.commons.cli.GnuParser
-import org.apache.commons.cli.HelpFormatter
-import org.apache.commons.cli.Option as CliOption
-import org.apache.commons.cli.Options
-import org.apache.commons.cli.ParseException
-import org.codehaus.groovy.runtime.InvokerHelper
-import org.codehaus.groovy.runtime.MetaClassHelper
-import org.codehaus.groovy.runtime.StringGroovyMethods
-
-import java.lang.annotation.Annotation
-import java.lang.reflect.Array
-import java.lang.reflect.Field
-import java.lang.reflect.Method
-
-/**
- * Provides a builder to assist the processing of command line arguments.
- * Two styles are supported: dynamic api style (declarative method calls provide a mini DSL for describing options)
- * and annotation style (annotations on an interface or class describe options).
- * <p>
- * <b>Dynamic api style</b>
- * <p>
- * Typical usage (emulate partial arg processing of unix command: ls -alt *.groovy):
- * <pre>
- * def cli = new CliBuilder(usage:'ls')
- * cli.a('display all files')
- * cli.l('use a long listing format')
- * cli.t('sort by modification time')
- * def options = cli.parse(args)
- * assert options // would be null (false) on failure
- * assert options.arguments() == ['*.groovy']
- * assert options.a && options.l && options.t
- * </pre>
- * The usage message for this example (obtained using <code>cli.usage()</code>) is shown below:
- * <pre>
- * usage: ls
- *  -a   display all files
- *  -l   use a long listing format
- *  -t   sort by modification time
- * </pre>
- * An underlying parser that supports what is called argument 'bursting' is used
- * by default. Bursting would convert '-alt' into '-a -l -t' provided no long
- * option exists with value 'alt' and provided that none of 'a', 'l' or 't'
- * takes an argument (in fact the last one is allowed to take an argument).
- * The bursting behavior can be turned off by using an
- * alternate underlying parser. The simplest way to achieve this is by using
- * the deprecated GnuParser from Commons CLI with the parser property on the CliBuilder,
- * i.e. include <code>parser: new GnuParser()</code> in the constructor call.
- * <p>
- * Another example (partial emulation of arg processing for 'ant' command line):
- * <pre>
- * def cli = new CliBuilder(usage:'ant [options] [targets]',
- *                          header:'Options:')
- * cli.help('print this message')
- * cli.logfile(args:1, argName:'file', 'use given file for log')
- * cli.D(args:2, valueSeparator:'=', argName:'property=value',
- *       'use value for given property')
- * def options = cli.parse(args)
- * ...
- * </pre>
- * Usage message would be:
- * <pre>
- * usage: ant [options] [targets]
- * Options:
- *  -D &lt;property=value>   use value for given property
- *  -help                 print this message
- *  -logfile &lt;file>       use given file for log
- * </pre>
- * And if called with the following arguments '-logfile foo -Dbar=baz target'
- * then the following assertions would be true:
- * <pre>
- * assert options // would be null (false) on failure
- * assert options.arguments() == ['target']
- * assert options.Ds == ['bar', 'baz']
- * assert options.logfile == 'foo'
- * </pre>
- * Note the use of some special notation. By adding 's' onto an option
- * that may appear multiple times and has an argument or as in this case
- * uses a valueSeparator to separate multiple argument values
- * causes the list of associated argument values to be returned.
- * <p>
- * Another example showing long options (partial emulation of arg processing for 'curl' command line):
- * <pre>
- * def cli = new CliBuilder(usage:'curl [options] &lt;url&gt;')
- * cli._(longOpt:'basic', 'Use HTTP Basic Authentication')
- * cli.d(longOpt:'data', args:1, argName:'data', 'HTTP POST data')
- * cli.G(longOpt:'get', 'Send the -d data with a HTTP GET')
- * cli.q('If used as the first parameter disables .curlrc')
- * cli._(longOpt:'url', args:1, argName:'URL', 'Set URL to work with')
- * </pre>
- * Which has the following usage message:
- * <pre>
- * usage: curl [options] &lt;url>
- *     --basic         Use HTTP Basic Authentication
- *  -d,--data &lt;data>   HTTP POST data
- *  -G,--get           Send the -d data with a HTTP GET
- *  -q                 If used as the first parameter disables .curlrc
- *     --url &lt;URL>     Set URL to work with
- * </pre>
- * This example shows a common convention. When mixing short and long names, the
- * short names are often one character in size. One character options with
- * arguments don't require a space between the option and the argument, e.g.
- * <code>-Ddebug=true</code>. The example also shows
- * the use of '_' when no short option is applicable.
- * <p>
- * Also note that '_' was used multiple times. This is supported but if
- * any other shortOpt or any longOpt is repeated, then the behavior is undefined.
- * <p>
- * Short option names may not contain a hyphen. If a long option name contains a hyphen, e.g. '--max-wait' then you can either
- * use the long hand method call <code>options.hasOption('max-wait')</code> or surround
- * the option name in quotes, e.g. <code>options.'max-wait'</code>.
- * <p>
- * Although CliBuilder on the whole hides away the underlying library used
- * for processing the arguments, it does provide some hooks which let you
- * make use of the underlying library directly should the need arise. For
- * example, the last two lines of the 'curl' example above could be replaced
- * with the following:
- * <pre>
- * import org.apache.commons.cli.*
- * ... as before ...
- * cli << new Option('q', false, 'If used as the first parameter disables .curlrc')
- * cli << Option.builder().longOpt('url').hasArg().argName('URL').
- *                      desc('Set URL to work with').build()
- * ...
- * </pre>
- *
- * CliBuilder also supports Argument File processing. If an argument starts with
- * an '@' character followed by a filename, then the contents of the file with name
- * filename are placed into the command line. The feature can be turned off by
- * setting expandArgumentFiles to false. If turned on, you can still pass a real
- * parameter with an initial '@' character by escaping it with an additional '@'
- * symbol, e.g. '@@foo' will become '@foo' and not be subject to expansion. As an
- * example, if the file temp.args contains the content:
- * <pre>
- * -arg1
- * paramA
- * paramB paramC
- * </pre>
- * Then calling the command line with:
- * <pre>
- * someCommand @temp.args -arg2 paramD
- * </pre>
- * Is the same as calling this:
- * <pre>
- * someCommand -arg1 paramA paramB paramC -arg2 paramD
- * </pre>
- * This feature is particularly useful on operating systems which place limitations
- * on the size of the command line (e.g. Windows). The feature is similar to
- * the 'Command Line Argument File' processing supported by javadoc and javac.
- * Consult the corresponding documentation for those tools if you wish to see further examples.
- * <p>
- * <b>Supported Option Properties</b>:
- * <pre>
- *   argName:        String
- *   longOpt:        String
- *   args:           int or String
- *   optionalArg:    boolean
- *   required:       boolean
- *   type:           Class
- *   valueSeparator: char
- *   convert:        Closure
- *   defaultValue:   String
- * </pre>
- * See {@link org.apache.commons.cli.Option} for the meaning of most of these properties
- * and {@link CliBuilderTest} for further examples.
- * <p>
- * <b>Annotation style with an interface</b>
- * <p>
- * With this style an interface is defined containing an annotated method for each option.
- * It might look like this (following roughly the earlier 'ls' example):
- * <pre>
- * import groovy.cli.Option
- * import groovy.cli.Unparsed
- *
- * interface OptionInterface {
- *     @{@link groovy.cli.Option}(shortName='a', description='display all files') boolean all()
- *     @{@link groovy.cli.Option}(shortName='l', description='use a long listing format') boolean longFormat()
- *     @{@link groovy.cli.Option}(shortName='t', description='sort by modification time') boolean time()
- *     @{@link groovy.cli.Unparsed} List remaining()
- * }
- * </pre>
- * Then this description is supplied to CliBuilder during parsing, e.g.:
- * <pre>
- * def args = '-alt *.groovy'.split() // normally from commandline itself
- * def cli = new CliBuilder(usage:'ls')
- * def options = cli.parseFromSpec(OptionInterface, args)
- * assert options.remaining() == ['*.groovy']
- * assert options.all() && options.longFormat() && options.time()
- * </pre>
- * <p>
- * <b>Annotation style with a class</b>
- * <p>
- * With this style a user-supplied instance is used. Annotations on that instance's class
- * members (properties and setter methods) indicate how to set options and provide the option details
- * using annotation attributes.
- * It might look like this (again using the earlier 'ls' example):
- * <pre>
- * import groovy.cli.Option
- * import groovy.cli.Unparsed
- *
- * class OptionClass {
- *     @{@link groovy.cli.Option}(shortName='a', description='display all files') boolean all
- *     @{@link groovy.cli.Option}(shortName='l', description='use a long listing format') boolean longFormat
- *     @{@link groovy.cli.Option}(shortName='t', description='sort by modification time') boolean time
- *     @{@link groovy.cli.Unparsed} List remaining
- * }
- * </pre>
- * Then this description is supplied to CliBuilder during parsing, e.g.:
- * <pre>
- * def args = '-alt *.groovy'.split() // normally from commandline itself
- * def cli = new CliBuilder(usage:'ls')
- * def options = new OptionClass()
- * cli.parseFromInstance(options, args)
- * assert options.remaining == ['*.groovy']
- * assert options.all && options.longFormat && options.time
- * </pre>
- */
-class CliBuilder {
-
-    /**
-     * Usage summary displayed as the first line when <code>cli.usage()</code> is called.
-     */
-    String usage = 'groovy'
-
-    /**
-     * Normally set internally but allows you full customisation of the underlying processing engine.
-     */
-    CommandLineParser parser = null
-
-    /**
-     * To change from the default PosixParser to the GnuParser, set this to false. Ignored if the parser is explicitly set.
-     * @deprecated use the parser option instead with an instance of your preferred parser
-     */
-    @Deprecated
-    Boolean posix = null
-
-    /**
-     * Whether arguments of the form '{@code @}<i>filename</i>' will be expanded into the arguments contained within the file named <i>filename</i> (default true).
-     */
-    boolean expandArgumentFiles = true
-
-    /**
-     * Normally set internally but can be overridden if you want to customise how the usage message is displayed.
-     */
-    HelpFormatter formatter = new HelpFormatter()
-
-    /**
-     * Defaults to stdout but you can provide your own PrintWriter if desired.
-     */
-    PrintWriter writer = new PrintWriter(System.out)
-
-    /**
-     * Optional additional message for usage; displayed after the usage summary but before the options are displayed.
-     */
-    String header = ''
-
-    /**
-     * Optional additional message for usage; displayed after the options are displayed.
-     */
-    String footer = ''
-
-    /**
-     * Indicates that option processing should continue for all arguments even
-     * if arguments not recognized as options are encountered (default true).
-     */
-    boolean stopAtNonOption = true
-
-    /**
-     * Allows customisation of the usage message width.
-     */
-    int width = HelpFormatter.DEFAULT_WIDTH
-
-    /**
-     * Not normally accessed directly but full access to underlying options if needed.
-     */
-    Options options = new Options()
-
-    Map<String, TypedOption> savedTypeOptions = new HashMap<String, TypedOption>()
-
-    public <T> TypedOption<T> option(Map args, Class<T> type, String description) {
-        def name = args.opt ?: '_'
-        args.type = type
-        args.remove('opt')
-        "$name"(args, description)
-    }
-
-    /**
-     * Internal method: Detect option specification method calls.
-     */
-    def invokeMethod(String name, Object args) {
-        if (args instanceof Object[]) {
-            if (args.size() == 1 && (args[0] instanceof String || args[0] instanceof GString)) {
-                def option = option(name, [:], args[0])
-                options.addOption(option)
-
-                return create(option, null, null, null)
-            }
-            if (args.size() == 1 && args[0] instanceof CliOption && name == 'leftShift') {
-                CliOption option = args[0]
-                options.addOption(option)
-                return create(option, null, null, null)
-            }
-            if (args.size() == 2 && args[0] instanceof Map) {
-                def convert = args[0].remove('convert')
-                def type = args[0].remove('type')
-                def defaultValue = args[0].remove('defaultValue')
-                if (type && !(type instanceof Class)) {
-                    throw new CliBuilderException("'type' must be a Class")
-                }
-                if ((convert || type) && !args[0].containsKey('args') &&
-                        type?.simpleName?.toLowerCase() != 'boolean') {
-                    args[0].args = 1
-                }
-                def option = option(name, args[0], args[1])
-                options.addOption(option)
-                return create(option, type, defaultValue, convert)
-            }
-        }
-        return InvokerHelper.getMetaClass(this).invokeMethod(this, name, args)
-    }
-
-    /**
-     * Make options accessible from command line args with parser.
-     * Returns null on bad command lines after displaying usage message.
-     */
-    OptionAccessor parse(args) {
-        if (expandArgumentFiles) args = expandArgumentFiles(args)
-        if (!parser) {
-            parser = posix != null && posix == false ? new GnuParser() : new DefaultParser()
-        }
-        try {
-            def accessor = new OptionAccessor(
-                    parser.parse(options, args as String[], stopAtNonOption))
-            accessor.savedTypeOptions = savedTypeOptions
-            return accessor
-        } catch (ParseException pe) {
-            writer.println("error: " + pe.message)
-            usage()
-            return null
-        }
-    }
-
-    /**
-     * Print the usage message with writer (default: System.out) and formatter (default: HelpFormatter)
-     */
-    void usage() {
-        formatter.printHelp(writer, width, usage, header, options, HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD, footer)
-        writer.flush()
-    }
-
-    /**
-     * Given an interface containing members with annotations, derive
-     * the options specification.
-     *
-     * @param optionsClass
-     * @param args
-     * @return an instance containing the processed options
-     */
-    public <T> T parseFromSpec(Class<T> optionsClass, String[] args) {
-        addOptionsFromAnnotations(optionsClass, false)
-        def cli = parse(args)
-        def cliOptions = [:]
-        setOptionsFromAnnotations(cli, optionsClass, cliOptions, false)
-        cliOptions as T
-    }
-
-    /**
-     * Given an instance containing members with annotations, derive
-     * the options specification.
-     *
-     * @param optionInstance
-     * @param args
-     * @return the options instance populated with the processed options
-     */
-    public <T> T parseFromInstance(T optionInstance, args) {
-        addOptionsFromAnnotations(optionInstance.getClass(), true)
-        def cli = parse(args)
-        setOptionsFromAnnotations(cli, optionInstance.getClass(), optionInstance, true)
-        optionInstance
-    }
-
-    void addOptionsFromAnnotations(Class optionClass, boolean namesAreSetters) {
-        optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
-            Annotation annotation = m.getAnnotation(Option)
-            def typedOption = processAddAnnotation(annotation, m, namesAreSetters)
-            options.addOption(typedOption.cliOption)
-        }
-
-        def optionFields = optionClass.declaredFields.findAll { it.getAnnotation(Option) }
-        if (optionClass.isInterface() && !optionFields.isEmpty()) {
-            throw new CliBuilderException("@Option only allowed on methods in interface " + optionClass.simpleName)
-        }
-        optionFields.each { Field f ->
-            Annotation annotation = f.getAnnotation(Option)
-            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
-            Method m = optionClass.getMethod(setterName, f.getType())
-            def typedOption = processAddAnnotation(annotation, m, true)
-            options.addOption(typedOption.cliOption)
-        }
-    }
-
-    private TypedOption processAddAnnotation(Option annotation, Method m, boolean namesAreSetters) {
-        String shortName = annotation.shortName()
-        String description = annotation.description()
-        String defaultValue = annotation.defaultValue()
-        char valueSeparator = 0
-        if (annotation.valueSeparator()) valueSeparator = annotation.valueSeparator() as char
-        boolean optionalArg = annotation.optionalArg()
-        Integer numberOfArguments = annotation.numberOfArguments()
-        String numberOfArgumentsString = annotation.numberOfArgumentsString()
-        Class convert = annotation.convert()
-        if (convert == Undefined.CLASS) {
-            convert = null
-        }
-        Map names = calculateNames(annotation.longName(), shortName, m, namesAreSetters)
-        def builder = names.short ? CliOption.builder(names.short) : CliOption.builder()
-        if (names.long) {
-            builder.longOpt(names.long)
-        }
-        if (numberOfArguments != 1) {
-            if (numberOfArgumentsString) {
-                throw new CliBuilderException("You can't specify both 'numberOfArguments' and 'numberOfArgumentsString'")
-            }
-        }
-        def details = [:]
-        Class type = namesAreSetters ? (m.parameterTypes.size() > 0 ? m.parameterTypes[0] : null) : m.returnType
-        if (optionalArg && (!type || !type.isArray())) {
-            throw new CliBuilderException("Attempted to set optional argument for non array type")
-        }
-        def isFlag = type.simpleName.toLowerCase() == 'boolean'
-        if (numberOfArgumentsString) {
-            details.args = numberOfArgumentsString
-            details = adjustDetails(details)
-            if (details.optionalArg) optionalArg = true
-        } else {
-            details.args = isFlag ? 0 : numberOfArguments
-        }
-        if (details?.args == 0 && !(isFlag || type.name == 'java.lang.Object')) {
-            throw new CliBuilderException("Flag '${names.long ?: names.short}' must be Boolean or Object")
-        }
-        if (description) builder.desc(description)
-        if (valueSeparator) builder.valueSeparator(valueSeparator)
-        if (type) {
-            if (isFlag && details.args == 1) {
-                // special flag: treat like normal not boolean expecting explicit 'true' or 'false' param
-                isFlag = false
-            }
-            if (!isFlag) {
-                builder.hasArg(true)
-                if (details.containsKey('args')) builder.numberOfArgs(details.args)
-            }
-            if (type.isArray()) {
-                builder.optionalArg(optionalArg)
-            }
-        }
-        def typedOption = create(builder.build(), convert ? null : type, defaultValue, convert)
-        typedOption
-    }
-
-    private TypedOption create(CliOption o, Class theType, defaultValue, convert) {
-        Map<String, Object> result = new TypedOption<Object>()
-        o.with {
-            if (opt != null) result.put("opt", opt)
-            result.put("longOpt", longOpt)
-            result.put("cliOption", o)
-            if (defaultValue) {
-                result.put("defaultValue", defaultValue)
-            }
-            if (convert) {
-                if (theType) {
-                    throw new CliBuilderException("You can't specify 'type' when using 'convert'")
-                }
-                result.put("convert", convert)
-                result.put("type", convert instanceof Class ? convert : convert.getClass())
-            } else {
-                result.put("type", theType)
-            }
-        }
-        savedTypeOptions[o.longOpt ?: o.opt] = result
-        result
-    }
-
-    def setOptionsFromAnnotations(def cli, Class optionClass, Object t, boolean namesAreSetters) {
-        optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
-            Annotation annotation = m.getAnnotation(Option)
-            Map names = calculateNames(annotation.longName(), annotation.shortName(), m, namesAreSetters)
-            processSetAnnotation(m, t, names.long ?: names.short, cli, namesAreSetters)
-        }
-        optionClass.declaredFields.findAll { it.getAnnotation(Option) }.each { Field f ->
-            Annotation annotation = f.getAnnotation(Option)
-            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
-            Method m = optionClass.getMethod(setterName, f.getType())
-            Map names = calculateNames(annotation.longName(), annotation.shortName(), m, true)
-            processSetAnnotation(m, t, names.long ?: names.short, cli, true)
-        }
-        def remaining = cli.arguments()
-        optionClass.methods.findAll{ it.getAnnotation(Unparsed) }.each { Method m ->
-            processSetRemaining(m, remaining, t, cli, namesAreSetters)
-        }
-        optionClass.declaredFields.findAll{ it.getAnnotation(Unparsed) }.each { Field f ->
-            String setterName = "set" + MetaClassHelper.capitalize(f.getName());
-            Method m = optionClass.getMethod(setterName, f.getType())
-            processSetRemaining(m, remaining, t, cli, namesAreSetters)
-        }
-    }
-
-    private void processSetRemaining(Method m, remaining, Object t, cli, boolean namesAreSetters) {
-        def resultType = namesAreSetters ? m.parameterTypes[0] : m.returnType
-        def isTyped = resultType?.isArray()
-        def result
-        def type = null
-        if (isTyped) {
-            type = resultType.componentType
-            result = remaining.collect{ cli.getValue(type, it, null) }
-        } else {
-            result = remaining.toList()
-        }
-        if (namesAreSetters) {
-            m.invoke(t, isTyped ? [result.toArray(Array.newInstance(type, result.size()))] as Object[] : result)
-        } else {
-            Map names = calculateNames("", "", m, namesAreSetters)
-            t.put(names.long, { -> result })
-        }
-    }
-
-    private void processSetAnnotation(Method m, Object t, String name, cli, boolean namesAreSetters) {
-        def conv = savedTypeOptions[name]?.convert
-        if (conv && conv instanceof Class) {
-            savedTypeOptions[name].convert = conv.newInstance(t, t)
-        }
-        boolean hasArg = savedTypeOptions[name]?.cliOption?.numberOfArgs == 1
-        boolean noArg = savedTypeOptions[name]?.cliOption?.numberOfArgs == 0
-        if (namesAreSetters) {
-            def isBoolArg = m.parameterTypes.size() > 0 && m.parameterTypes[0].simpleName.toLowerCase() == 'boolean'
-            boolean isFlag = (isBoolArg && !hasArg) || noArg
-            if (cli.hasOption(name) || isFlag || cli.defaultValue(name)) {
-                m.invoke(t, [isFlag ? cli.hasOption(name) :
-                                     cli.hasOption(name) ? optionValue(cli, name) : cli.defaultValue(name)] as Object[])
-            }
-        } else {
-            def isBoolRetType = m.returnType.simpleName.toLowerCase() == 'boolean'
-            boolean isFlag = (isBoolRetType && !hasArg) || noArg
-            t.put(m.getName(), cli.hasOption(name) ?
-                    { -> isFlag ? true : optionValue(cli, name) } :
-                    { -> isFlag ? false : cli.defaultValue(name) })
-        }
-    }
-
-    private optionValue(cli, String name) {
-        if (savedTypeOptions.containsKey(name)) {
-            return cli.getOptionValue(savedTypeOptions[name])
-        }
-        cli[name]
-    }
-
-    private Map calculateNames(String longName, String shortName, Method m, boolean namesAreSetters) {
-        boolean useShort = longName == '_'
-        if (longName == '_') longName = ""
-        def result = longName
-        if (!longName) {
-            result = m.getName()
-            if (namesAreSetters && result.startsWith("set")) {
-                result = MetaClassHelper.convertPropertyName(result.substring(3))
-            }
-        }
-        [long: useShort ? "" : result, short: (useShort && !shortName) ? result : shortName]
-    }
-
-    // implementation details -------------------------------------
-
-    /**
-     * Internal method: How to create an option from the specification.
-     */
-    CliOption option(shortname, Map details, info) {
-        CliOption option
-        if (shortname == '_') {
-            option = CliOption.builder().desc(info).longOpt(details.longOpt).build()
-            details.remove('longOpt')
-        } else {
-            option = new CliOption(shortname, info)
-        }
-        adjustDetails(details).each { key, value ->
-            option[key] = value
-        }
-        return option
-    }
-
-    static Map adjustDetails(Map m) {
-        m.collectMany { k, v ->
-            if (k == 'args' && v == '+') {
-                [[args: org.apache.commons.cli.Option.UNLIMITED_VALUES]]
-            } else if (k == 'args' && v == '*') {
-                [[args: org.apache.commons.cli.Option.UNLIMITED_VALUES,
-                  optionalArg: true]]
-            } else if (k == 'args' && v instanceof String) {
-                [[args: Integer.parseInt(v)]]
-            } else {
-                [[(k): v]]
-            }
-        }.sum()
-    }
-
-    static expandArgumentFiles(args) throws IOException {
-        def result = []
-        for (arg in args) {
-            if (arg && arg != '@' && arg[0] == '@') {
-                arg = arg.substring(1)
-                if (arg[0] != '@') {
-                    expandArgumentFile(arg, result)
-                    continue
-                }
-            }
-            result << arg
-        }
-        return result
-    }
-
-    private static expandArgumentFile(name, args) throws IOException {
-        def charAsInt = { String s -> s.toCharacter() as int }
-        new File(name).withReader { r ->
-            new StreamTokenizer(r).with {
-                resetSyntax()
-                wordChars(charAsInt(' '), 255)
-                whitespaceChars(0, charAsInt(' '))
-                commentChar(charAsInt('#'))
-                quoteChar(charAsInt('"'))
-                quoteChar(charAsInt('\''))
-                while (nextToken() != StreamTokenizer.TT_EOF) {
-                    args << sval
-                }
-            }
-        }
-    }
-
-}
-
-class OptionAccessor {
-    CommandLine commandLine
-    Map<String, TypedOption> savedTypeOptions
-
-    OptionAccessor(CommandLine commandLine) {
-        this.commandLine = commandLine
-    }
-
-    boolean hasOption(TypedOption typedOption) {
-        commandLine.hasOption(typedOption.longOpt ?: typedOption.opt)
-    }
-
-    public <T> T defaultValue(String name) {
-        Class<T> type = savedTypeOptions[name]?.type
-        String value = savedTypeOptions[name]?.defaultValue() ? savedTypeOptions[name].defaultValue() : null
-        return (T) value ? getTypedValue(type, name, value) : null
-    }
-
-    public <T> T getOptionValue(TypedOption<T> typedOption) {
-        getOptionValue(typedOption, null)
-    }
-
-    public <T> T getOptionValue(TypedOption<T> typedOption, T defaultValue) {
-        String optionName = (String) typedOption.longOpt ?: typedOption.opt
-        if (commandLine.hasOption(optionName)) {
-            if (typedOption.containsKey('type') && typedOption.type.isArray()) {
-                def compType = typedOption.type.componentType
-                return (T) getTypedValuesFromName(optionName, compType)
-            }
-            return getTypedValueFromName(optionName)
-        }
-        return defaultValue
-    }
-
-    private <T> T[] getTypedValuesFromName(String optionName, Class<T> compType) {
-        CliOption option = commandLine.options.find{ it.longOpt == optionName }
-        T[] result = null
-        if (option) {
-            int count = 0
-            def optionValues = commandLine.getOptionValues(optionName)
-            for (String optionValue : optionValues) {
-                if (result == null) {
-                    result = (T[]) Array.newInstance(compType, optionValues.length)
-                }
-                result[count++] = (T) getTypedValue(compType, optionName, optionValue)
-            }
-        }
-        if (result == null) {
-            result = (T[]) Array.newInstance(compType, 0)
-        }
-        return result
-    }
-
-    public <T> T getAt(TypedOption<T> typedOption) {
-        getAt(typedOption, null)
-    }
-
-    public <T> T getAt(TypedOption<T> typedOption, T defaultValue) {
-        String optionName = (String) typedOption.longOpt ?: typedOption.opt
-        if (savedTypeOptions.containsKey(optionName)) {
-            return getTypedValueFromName(optionName)
-        }
-        return defaultValue
-    }
-
-    private <T> T getTypedValueFromName(String optionName) {
-        Class type = savedTypeOptions[optionName].type
-        String optionValue = commandLine.getOptionValue(optionName)
-        return (T) getTypedValue(type, optionName, optionValue)
-    }
-
-    private <T> T getTypedValue(Class<T> type, String optionName, String optionValue) {
-        if (savedTypeOptions[optionName]?.cliOption?.numberOfArgs == 0) {
-            return (T) commandLine.hasOption(optionName)
-        }
-        def convert = savedTypeOptions[optionName]?.convert
-        return getValue(type, optionValue, convert)
-    }
-
-    private <T> T getValue(Class<T> type, String optionValue, Closure convert) {
-        if (!type) {
-            return (T) optionValue
-        }
-        if (Closure.isAssignableFrom(type) && convert) {
-            return (T) convert(optionValue)
-        }
-        if (type?.simpleName?.toLowerCase() == 'boolean') {
-            return (T) Boolean.parseBoolean(optionValue)
-        }
-        StringGroovyMethods.asType(optionValue, (Class<T>) type)
-    }
-
-    def invokeMethod(String name, Object args) {
-        return InvokerHelper.getMetaClass(commandLine).invokeMethod(commandLine, name, args)
-    }
-
-    def getProperty(String name) {
-        if (!savedTypeOptions.containsKey(name)) {
-            def alt = savedTypeOptions.find{ it.value.opt == name }
-            if (alt) name = alt.key
-        }
-        def methodname = 'getOptionValue'
-        Class type = savedTypeOptions[name]?.type
-        def foundArray = type?.isArray()
-        if (name.size() > 1 && name.endsWith('s')) {
-            def singularName = name[0..-2]
-            if (commandLine.hasOption(singularName) || foundArray) {
-                name = singularName
-                methodname += 's'
-                type = savedTypeOptions[name]?.type
-            }
-        }
-        if (type?.isArray()) {
-            methodname = 'getOptionValues'
-        }
-        if (name.size() == 1) name = name as char
-        def result = InvokerHelper.getMetaClass(commandLine).invokeMethod(commandLine, methodname, name)
-        if (result != null) {
-            if (result instanceof String[]) {
-                result = result.collect{ type ? getTypedValue(type.isArray() ? type.componentType : type, name, it) : it }
-            } else {
-                if (type) result = getTypedValue(type, name, result)
-            }
-        } else if (type?.simpleName != 'boolean' && savedTypeOptions[name]?.defaultValue) {
-            result = getTypedValue(type, name, savedTypeOptions[name].defaultValue)
-        } else {
-            result = commandLine.hasOption(name)
-        }
-        return result
-    }
-
-    List<String> arguments() {
-        commandLine.args.toList()
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ClosureComparator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ClosureComparator.java b/src/main/groovy/util/ClosureComparator.java
deleted file mode 100644
index dc70ea6..0000000
--- a/src/main/groovy/util/ClosureComparator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * A Comparator which uses a closure to compare 2 values being equal
- * 
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class ClosureComparator<T> implements Comparator<T>, Serializable {
-
-    private static final long serialVersionUID = -4593521535656429522L;
-    Closure closure;
-
-    public ClosureComparator(Closure closure) {
-        this.closure = closure;
-    }
-
-    public int compare(T object1, T object2) {
-        Object value = closure.call(object1, object2);
-        return DefaultTypeTransformation.intUnbox(value);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ConfigObject.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ConfigObject.java b/src/main/groovy/util/ConfigObject.java
deleted file mode 100644
index c76bc97..0000000
--- a/src/main/groovy/util/ConfigObject.java
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.Writable;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.StringGroovyMethods;
-import org.codehaus.groovy.syntax.Types;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URL;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * A ConfigObject at a simple level is a Map that creates configuration entries (other ConfigObjects) when referencing them.
- * This means that navigating to foo.bar.stuff will not return null but nested ConfigObjects which are of course empty maps
- * The Groovy truth can be used to check for the existence of "real" entries.
- *
- * @author Graeme Rocher
- * @author Guillaume Laforge (rewrite in Java related to security constraints on Google App Engine)
- * @since 1.5
- */
-public class ConfigObject extends GroovyObjectSupport implements Writable, Map, Cloneable {
-
-    static final Collection<String> KEYWORDS = Types.getKeywords();
-
-    static final String TAB_CHARACTER = "\t";
-
-    /**
-     * The config file that was used when parsing this ConfigObject
-     */
-    private URL configFile;
-
-    private HashMap delegateMap = new LinkedHashMap();
-
-    public ConfigObject(URL file) {
-        this.configFile = file;
-    }
-
-    public ConfigObject() {
-        this(null);
-    }
-
-    public URL getConfigFile() {
-        return configFile;
-    }
-
-    public void setConfigFile(URL configFile) {
-        this.configFile = configFile;
-    }
-
-    /**
-     * Writes this config object into a String serialized representation which can later be parsed back using the parse()
-     * method
-     *
-     * @see groovy.lang.Writable#writeTo(java.io.Writer)
-     */
-    public Writer writeTo(Writer outArg) throws IOException {
-        BufferedWriter out = new BufferedWriter(outArg);
-        try {
-            writeConfig("", this, out, 0, false);
-        } finally {
-            out.flush();
-        }
-
-        return outArg;
-    }
-
-
-    /**
-     * Overrides the default getProperty implementation to create nested ConfigObject instances on demand
-     * for non-existent keys
-     */
-    public Object getProperty(String name) {
-        if ("configFile".equals(name))
-            return this.configFile;
-
-        if (!containsKey(name)) {
-            ConfigObject prop = new ConfigObject(this.configFile);
-            put(name, prop);
-
-            return prop;
-        }
-
-        return get(name);
-    }
-
-    /**
-     * A ConfigObject is a tree structure consisting of nested maps. This flattens the maps into
-     * a single level structure like a properties file
-     */
-    public Map flatten() {
-        return flatten(null);
-    }
-
-    /**
-     * Flattens this ConfigObject populating the results into the target Map
-     *
-     * @see ConfigObject#flatten()
-     */
-    public Map flatten(Map target) {
-        if (target == null)
-            target = new ConfigObject();
-        populate("", target, this);
-
-        return target;
-    }
-
-    /**
-     * Merges the given map with this ConfigObject overriding any matching configuration entries in this ConfigObject
-     *
-     * @param other The ConfigObject to merge with
-     * @return The result of the merge
-     */
-    public Map merge(ConfigObject other) {
-        return doMerge(this, other);
-    }
-
-
-    /**
-     * Converts this ConfigObject into a the java.util.Properties format, flattening the tree structure beforehand
-     *
-     * @return A java.util.Properties instance
-     */
-    public Properties toProperties() {
-        Properties props = new Properties();
-        flatten(props);
-
-        props = convertValuesToString(props);
-
-        return props;
-    }
-
-    /**
-     * Converts this ConfigObject ino the java.util.Properties format, flatten the tree and prefixing all entries with the given prefix
-     *
-     * @param prefix The prefix to append before property entries
-     * @return A java.util.Properties instance
-     */
-    public Properties toProperties(String prefix) {
-        Properties props = new Properties();
-        populate(prefix + ".", props, this);
-
-        props = convertValuesToString(props);
-
-        return props;
-    }
-
-    private Map doMerge(Map config, Map other) {
-        for (Object o : other.entrySet()) {
-            Map.Entry next = (Map.Entry) o;
-            Object key = next.getKey();
-            Object value = next.getValue();
-
-            Object configEntry = config.get(key);
-
-            if (configEntry == null) {
-                config.put(key, value);
-
-                continue;
-            } else {
-                if (configEntry instanceof Map && !((Map) configEntry).isEmpty() && value instanceof Map) {
-                    // recur
-                    doMerge((Map) configEntry, (Map) value);
-                } else {
-                    config.put(key, value);
-                }
-            }
-        }
-
-        return config;
-    }
-
-    private void writeConfig(String prefix, ConfigObject map, BufferedWriter out, int tab, boolean apply) throws IOException {
-        String space = apply ? StringGroovyMethods.multiply(TAB_CHARACTER, tab) : "";
-
-        for (Object o1 : map.keySet()) {
-            String key = (String) o1;
-            Object v = map.get(key);
-
-            if (v instanceof ConfigObject) {
-                ConfigObject value = (ConfigObject) v;
-
-                if (!value.isEmpty()) {
-
-                    Object dotsInKeys = null;
-                    for (Object o : value.entrySet()) {
-                        Entry e = (Entry) o;
-                        String k = (String) e.getKey();
-                        if (k.indexOf('.') > -1) {
-                            dotsInKeys = e;
-                            break;
-                        }
-                    }
-
-                    int configSize = value.size();
-                    Object firstKey = value.keySet().iterator().next();
-                    Object firstValue = value.values().iterator().next();
-
-                    int firstSize;
-                    if (firstValue instanceof ConfigObject) {
-                        firstSize = ((ConfigObject) firstValue).size();
-                    } else {
-                        firstSize = 1;
-                    }
-
-                    if (configSize == 1 || DefaultGroovyMethods.asBoolean(dotsInKeys)) {
-                        if (firstSize == 1 && firstValue instanceof ConfigObject) {
-                            key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
-                            String writePrefix = prefix + key + "." + firstKey + ".";
-                            writeConfig(writePrefix, (ConfigObject) firstValue, out, tab, true);
-                        } else if (!DefaultGroovyMethods.asBoolean(dotsInKeys) && firstValue instanceof ConfigObject) {
-                            writeNode(key, space, tab, value, out);
-                        } else {
-                            for (Object j : value.keySet()) {
-                                Object v2 = value.get(j);
-                                Object k2 = ((String) j).indexOf('.') > -1 ? InvokerHelper.inspect(j) : j;
-                                if (v2 instanceof ConfigObject) {
-                                    key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
-                                    writeConfig(prefix + key, (ConfigObject) v2, out, tab, false);
-                                } else {
-                                    writeValue(key + "." + k2, space, prefix, v2, out);
-                                }
-                            }
-                        }
-                    } else {
-                        writeNode(key, space, tab, value, out);
-                    }
-                }
-            } else {
-                writeValue(key, space, prefix, v, out);
-            }
-        }
-    }
-
-    private static void writeValue(String key, String space, String prefix, Object value, BufferedWriter out) throws IOException {
-//        key = key.indexOf('.') > -1 ? InvokerHelper.inspect(key) : key;
-        boolean isKeyword = KEYWORDS.contains(key);
-        key = isKeyword ? InvokerHelper.inspect(key) : key;
-
-        if (!StringGroovyMethods.asBoolean(prefix) && isKeyword) prefix = "this.";
-        out.append(space).append(prefix).append(key).append('=').append(InvokerHelper.inspect(value));
-        out.newLine();
-    }
-
-    private void writeNode(String key, String space, int tab, ConfigObject value, BufferedWriter out) throws IOException {
-        key = KEYWORDS.contains(key) ? InvokerHelper.inspect(key) : key;
-        out.append(space).append(key).append(" {");
-        out.newLine();
-        writeConfig("", value, out, tab + 1, true);
-        out.append(space).append('}');
-        out.newLine();
-    }
-
-    private static Properties convertValuesToString(Map props) {
-        Properties newProps = new Properties();
-
-        for (Object o : props.entrySet()) {
-            Map.Entry next = (Map.Entry) o;
-            Object key = next.getKey();
-            Object value = next.getValue();
-
-            newProps.put(key, value != null ? value.toString() : null);
-        }
-
-        return newProps;
-    }
-
-    private void populate(String suffix, Map config, Map map) {
-        for (Object o : map.entrySet()) {
-            Map.Entry next = (Map.Entry) o;
-            Object key = next.getKey();
-            Object value = next.getValue();
-
-            if (value instanceof Map) {
-                populate(suffix + key + ".", config, (Map) value);
-            } else {
-                try {
-                    config.put(suffix + key, value);
-                } catch (NullPointerException e) {
-                    // it is idiotic story but if config map doesn't allow null values (like Hashtable)
-                    // we can't do too much
-                }
-            }
-        }
-    }
-
-    public int size() {
-        return delegateMap.size();
-    }
-
-    public boolean isEmpty() {
-        return delegateMap.isEmpty();
-    }
-
-    public boolean containsKey(Object key) {
-        return delegateMap.containsKey(key);
-    }
-
-    public boolean containsValue(Object value) {
-        return delegateMap.containsValue(value);
-    }
-
-    public Object get(Object key) {
-        return delegateMap.get(key);
-    }
-
-    public Object put(Object key, Object value) {
-        return delegateMap.put(key, value);
-    }
-
-    public Object remove(Object key) {
-        return delegateMap.remove(key);
-    }
-
-    public void putAll(Map m) {
-        delegateMap.putAll(m);
-    }
-
-    public void clear() {
-        delegateMap.clear();
-    }
-
-    public Set keySet() {
-        return delegateMap.keySet();
-    }
-
-    public Collection values() {
-        return delegateMap.values();
-    }
-
-    public Set entrySet() {
-        return delegateMap.entrySet();
-    }
-
-    /**
-     * Returns a shallow copy of this ConfigObject, keys and configuration entries are not cloned.
-     * @return a shallow copy of this ConfigObject
-     */
-    public ConfigObject clone() {
-        try {
-            ConfigObject clone = (ConfigObject) super.clone();
-            clone.configFile = configFile;
-            clone.delegateMap = (LinkedHashMap) delegateMap.clone();
-            return clone;
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError();
-        }
-    }
-
-    /**
-     * Checks if a config option is set. Example usage:
-     * <pre class="groovyTestCase">
-     * def config = new ConfigSlurper().parse("foo { password='' }")
-     * assert config.foo.isSet('password')
-     * assert config.foo.isSet('username') == false
-     * </pre>
-     *
-     * The check works <b>only</v> for options <b>one</b> block below the current block.
-     * E.g. <code>config.isSet('foo.password')</code> will always return false.
-     *
-     * @param option The name of the option
-     * @return <code>true</code> if the option is set <code>false</code> otherwise
-     * @since 2.3.0
-     */
-    public Boolean isSet(String option) {
-        if (delegateMap.containsKey(option)) {
-            Object entry = delegateMap.get(option);
-            if (!(entry instanceof ConfigObject) || !((ConfigObject) entry).isEmpty()) {
-                return Boolean.TRUE;
-            }
-        }
-        return Boolean.FALSE;
-    }
-
-    public String prettyPrint() {
-        StringWriter sw = new StringWriter();
-        try {
-            writeTo(sw);
-        } catch (IOException e) {
-            throw new GroovyRuntimeException(e);
-        }
-
-        return sw.toString();
-    }
-
-    @Override
-    public String toString() {
-        StringWriter sw = new StringWriter();
-        try {
-            InvokerHelper.write(sw, this);
-        } catch (IOException e) {
-            throw new GroovyRuntimeException(e);
-        }
-
-        return sw.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ConfigSlurper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ConfigSlurper.groovy b/src/main/groovy/util/ConfigSlurper.groovy
deleted file mode 100644
index 20d0723..0000000
--- a/src/main/groovy/util/ConfigSlurper.groovy
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- *  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 groovy.util
-
-import org.codehaus.groovy.runtime.InvokerHelper
-
-/**
- * ConfigSlurper is a utility class for reading configuration files defined in the form of Groovy
- * scripts. Configuration settings can be defined using dot notation or scoped using closures:
- *
- * <pre><code>
- * grails.webflow.stateless = true
- * smtp {
- *     mail.host = 'smtp.myisp.com'
- *     mail.auth.user = 'server'
- * }
- * resources.URL = "http://localhost:80/resources"
- * </code></pre>
- *
- * Settings can either be bound into nested maps or onto a specified JavaBean instance.
- * In the latter case, an error will be thrown if a property cannot be bound.
- *
- * @author Graeme Rocher
- * @author Andres Almiray
- * @since 1.5
- */
-class ConfigSlurper {
-    private static final ENVIRONMENTS_METHOD = 'environments'
-    GroovyClassLoader classLoader = new GroovyClassLoader()
-    private Map bindingVars = [:]
-
-    private final Map<String, String> conditionValues = [:]
-    private final Stack<Map<String, ConfigObject>> conditionalBlocks = new Stack<Map<String,ConfigObject>>()
-
-    ConfigSlurper() {
-        this('')
-    }
-
-    /**
-     * Constructs a new ConfigSlurper instance using the given environment
-     *
-     * @param env The Environment to use
-     */
-    ConfigSlurper(String env) {
-        conditionValues[ENVIRONMENTS_METHOD] = env
-    }
-
-    void registerConditionalBlock(String blockName, String blockValue) {
-        if (blockName) {
-            if (!blockValue) {
-                conditionValues.remove(blockName)
-            } else {
-                conditionValues[blockName] = blockValue
-            }
-        }
-    }
-
-    Map<String, String> getConditionalBlockValues() {
-        Collections.unmodifiableMap(conditionValues)
-    }
-
-    String getEnvironment() {
-        return conditionValues[ENVIRONMENTS_METHOD]
-    }
-
-    void setEnvironment(String environment) {
-        conditionValues[ENVIRONMENTS_METHOD] = environment
-    }
-
-    /**
-     * Sets any additional variables that should be placed into the binding when evaluating Config scripts
-     */
-    void setBinding(Map vars) {
-        this.bindingVars = vars
-    }
-
-    /**
-     * Parses a ConfigObject instances from an instance of java.util.Properties
-     *
-     * @param The java.util.Properties instance
-     */
-    ConfigObject parse(Properties properties) {
-        ConfigObject config = new ConfigObject()
-        for (key in properties.keySet()) {
-            def tokens = key.split(/\./)
-
-            def current = config
-            def last
-            def lastToken
-            def foundBase = false
-            for (token in tokens) {
-                if (foundBase) {
-                    // handle not properly nested tokens by ignoring
-                    // hierarchy below this point
-                    lastToken += "." + token
-                    current = last
-                } else {
-                    last = current
-                    lastToken = token
-                    current = current."${token}"
-                    if (!(current instanceof ConfigObject)) foundBase = true
-                }
-            }
-
-            if (current instanceof ConfigObject) {
-                if (last[lastToken]) {
-                    def flattened = last.flatten()
-                    last.clear()
-                    flattened.each { k2, v2 -> last[k2] = v2 }
-                    last[lastToken] = properties.get(key)
-                }
-                else {
-                    last[lastToken] = properties.get(key)
-                }
-            }
-            current = config
-        }
-        return config
-    }
-    /**
-     * Parse the given script as a string and return the configuration object
-     *
-     * @see ConfigSlurper#parse(groovy.lang.Script)
-     */
-    ConfigObject parse(String script) {
-        return parse(classLoader.parseClass(script))
-    }
-
-    /**
-     * Create a new instance of the given script class and parse a configuration object from it
-     *
-     * @see ConfigSlurper#parse(groovy.lang.Script)
-     */
-    ConfigObject parse(Class scriptClass) {
-        return parse(scriptClass.newInstance())
-    }
-
-    /**
-     * Parse the given script into a configuration object (a Map)
-     * (This method creates a new class to parse the script each time it is called.)
-     *
-     * @param script The script to parse
-     * @return A Map of maps that can be navigating with dot de-referencing syntax to obtain configuration entries
-     */
-    ConfigObject parse(Script script) {
-        return parse(script, null)
-    }
-
-    /**
-     * Parses a Script represented by the given URL into a ConfigObject
-     *
-     * @param scriptLocation The location of the script to parse
-     * @return The ConfigObject instance
-     */
-    ConfigObject parse(URL scriptLocation) {
-        return parse(classLoader.parseClass(scriptLocation.text).newInstance(), scriptLocation)
-    }
-
-    /**
-     * Parses the passed groovy.lang.Script instance using the second argument to allow the ConfigObject
-     * to retain an reference to the original location other Groovy script
-     *
-     * @param script The groovy.lang.Script instance
-     * @param location The original location of the Script as a URL
-     * @return The ConfigObject instance
-     */
-    ConfigObject parse(Script script, URL location) {
-        Stack<String> currentConditionalBlock = new Stack<String>()
-        def config = location ? new ConfigObject(location) : new ConfigObject()
-        GroovySystem.metaClassRegistry.removeMetaClass(script.class)
-        def mc = script.class.metaClass
-        def prefix = ""
-        LinkedList stack = new LinkedList()
-        stack << [config: config, scope: [:]]
-        def pushStack = { co ->
-            stack << [config: co, scope: stack.last.scope.clone()]
-        }
-        def assignName = { name, co ->
-            def current = stack.last
-            current.config[name] = co
-            current.scope[name] = co
-        }
-        mc.getProperty = { String name ->
-            def current = stack.last
-            def result
-            if (current.config.get(name)) {
-                result = current.config.get(name)
-            } else if (current.scope[name]) {
-                result = current.scope[name]
-            } else {
-                try {
-                    result = InvokerHelper.getProperty(this, name)
-                } catch (GroovyRuntimeException e) {
-                    result = new ConfigObject()
-                    assignName.call(name, result)
-                }
-            }
-            result
-        }
-
-        ConfigObject overrides = new ConfigObject()
-        mc.invokeMethod = { String name, args ->
-            def result
-            if (args.length == 1 && args[0] instanceof Closure) {
-                if (name in conditionValues.keySet()) {
-                    try {
-                        currentConditionalBlock.push(name)
-                        conditionalBlocks.push([:])
-                        args[0].call()
-                    } finally {
-                        currentConditionalBlock.pop()
-                        for (entry in conditionalBlocks.pop().entrySet()) {
-                            def c = stack.last.config
-                            (c != config? c : overrides).merge(entry.value)
-                        }
-                    }
-                } else if (currentConditionalBlock.size() > 0) {
-                    String conditionalBlockKey = currentConditionalBlock.peek()
-                    if (name == conditionValues[conditionalBlockKey]) {
-                        def co = new ConfigObject()
-                        conditionalBlocks.peek()[conditionalBlockKey] = co
-
-                        pushStack.call(co)
-                        try {
-                            currentConditionalBlock.pop()
-                            args[0].call()
-                        } finally {
-                            currentConditionalBlock.push(conditionalBlockKey)
-                        }
-                        stack.removeLast()
-                    }
-                } else {
-                    def co
-                    if (stack.last.config.get(name) instanceof ConfigObject) {
-                        co = stack.last.config.get(name)
-                    } else {
-                        co = new ConfigObject()
-                    }
-
-                    assignName.call(name, co)
-                    pushStack.call(co)
-                    args[0].call()
-                    stack.removeLast()
-                }
-            } else if (args.length == 2 && args[1] instanceof Closure) {
-                try {
-                    prefix = name + '.'
-                    assignName.call(name, args[0])
-                    args[1].call()
-                } finally { prefix = "" }
-            } else {
-                MetaMethod mm = mc.getMetaMethod(name, args)
-                if (mm) {
-                    result = mm.invoke(delegate, args)
-                } else {
-                    throw new MissingMethodException(name, getClass(), args)
-                }
-            }
-            result
-        }
-        script.metaClass = mc
-
-        def setProperty = { String name, value ->
-            assignName.call(prefix + name, value)
-        }
-        def binding = new ConfigBinding(setProperty)
-        if (this.bindingVars) {
-            binding.getVariables().putAll(this.bindingVars)
-        }
-        script.binding = binding
-
-        script.run()
-
-        config.merge(overrides)
-
-        return config
-    }
-}
-
-/**
- * Since Groovy Script doesn't support overriding setProperty, we use a trick with the Binding to provide this
- * functionality
- */
-class ConfigBinding extends Binding {
-    def callable
-    ConfigBinding(Closure c) {
-        this.callable = c
-    }
-
-    void setVariable(String name, Object value) {
-        callable(name, value)
-    }
-}


[33/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/NumberRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/NumberRange.java b/src/main/groovy/groovy/lang/NumberRange.java
new file mode 100644
index 0000000..92c6195
--- /dev/null
+++ b/src/main/groovy/groovy/lang/NumberRange.java
@@ -0,0 +1,629 @@
+/*
+ * 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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.IteratorClosureAdapter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.AbstractList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEqual;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareGreaterThan;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareGreaterThanEqual;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThan;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThanEqual;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareNotEqual;
+import static org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareTo;
+import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberMinus.minus;
+import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberMultiply.multiply;
+import static org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus.plus;
+
+/**
+ * Represents an immutable list of Numbers from a value to a value with a particular step size.
+ *
+ * In general, it isn't recommended using a NumberRange as a key to a map. The range
+ * 0..3 is deemed to be equal to 0.0..3.0 but they have different hashCode values,
+ * so storing a value using one of these ranges couldn't be retrieved using the other.
+ *
+ * @since 2.5
+ */
+public class NumberRange extends AbstractList<Comparable> implements Range<Comparable> {
+
+    /**
+     * The first value in the range.
+     */
+    private final Comparable from;
+
+    /**
+     * The last value in the range.
+     */
+    private final Comparable to;
+
+    /**
+     * The step size in the range.
+     */
+    private final Number stepSize;
+
+    /**
+     * The cached size, or -1 if not yet computed
+     */
+    private int size = -1;
+
+    /**
+     * The cached hashCode (once calculated)
+     */
+    private Integer hashCodeCache = null;
+
+    /**
+     * <code>true</code> if the range counts backwards from <code>to</code> to <code>from</code>.
+     */
+    private final boolean reverse;
+
+    /**
+     * <code>true</code> if the range includes the upper bound.
+     */
+    private final boolean inclusive;
+
+    /**
+     * Creates an inclusive {@link NumberRange} with step size 1.
+     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
+     *
+     * @param from the first value in the range
+     * @param to   the last value in the range
+     */
+    public <T extends Number & Comparable, U extends Number & Comparable>
+    NumberRange(T from, U to) {
+        this(from, to, null, true);
+    }
+
+    /**
+     * Creates a new {@link NumberRange} with step size 1.
+     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
+     *
+     * @param from start of the range
+     * @param to   end of the range
+     * @param inclusive whether the range is inclusive
+     */
+    public <T extends Number & Comparable, U extends Number & Comparable>
+    NumberRange(T from, U to, boolean inclusive) {
+        this(from, to, null, inclusive);
+    }
+
+    /**
+     * Creates an inclusive {@link NumberRange}.
+     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
+     *
+     * @param from start of the range
+     * @param to   end of the range
+     * @param stepSize the gap between discrete elements in the range
+     */
+    public <T extends Number & Comparable, U extends Number & Comparable, V extends
+            Number & Comparable<? super Number>>
+    NumberRange(T from, U to, V stepSize) {
+        this(from, to, stepSize, true);
+    }
+
+    /**
+     * Creates a {@link NumberRange}.
+     * Creates a reversed range if <code>from</code> &lt; <code>to</code>.
+     *
+     * @param from start of the range
+     * @param to   end of the range
+     * @param stepSize the gap between discrete elements in the range
+     * @param inclusive whether the range is inclusive
+     */
+    public <T extends Number & Comparable, U extends Number & Comparable, V extends
+            Number & Comparable>
+    NumberRange(T from, U to, V stepSize, boolean inclusive) {
+        if (from == null) {
+            throw new IllegalArgumentException("Must specify a non-null value for the 'from' index in a Range");
+        }
+        if (to == null) {
+            throw new IllegalArgumentException("Must specify a non-null value for the 'to' index in a Range");
+        }
+        reverse = areReversed(from, to);
+        Number tempFrom;
+        Number tempTo;
+        if (reverse) {
+            tempFrom = to;
+            tempTo = from;
+        } else {
+            tempFrom = from;
+            tempTo = to;
+        }
+        if (tempFrom instanceof Short) {
+            tempFrom = tempFrom.intValue();
+        } else if (tempFrom instanceof Float) {
+            tempFrom = tempFrom.doubleValue();
+        }
+        if (tempTo instanceof Short) {
+            tempTo = tempTo.intValue();
+        } else if (tempTo instanceof Float) {
+            tempTo = tempTo.doubleValue();
+        }
+
+        if (tempFrom instanceof Integer && tempTo instanceof Long) {
+            tempFrom = tempFrom.longValue();
+        } else if (tempTo instanceof Integer && tempFrom instanceof Long) {
+            tempTo = tempTo.longValue();
+        }
+
+        this.from = (Comparable) tempFrom;
+        this.to = (Comparable) tempTo;
+        this.stepSize = stepSize == null ? 1 : stepSize;
+        this.inclusive = inclusive;
+    }
+
+    /**
+     * For a NumberRange with step size 1, creates a new NumberRange with the same
+     * <code>from</code> and <code>to</code> as this NumberRange
+     * but with a step size of <code>stepSize</code>.
+     *
+     * @param stepSize the desired step size
+     * @return a new NumberRange
+     */
+    public <T extends Number & Comparable> NumberRange by(T stepSize) {
+        if (!Integer.valueOf(1).equals(this.stepSize)) {
+            throw new IllegalStateException("by only allowed on ranges with original stepSize = 1 but found " + this.stepSize);
+        }
+        return new NumberRange(comparableNumber(from), comparableNumber(to), stepSize, inclusive);
+    }
+
+    @SuppressWarnings("unchecked")
+    /* package private */ static <T extends Number & Comparable> T comparableNumber(Comparable c) {
+        return (T) c;
+    }
+
+    @SuppressWarnings("unchecked")
+    /* package private */ static <T extends Number & Comparable> T comparableNumber(Number n) {
+        return (T) n;
+    }
+
+    private static boolean areReversed(Number from, Number to) {
+        try {
+            return compareGreaterThan(from, to);
+        } catch (ClassCastException cce) {
+            throw new IllegalArgumentException("Unable to create range due to incompatible types: " + from.getClass().getSimpleName() + ".." + to.getClass().getSimpleName() + " (possible missing brackets around range?)", cce);
+        }
+    }
+
+    /**
+     * An object is deemed equal to this NumberRange if it represents a List of items and
+     * those items equal the list of discrete items represented by this NumberRange.
+     *
+     * @param that the object to be compared for equality with this NumberRange
+     * @return {@code true} if the specified object is equal to this NumberRange
+     * @see #fastEquals(NumberRange)
+     */
+    @Override
+    public boolean equals(Object that) {
+        return super.equals(that);
+    }
+
+    /**
+     * A NumberRange's hashCode is based on hashCode values of the discrete items it represents.
+     *
+     * @return the hashCode value
+     */
+    @Override
+    public int hashCode() {
+        if (hashCodeCache == null) {
+            hashCodeCache = super.hashCode();
+        }
+        return hashCodeCache;
+    }
+
+    /*
+     * NOTE: as per the class javadoc, this class doesn't obey the normal equals/hashCode contract.
+     * The following field and method could assist some scenarios which required a similar sort of contract
+     * (but between equals and the custom canonicalHashCode). Currently commented out since we haven't
+     * found a real need. We will likely remove this commented out code if no usage is identified soon.
+     */
+
+    /*
+     * The cached canonical hashCode (once calculated)
+     */
+//    private Integer canonicalHashCodeCache = null;
+
+    /*
+     * A NumberRange's canonicalHashCode is based on hashCode values of the discrete items it represents.
+     * When two NumberRange's are equal they will have the same canonicalHashCode value.
+     * Numerical values which Groovy deems equal have the same hashCode during this calculation.
+     * So currently (0..3).equals(0.0..3.0) yet they have different hashCode values. This breaks
+     * the normal equals/hashCode contract which is a weakness in Groovy's '==' operator. However
+     * the contract isn't broken between equals and canonicalHashCode.
+     *
+     * @return the hashCode value
+     */
+//    public int canonicalHashCode() {
+//        if (canonicalHashCodeCache == null) {
+//            int hashCode = 1;
+//            for (Comparable e : this) {
+//                int value;
+//                if (e == null) {
+//                    value = 0;
+//                } else {
+//                    BigDecimal next = new BigDecimal(e.toString());
+//                    if (next.compareTo(BigDecimal.ZERO) == 0) {
+//                        // workaround on pre-Java8 for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6480539
+//                        value = BigDecimal.ZERO.hashCode();
+//                    } else {
+//                        value = next.stripTrailingZeros().hashCode();
+//                    }
+//                }
+//                hashCode = 31 * hashCode + value;
+//            }
+//            canonicalHashCodeCache = hashCode;
+//        }
+//        return canonicalHashCodeCache;
+//    }
+
+    /**
+     * Compares a {@link NumberRange} to another {@link NumberRange} using only a strict comparison
+     * of the NumberRange properties. This won't return true for some ranges which represent the same
+     * discrete items, use equals instead for that but will be much faster for large lists.
+     *
+     * @param that the NumberRange to check equality with
+     * @return <code>true</code> if the ranges are equal
+     */
+    public boolean fastEquals(NumberRange that) {
+        return that != null
+                && reverse == that.reverse
+                && inclusive == that.inclusive
+                && compareEqual(from, that.from)
+                && compareEqual(to, that.to)
+                && compareEqual(stepSize, that.stepSize);
+    }
+
+    /*
+     * NOTE: as per the class javadoc, this class doesn't obey the normal equals/hashCode contract.
+     * The following field and method could assist some scenarios which required a similar sort of contract
+     * (but between fastEquals and the custom fastHashCode). Currently commented out since we haven't
+     * found a real need. We will likely remove this commented out code if no usage is identified soon.
+     */
+
+    /*
+     * The cached fast hashCode (once calculated)
+     */
+//    private Integer fastHashCodeCache = null;
+
+    /*
+     * A hashCode function that pairs with fastEquals, following the normal equals/hashCode contract.
+     *
+     * @return the calculated hash code
+     */
+//    public int fastHashCode() {
+//        if (fastHashCodeCache == null) {
+//            int result = 17;
+//            result = result * 31 + (reverse ? 1 : 0);
+//            result = result * 31 + (inclusive ? 1 : 0);
+//            result = result * 31 + new BigDecimal(from.toString()).stripTrailingZeros().hashCode();
+//            result = result * 31 + new BigDecimal(to.toString()).stripTrailingZeros().hashCode();
+//            result = result * 31 + new BigDecimal(stepSize.toString()).stripTrailingZeros().hashCode();
+//            fastHashCodeCache = result;
+//        }
+//        return fastHashCodeCache;
+//    }
+
+    @Override
+    public Comparable getFrom() {
+        return from;
+    }
+
+    @Override
+    public Comparable getTo() {
+        return to;
+    }
+
+    public Comparable getStepSize() {
+        return (Comparable) stepSize;
+    }
+
+    @Override
+    public boolean isReverse() {
+        return reverse;
+    }
+
+    @Override
+    public Comparable get(int index) {
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
+        }
+        final Iterator<Comparable> iter = new StepIterator(this, stepSize);
+
+        Comparable value = iter.next();
+        for (int i = 0; i < index; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + index + " is too big for range: " + this);
+            }
+            value = iter.next();
+        }
+        return value;
+    }
+
+    /**
+     * Checks whether a value is between the from and to values of a Range
+     *
+     * @param value the value of interest
+     * @return true if the value is within the bounds
+     */
+    @Override
+    public boolean containsWithinBounds(Object value) {
+        final int result = compareTo(from, value);
+        return result == 0 || result < 0 && compareTo(to, value) >= 0;
+    }
+
+    /**
+     * protection against calls from Groovy
+     */
+    @SuppressWarnings("unused")
+    private void setSize(int size) {
+        throw new UnsupportedOperationException("size must not be changed");
+    }
+
+    @Override
+    public int size() {
+        if (size == -1) {
+            calcSize(from, to, stepSize);
+        }
+        return size;
+    }
+
+    void calcSize(Comparable from, Comparable to, Number stepSize) {
+        int tempsize = 0;
+        boolean shortcut = false;
+        if (isIntegral(stepSize)) {
+            if ((from instanceof Integer || from instanceof Long)
+                    && (to instanceof Integer || to instanceof Long)) {
+                // let's fast calculate the size
+                final BigInteger fromNum = new BigInteger(from.toString());
+                final BigInteger toTemp = new BigInteger(to.toString());
+                final BigInteger toNum = inclusive ? toTemp : toTemp.subtract(BigInteger.ONE);
+                final BigInteger sizeNum = new BigDecimal(toNum.subtract(fromNum)).divide(new BigDecimal(stepSize.longValue()), BigDecimal.ROUND_DOWN).toBigInteger().add(BigInteger.ONE);
+                tempsize = sizeNum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == -1 ? sizeNum.intValue() : Integer.MAX_VALUE;
+                shortcut = true;
+            } else if (((from instanceof BigDecimal || from instanceof BigInteger) && to instanceof Number) ||
+                    ((to instanceof BigDecimal || to instanceof BigInteger) && from instanceof Number)) {
+                // let's fast calculate the size
+                final BigDecimal fromNum = new BigDecimal(from.toString());
+                final BigDecimal toTemp = new BigDecimal(to.toString());
+                final BigDecimal toNum = inclusive ? toTemp : toTemp.subtract(new BigDecimal("1.0"));
+                final BigInteger sizeNum = toNum.subtract(fromNum).divide(new BigDecimal(stepSize.longValue()), BigDecimal.ROUND_DOWN).toBigInteger().add(BigInteger.ONE);
+                tempsize = sizeNum.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == -1 ? sizeNum.intValue() : Integer.MAX_VALUE;
+                shortcut = true;
+            }
+        }
+        if (!shortcut) {
+            // let's brute-force calculate the size by iterating start to end
+            final Iterator iter = new StepIterator(this, stepSize);
+            while (iter.hasNext()) {
+                tempsize++;
+                // integer overflow
+                if (tempsize < 0) {
+                    break;
+                }
+                iter.next();
+            }
+            // integer overflow
+            if (tempsize < 0) {
+                tempsize = Integer.MAX_VALUE;
+            }
+        }
+        size = tempsize;
+    }
+
+    private boolean isIntegral(Number stepSize) {
+        BigDecimal tempStepSize = new BigDecimal(stepSize.toString());
+        return tempStepSize.equals(new BigDecimal(tempStepSize.toBigInteger()));
+    }
+
+    @Override
+    public List<Comparable> subList(int fromIndex, int toIndex) {
+        if (fromIndex < 0) {
+            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+        }
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex == toIndex) {
+            return new EmptyRange<Comparable>(from);
+        }
+
+        // Performance detail:
+        // not using get(fromIndex), get(toIndex) in the following to avoid stepping over elements twice
+        final Iterator<Comparable> iter = new StepIterator(this, stepSize);
+
+        Comparable value = iter.next();
+        int i = 0;
+        for (; i < fromIndex; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
+            }
+            value = iter.next();
+        }
+        final Comparable fromValue = value;
+        for (; i < toIndex - 1; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
+            }
+            value = iter.next();
+        }
+        final Comparable toValue = value;
+
+        return new NumberRange(comparableNumber(fromValue), comparableNumber(toValue), comparableNumber(stepSize), true);
+    }
+
+    @Override
+    public String toString() {
+        return getToString(to.toString(), from.toString());
+    }
+
+    @Override
+    public String inspect() {
+        return getToString(InvokerHelper.inspect(to), InvokerHelper.inspect(from));
+    }
+
+    private String getToString(String toText, String fromText) {
+        String sep = inclusive ? ".." : "..<";
+        String base = reverse ? "" + toText + sep + fromText : "" + fromText + sep + toText;
+        return Integer.valueOf(1).equals(stepSize) ? base : base + ".by(" + stepSize + ")";
+    }
+
+    /**
+     * iterates over all values and returns true if one value matches.
+     * Also see containsWithinBounds.
+     */
+    @Override
+    public boolean contains(Object value) {
+        if (value == null) {
+            return false;
+        }
+        final Iterator it = new StepIterator(this, stepSize);
+        while (it.hasNext()) {
+            if (compareEqual(value, it.next())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void step(int numSteps, Closure closure) {
+        if (numSteps == 0 && compareTo(from, to) == 0) {
+            return; // from == to and step == 0, nothing to do, so return
+        }
+        final StepIterator iter = new StepIterator(this, multiply(numSteps, stepSize));
+        while (iter.hasNext()) {
+            closure.call(iter.next());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterator<Comparable> iterator() {
+        return new StepIterator(this, stepSize);
+    }
+
+    /**
+     * convenience class to serve in other methods.
+     * It's not thread-safe, and lazily produces the next element only on calls of hasNext() or next()
+     */
+    private class StepIterator implements Iterator<Comparable> {
+        private final NumberRange range;
+        private final Number step;
+        private final boolean isAscending;
+
+        private boolean isNextFetched = false;
+        private Comparable next = null;
+
+        StepIterator(NumberRange range, Number step) {
+            if (compareEqual(step, 0) && compareNotEqual(range.getFrom(), range.getTo())) {
+                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
+            }
+
+            this.range = range;
+            if (compareLessThan(step, 0)) {
+                this.step = multiply(step, -1);
+                isAscending = range.isReverse();
+            } else {
+                this.step = step;
+                isAscending = !range.isReverse();
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            fetchNextIfNeeded();
+            return (next != null) && (isAscending
+                    ? (range.inclusive ? compareLessThanEqual(next, range.getTo()) : compareLessThan(next, range.getTo()))
+                    : (range.inclusive ? compareGreaterThanEqual(next, range.getFrom()) : compareGreaterThan(next, range.getFrom())));
+        }
+
+        @Override
+        public Comparable next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            fetchNextIfNeeded();
+            isNextFetched = false;
+            return next;
+        }
+
+        private void fetchNextIfNeeded() {
+            if (!isNextFetched) {
+                isNextFetched = true;
+
+                if (next == null) {
+                    // make the first fetch lazy too
+                    next = isAscending ? range.getFrom() : range.getTo();
+                } else {
+                    next = isAscending ? increment(next, step) : decrement(next, step);
+                }
+            }
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public List<Comparable> step(int numSteps) {
+        final IteratorClosureAdapter<Comparable> adapter = new IteratorClosureAdapter<Comparable>(this);
+        step(numSteps, adapter);
+        return adapter.asList();
+    }
+
+    /**
+     * Increments by given step
+     *
+     * @param value the value to increment
+     * @param step the amount to increment
+     * @return the incremented value
+     */
+    @SuppressWarnings("unchecked")
+    private Comparable increment(Object value, Number step) {
+        return (Comparable) plus((Number) value, step);
+    }
+
+    /**
+     * Decrements by given step
+     *
+     * @param value the value to decrement
+     * @param step the amount to decrement
+     * @return the decremented value
+     */
+    @SuppressWarnings("unchecked")
+    private Comparable decrement(Object value, Number step) {
+        return (Comparable) minus((Number) value, step);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ObjectRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ObjectRange.java b/src/main/groovy/groovy/lang/ObjectRange.java
new file mode 100644
index 0000000..a7e2b05
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ObjectRange.java
@@ -0,0 +1,539 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.IteratorClosureAdapter;
+import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.AbstractList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Represents an inclusive list of objects from a value to a value using
+ * comparators.
+ * <p>
+ * Note: This class is similar to {@link IntRange}. If you make any changes to this
+ * class, you might consider making parallel changes to {@link IntRange}.
+ */
+public class ObjectRange extends AbstractList<Comparable> implements Range<Comparable> {
+    /**
+     * The first value in the range.
+     */
+    private final Comparable from;
+
+    /**
+     * The last value in the range.
+     */
+    private final Comparable to;
+
+    /**
+     * The cached size, or -1 if not yet computed
+     */
+    private int size = -1;
+
+    /**
+     * <code>true</code> if the range counts backwards from <code>to</code> to <code>from</code>.
+     */
+    private final boolean reverse;
+
+    /**
+     * Creates a new {@link ObjectRange}. Creates a reversed range if
+     * <code>from</code> &lt; <code>to</code>.
+     *
+     * @param from the first value in the range.
+     * @param to   the last value in the range.
+     */
+    public ObjectRange(Comparable from, Comparable to) {
+        this(from, to, null);
+    }
+
+    /**
+     * Creates a new {@link ObjectRange} assumes smaller &lt;&#61; larger, else behavior is undefined.
+     * Caution: Prefer the other constructor when in doubt.
+     * <p>
+     * Optimized Constructor avoiding initial computation of comparison.
+     */
+    public ObjectRange(Comparable smaller, Comparable larger, boolean reverse) {
+        this(smaller, larger, (Boolean) reverse);
+    }
+
+    /**
+     * Constructs a Range, computing reverse if not provided. When providing reverse,
+     * 'smaller' must not be larger than 'larger'.
+     *
+     * @param smaller start of the range, must no be larger than to when reverse != null
+     * @param larger  end of the range, must be larger than from when reverse != null
+     * @param reverse direction of the range. If null, causes direction to be computed (can be expensive).
+     */
+    private ObjectRange(Comparable smaller, Comparable larger, Boolean reverse) {
+        if (smaller == null) {
+            throw new IllegalArgumentException("Must specify a non-null value for the 'from' index in a Range");
+        }
+        if (larger == null) {
+            throw new IllegalArgumentException("Must specify a non-null value for the 'to' index in a Range");
+        }
+        if (reverse == null) {
+            final boolean computedReverse = areReversed(smaller, larger);
+            // ensure invariant from <= to
+            if (computedReverse) {
+                final Comparable temp = larger;
+                larger = smaller;
+                smaller = temp;
+            }
+            this.reverse = computedReverse;
+        } else {
+            this.reverse = reverse;
+        }
+
+        if (smaller instanceof Short) {
+            smaller = ((Short) smaller).intValue();
+        } else if (smaller instanceof Float) {
+            smaller = ((Float) smaller).doubleValue();
+        }
+        if (larger instanceof Short) {
+            larger = ((Short) larger).intValue();
+        } else if (larger instanceof Float) {
+            larger = ((Float) larger).doubleValue();
+        }
+
+        if (smaller instanceof Integer && larger instanceof Long) {
+            smaller = ((Integer) smaller).longValue();
+        } else if (larger instanceof Integer && smaller instanceof Long) {
+            larger = ((Integer) larger).longValue();
+        }
+
+        /*
+            areReversed() already does an implicit type compatibility check
+            based on DefaultTypeTransformation.compareToWithEqualityCheck() for mixed classes
+            but it is only invoked if reverse == null.
+            So Object Range has to perform those type checks for consistency even when not calling
+            compareToWithEqualityCheck(), and ObjectRange has
+            to use the normalized value used in a successful comparison in
+            compareToWithEqualityCheck(). Currently that means Chars and single-char Strings
+            are evaluated as the char's charValue (an integer) when compared to numbers.
+            So '7'..'9' should produce ['7', '8', '9'], whereas ['7'..9] and [7..'9'] should produce [55, 56, 57].
+            if classes match, or both numerical, no checks possible / necessary
+        */
+        if (smaller.getClass() == larger.getClass() ||
+                (smaller instanceof Number && larger instanceof Number)) {
+            this.from = smaller;
+            this.to = larger;
+        } else {
+            // Convenience hack: try convert single-char strings to ints
+            final Comparable tempfrom = normaliseStringType(smaller);
+            final Comparable tempto = normaliseStringType(larger);
+            // if after normalizing both are numbers, assume intended range was numbers
+            if (tempfrom instanceof Number && tempto instanceof Number) {
+                this.from = tempfrom;
+                this.to = tempto;
+            } else {
+                // if convenience hack did not make classes match,
+                // throw exception when starting with known class, and thus "from" cannot be advanced over "to".
+                // Note if start is an unusual Object, it could have a next() method
+                // that yields a Number or String to close the range
+                final Comparable start = this.reverse ? larger : smaller;
+                if (start instanceof String || start instanceof Number) {
+                    // starting with number will never reach a non-number, same for string
+                    throw new IllegalArgumentException("Incompatible Argument classes for ObjectRange " + smaller.getClass() + ", " + larger.getClass());
+                }
+                // Since normalizing did not help, use original values at user's risk
+                this.from = smaller;
+                this.to = larger;
+            }
+        }
+        checkBoundaryCompatibility();
+    }
+
+    /**
+     * throws IllegalArgumentException if to and from are incompatible, meaning they e.g. (likely) produce infinite sequences.
+     * Called at construction time, subclasses may override cautiously (using only members to and from).
+     */
+    protected void checkBoundaryCompatibility() {
+        if (from instanceof String && to instanceof String) {
+            // this test depends deeply on the String.next implementation
+            // 009.next is 00:, not 010
+            final String start = from.toString();
+            final String end = to.toString();
+            if (start.length() != end.length()) {
+                throw new IllegalArgumentException("Incompatible Strings for Range: different length");
+            }
+            final int length = start.length();
+            int i;
+            for (i = 0; i < length; i++) {
+                if (start.charAt(i) != end.charAt(i)) {
+                    break;
+                }
+            }
+            // strings must be equal except for the last character
+            if (i < length - 1) {
+                throw new IllegalArgumentException("Incompatible Strings for Range: String#next() will not reach the expected value");
+            }
+        }
+    }
+
+    private static boolean areReversed(Comparable from, Comparable to) {
+        try {
+            return ScriptBytecodeAdapter.compareGreaterThan(from, to);
+        } catch (IllegalArgumentException iae) {
+            throw new IllegalArgumentException("Unable to create range due to incompatible types: " + from.getClass().getSimpleName() + ".." + to.getClass().getSimpleName() + " (possible missing brackets around range?)", iae);
+        }
+    }
+
+    public boolean equals(Object that) {
+        return (that instanceof ObjectRange) ? equals((ObjectRange) that) : super.equals(that);
+    }
+
+    /**
+     * Compares an {@link ObjectRange} to another {@link ObjectRange}.
+     *
+     * @param that the object to check equality with
+     * @return <code>true</code> if the ranges are equal
+     */
+    public boolean equals(ObjectRange that) {
+        return that != null
+                && reverse == that.reverse
+                && DefaultTypeTransformation.compareEqual(from, that.from)
+                && DefaultTypeTransformation.compareEqual(to, that.to);
+    }
+
+    @Override
+    public Comparable getFrom() {
+        return from;
+    }
+
+    @Override
+    public Comparable getTo() {
+        return to;
+    }
+
+    @Override
+    public boolean isReverse() {
+        return reverse;
+    }
+
+    @Override
+    public Comparable get(int index) {
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Index: " + index + " should not be negative");
+        }
+        final StepIterator iter = new StepIterator(this, 1);
+
+        Comparable value = iter.next();
+        for (int i = 0; i < index; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + index + " is too big for range: " + this);
+            }
+            value = iter.next();
+        }
+        return value;
+    }
+
+    /**
+     * Checks whether a value is between the from and to values of a Range
+     *
+     * @param value the value of interest
+     * @return true if the value is within the bounds
+     */
+    @Override
+    public boolean containsWithinBounds(Object value) {
+        if (value instanceof Comparable) {
+            final int result = compareTo(from, (Comparable) value);
+            return result == 0 || result < 0 && compareTo(to, (Comparable) value) >= 0;
+        }
+        return contains(value);
+    }
+
+    protected int compareTo(Comparable first, Comparable second) {
+        return DefaultGroovyMethods.numberAwareCompareTo(first, second);
+    }
+
+    /**
+     * protection against calls from Groovy
+     */
+    @SuppressWarnings("unused")
+    private void setSize(int size) {
+        throw new UnsupportedOperationException("size must not be changed");
+    }
+
+    @Override
+    public int size() {
+        if (size == -1) {
+            int tempsize = 0;
+            if ((from instanceof Integer || from instanceof Long)
+                    && (to instanceof Integer || to instanceof Long)) {
+                // let's fast calculate the size
+                final BigInteger fromNum = new BigInteger(from.toString());
+                final BigInteger toNum = new BigInteger(to.toString());
+                final BigInteger sizeNum = toNum.subtract(fromNum).add(new BigInteger("1"));
+                tempsize = sizeNum.intValue();
+                if (!BigInteger.valueOf(tempsize).equals(sizeNum)) {
+                    tempsize = Integer.MAX_VALUE;
+                }
+            } else if (from instanceof Character && to instanceof Character) {
+                // let's fast calculate the size
+                final char fromNum = (Character) from;
+                final char toNum = (Character) to;
+                tempsize = toNum - fromNum + 1;
+            } else if (((from instanceof BigDecimal || from instanceof BigInteger) && to instanceof Number) ||
+                    ((to instanceof BigDecimal || to instanceof BigInteger) && from instanceof Number)) {
+                // let's fast calculate the size
+                final BigDecimal fromNum = new BigDecimal(from.toString());
+                final BigDecimal toNum = new BigDecimal(to.toString());
+                final BigInteger sizeNum = toNum.subtract(fromNum).add(new BigDecimal(1.0)).toBigInteger();
+                tempsize = sizeNum.intValue();
+                if (!BigInteger.valueOf(tempsize).equals(sizeNum)) {
+                    tempsize = Integer.MAX_VALUE;
+                }
+            } else {
+                // let's brute-force calculate the size by iterating start to end
+                final Iterator<Comparable> iter = new StepIterator(this, 1);
+                while (iter.hasNext()) {
+                    tempsize++;
+                    // integer overflow
+                    if (tempsize < 0) {
+                        break;
+                    }
+                    iter.next();
+                }
+            }
+            // integer overflow
+            if (tempsize < 0) {
+                tempsize = Integer.MAX_VALUE;
+            }
+            size = tempsize;
+        }
+        return size;
+    }
+
+    @Override
+    public List<Comparable> subList(int fromIndex, int toIndex) {
+        if (fromIndex < 0) {
+            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+        }
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex == toIndex) {
+            return new EmptyRange<Comparable>(from);
+        }
+
+        // Performance detail:
+        // not using get(fromIndex), get(toIndex) in the following to avoid stepping over elements twice
+        final Iterator<Comparable> iter = new StepIterator(this, 1);
+
+        Comparable toValue = iter.next();
+        int i = 0;
+        for (; i < fromIndex; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
+            }
+            toValue = iter.next();
+        }
+        final Comparable fromValue = toValue;
+        for (; i < toIndex - 1; i++) {
+            if (!iter.hasNext()) {
+                throw new IndexOutOfBoundsException("Index: " + i + " is too big for range: " + this);
+            }
+            toValue = iter.next();
+        }
+
+        return new ObjectRange(fromValue, toValue, reverse);
+    }
+
+    public String toString() {
+        return reverse ? "" + to + ".." + from : "" + from + ".." + to;
+    }
+
+    @Override
+    public String inspect() {
+        final String toText = InvokerHelper.inspect(to);
+        final String fromText = InvokerHelper.inspect(from);
+        return reverse ? "" + toText + ".." + fromText : "" + fromText + ".." + toText;
+    }
+
+    /**
+     * Iterates over all values and returns true if one value matches.
+     *
+     * @see #containsWithinBounds(Object)
+     */
+    @Override
+    public boolean contains(Object value) {
+        final Iterator<Comparable> iter = new StepIterator(this, 1);
+        if (value == null) {
+            return false;
+        }
+        while (iter.hasNext()) {
+            if (DefaultTypeTransformation.compareEqual(value, iter.next())) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void step(int step, Closure closure) {
+        if (step == 0 && compareTo(from, to) == 0) {
+            return; // from == to and step == 0, nothing to do, so return
+        }
+        final Iterator<Comparable> iter = new StepIterator(this, step);
+        while (iter.hasNext()) {
+            closure.call(iter.next());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterator<Comparable> iterator() {
+        // non thread-safe iterator
+        return new StepIterator(this, 1);
+    }
+
+    /**
+     * Non-thread-safe iterator which lazily produces the next element only on calls of hasNext() or next()
+     */
+    private static final class StepIterator implements Iterator<Comparable> {
+        // actual step, can be +1 when desired step is -1 and direction is from high to low
+        private final int step;
+        private final ObjectRange range;
+        private int index = -1;
+        private Comparable value;
+        private boolean nextFetched = true;
+
+        private StepIterator(ObjectRange range, final int desiredStep) {
+            if (desiredStep == 0 && range.compareTo(range.getFrom(), range.getTo()) != 0) {
+                throw new GroovyRuntimeException("Infinite loop detected due to step size of 0");
+            }
+            this.range = range;
+            if (range.isReverse()) {
+                step = -desiredStep;
+            } else {
+                step = desiredStep;
+            }
+            if (step > 0) {
+                value = range.getFrom();
+            } else {
+                value = range.getTo();
+            }
+        }
+
+        @Override
+        public void remove() {
+            range.remove(index);
+        }
+
+        @Override
+        public Comparable next() {
+            // not thread safe
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            nextFetched = false;
+            index++;
+            return value;
+        }
+
+        @Override
+        public boolean hasNext() {
+            // not thread safe
+            if (!nextFetched) {
+                value = peek();
+                nextFetched = true;
+            }
+            return value != null;
+        }
+
+        private Comparable peek() {
+            if (step > 0) {
+                Comparable peekValue = value;
+                for (int i = 0; i < step; i++) {
+                    peekValue = (Comparable) range.increment(peekValue);
+                    // handle back to beginning due to modulo incrementing
+                    if (range.compareTo(peekValue, range.from) <= 0) return null;
+                }
+                if (range.compareTo(peekValue, range.to) <= 0) {
+                    return peekValue;
+                }
+            } else {
+                final int positiveStep = -step;
+                Comparable peekValue = value;
+                for (int i = 0; i < positiveStep; i++) {
+                    peekValue = (Comparable) range.decrement(peekValue);
+                    // handle back to beginning due to modulo decrementing
+                    if (range.compareTo(peekValue, range.to) >= 0) return null;
+                }
+                if (range.compareTo(peekValue, range.from) >= 0) {
+                    return peekValue;
+                }
+            }
+            return null;
+        }
+    }
+
+    @Override
+    public List<Comparable> step(int step) {
+        final IteratorClosureAdapter<Comparable> adapter = new IteratorClosureAdapter<Comparable>(this);
+        step(step, adapter);
+        return adapter.asList();
+    }
+
+    /**
+     * Increments by one
+     *
+     * @param value the value to increment
+     * @return the incremented value
+     */
+    protected Object increment(Object value) {
+        return InvokerHelper.invokeMethod(value, "next", null);
+    }
+
+    /**
+     * Decrements by one
+     *
+     * @param value the value to decrement
+     * @return the decremented value
+     */
+    protected Object decrement(Object value) {
+        return InvokerHelper.invokeMethod(value, "previous", null);
+    }
+
+    /**
+     * if operand is a Character or a String with one character, return that character's int value.
+     */
+    private static Comparable normaliseStringType(final Comparable operand) {
+        if (operand instanceof Character) {
+            return (int) (Character) operand;
+        }
+        if (operand instanceof String) {
+            final String string = (String) operand;
+
+            if (string.length() == 1) {
+                return (int) string.charAt(0);
+            }
+            return string;
+        }
+        return operand;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ParameterArray.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ParameterArray.java b/src/main/groovy/groovy/lang/ParameterArray.java
new file mode 100644
index 0000000..d3a4163
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ParameterArray.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 groovy.lang;
+
+/**
+ * Distinguish a parameter array from Object[].
+ *
+ * @author Pilho Kim
+ */
+public class ParameterArray {
+
+    private final Object parameters;
+
+    public ParameterArray(Object data) {
+        parameters = packArray(data);
+    }
+
+    private static Object packArray(Object object) {
+        if (object instanceof Object[])
+            return (Object[]) object;
+        else
+            return object;
+    }
+
+    public Object get() {
+        return parameters;
+    }
+
+    public String toString() {
+        if (parameters == null)
+            return "<null parameter>";
+        return parameters.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/PropertyAccessInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/PropertyAccessInterceptor.java b/src/main/groovy/groovy/lang/PropertyAccessInterceptor.java
new file mode 100644
index 0000000..6d2906e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/PropertyAccessInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * <p>An interface that adds the ability to intercept
+ * property getters/setters
+ *
+ * @author Graeme Rocher
+ * @since Oct 24, 2005
+ */
+public interface PropertyAccessInterceptor extends Interceptor {
+
+    /**
+     * Intercepts a getXXX call and returns a result. The result is replaced by the
+     * real value if doGet() return false
+     *
+     * @param object   The target object
+     * @param property The property to get
+     * @return A value supplied by the interceptor
+     */
+    Object beforeGet(Object object, String property);
+
+    /**
+     * Intercepts a setXXX call
+     *
+     * @param object   The target object
+     * @param property The property to set
+     * @param newValue The new value
+     */
+    void beforeSet(Object object, String property, Object newValue);
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/PropertyValue.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/PropertyValue.java b/src/main/groovy/groovy/lang/PropertyValue.java
new file mode 100644
index 0000000..ac77b54
--- /dev/null
+++ b/src/main/groovy/groovy/lang/PropertyValue.java
@@ -0,0 +1,49 @@
+/*
+ *  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 groovy.lang;
+
+public class PropertyValue {
+    // the owner of the property
+    private final Object bean;
+
+    // the description of the property
+    private final MetaProperty mp;
+
+    public PropertyValue(Object bean, MetaProperty mp) {
+        this.bean = bean;
+        this.mp = mp;
+    }
+
+    public String getName() {
+        return mp.getName();
+    }
+
+    public Class getType() {
+        return mp.getType();
+    }
+
+    public Object getValue() {
+        return mp.getProperty(bean);
+    }
+
+    public void setValue(Object value) {
+        mp.setProperty(bean, value);
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ProxyMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ProxyMetaClass.java b/src/main/groovy/groovy/lang/ProxyMetaClass.java
new file mode 100644
index 0000000..8c41f7d
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ProxyMetaClass.java
@@ -0,0 +1,242 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * As subclass of MetaClass, ProxyMetaClass manages calls from Groovy Objects to POJOs.
+ * It enriches MetaClass with the feature of making method invocations interceptable by
+ * an Interceptor. To this end, it acts as a decorator (decorator pattern) allowing
+ * to add or withdraw this feature at runtime.
+ * See groovy/lang/InterceptorTest.groovy for details.
+ * <p>
+ * WARNING: This implementation of ProxyMetaClass is NOT thread-safe and hence should only be used for
+ * as a per-instance MetaClass running in a single thread. Do not place this MetaClass in the MetaClassRegistry
+ * as it will result in unpredictable behaviour
+ *
+ * @author Dierk Koenig
+ * @author Graeme Rocher
+ * @see groovy.lang.MetaClassRegistry
+ */
+public class ProxyMetaClass extends MetaClassImpl implements AdaptingMetaClass {
+
+    protected MetaClass adaptee = null;
+    protected Interceptor interceptor = null;
+
+
+    /**
+     * convenience factory method for the most usual case.
+     */
+    public static ProxyMetaClass getInstance(Class theClass) {
+        MetaClassRegistry metaRegistry = GroovySystem.getMetaClassRegistry();
+        MetaClass meta = metaRegistry.getMetaClass(theClass);
+        return new ProxyMetaClass(metaRegistry, theClass, meta);
+    }
+
+    /**
+     * @param adaptee the MetaClass to decorate with interceptability
+     */
+    public ProxyMetaClass(MetaClassRegistry registry, Class theClass, MetaClass adaptee) {
+        super(registry, theClass);
+        this.adaptee = adaptee;
+        if (null == adaptee) throw new IllegalArgumentException("adaptee must not be null");
+        super.initialize();
+    }
+
+    public synchronized void initialize() {
+        this.adaptee.initialize();
+    }
+
+    /**
+     * Use the ProxyMetaClass for the given Closure.
+     * Cares for balanced register/unregister.
+     *
+     * @param closure piece of code to be executed with registered ProxyMetaClass
+     */
+    public Object use(Closure closure) {
+        // grab existing meta (usually adaptee but we may have nested use calls)
+        MetaClass origMetaClass = registry.getMetaClass(theClass);
+        registry.setMetaClass(theClass, this);
+        try {
+            return closure.call();
+        } finally {
+            registry.setMetaClass(theClass, origMetaClass);
+        }
+    }
+
+    /**
+     * Use the ProxyMetaClass for the given Closure.
+     * Cares for balanced setting/unsetting ProxyMetaClass.
+     *
+     * @param closure piece of code to be executed with ProxyMetaClass
+     */
+    public Object use(GroovyObject object, Closure closure) {
+        // grab existing meta (usually adaptee but we may have nested use calls)
+        MetaClass origMetaClass = object.getMetaClass();
+        object.setMetaClass(this);
+        try {
+            return closure.call();
+        } finally {
+            object.setMetaClass(origMetaClass);
+        }
+    }
+
+    /**
+     * @return the interceptor in use or null if no interceptor is used
+     */
+    public Interceptor getInterceptor() {
+        return interceptor;
+    }
+
+    /**
+     * @param interceptor may be null to reset any interception
+     */
+    public void setInterceptor(Interceptor interceptor) {
+        this.interceptor = interceptor;
+    }
+
+    /**
+     * Call invokeMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
+     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
+     * The method call is suppressed if Interceptor.doInvoke() returns false.
+     * See Interceptor for details.
+     */
+    public Object invokeMethod(final Object object, final String methodName, final Object[] arguments) {
+        return doCall(object, methodName, arguments, interceptor, new Callable() {
+            public Object call() {
+                return adaptee.invokeMethod(object, methodName, arguments);
+            }
+        });
+    }
+
+    /**
+     * Call invokeMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
+     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
+     * The method call is suppressed if Interceptor.doInvoke() returns false.
+     * See Interceptor for details.
+     */
+    @Override
+    public Object invokeMethod(final Class sender, final Object object, final String methodName, final Object[] arguments, final boolean isCallToSuper, final boolean fromInsideClass) {
+        return doCall(object, methodName, arguments, interceptor, new Callable() {
+            public Object call() {
+                return adaptee.invokeMethod(sender, object, methodName, arguments, isCallToSuper, fromInsideClass);
+            }
+        });
+    }
+
+    /**
+     * Call invokeStaticMethod on adaptee with logic like in MetaClass unless we have an Interceptor.
+     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
+     * The method call is suppressed if Interceptor.doInvoke() returns false.
+     * See Interceptor for details.
+     */
+    public Object invokeStaticMethod(final Object object, final String methodName, final Object[] arguments) {
+        return doCall(object, methodName, arguments, interceptor, new Callable() {
+            public Object call() {
+                return adaptee.invokeStaticMethod(object, methodName, arguments);
+            }
+        });
+    }
+
+    /**
+     * Call invokeConstructor on adaptee with logic like in MetaClass unless we have an Interceptor.
+     * With Interceptor the call is nested in its beforeInvoke and afterInvoke methods.
+     * The method call is suppressed if Interceptor.doInvoke() returns false.
+     * See Interceptor for details.
+     */
+    public Object invokeConstructor(final Object[] arguments) {
+        return doCall(theClass, "ctor", arguments, interceptor, new Callable() {
+            public Object call() {
+                return adaptee.invokeConstructor(arguments);
+            }
+        });
+    }
+
+    /**
+     * Interceptors the call to getProperty if a PropertyAccessInterceptor is
+     * available
+     *
+     * @param object   the object to invoke the getter on
+     * @param property the property name
+     * @return the value of the property
+     */
+    public Object getProperty(Class aClass, Object object, String property, boolean b, boolean b1) {
+        if (null == interceptor) {
+            return super.getProperty(aClass, object, property, b, b1);
+        }
+        if (interceptor instanceof PropertyAccessInterceptor) {
+            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;
+
+            Object result = pae.beforeGet(object, property);
+            if (interceptor.doInvoke()) {
+                result = super.getProperty(aClass, object, property, b, b1);
+            }
+            return result;
+        }
+        return super.getProperty(aClass, object, property, b, b1);
+    }
+
+    /**
+     * Interceptors the call to a property setter if a PropertyAccessInterceptor
+     * is available
+     *
+     * @param object   The object to invoke the setter on
+     * @param property The property name to set
+     * @param newValue The new value of the property
+     */
+    public void setProperty(Class aClass, Object object, String property, Object newValue, boolean b, boolean b1) {
+        if (null == interceptor) {
+            super.setProperty(aClass, object, property, newValue, b, b1);
+        }
+        if (interceptor instanceof PropertyAccessInterceptor) {
+            PropertyAccessInterceptor pae = (PropertyAccessInterceptor) interceptor;
+
+            pae.beforeSet(object, property, newValue);
+            if (interceptor.doInvoke()) {
+                super.setProperty(aClass, object, property, newValue, b, b1);
+            }
+        } else {
+            super.setProperty(aClass, object, property, newValue, b, b1);
+        }
+    }
+
+    public MetaClass getAdaptee() {
+        return this.adaptee;
+    }
+
+    public void setAdaptee(MetaClass metaClass) {
+        this.adaptee = metaClass;
+    }
+
+    // since Java has no Closures...
+    private interface Callable {
+        Object call();
+    }
+
+    private Object doCall(Object object, String methodName, Object[] arguments, Interceptor interceptor, Callable howToInvoke) {
+        if (null == interceptor) {
+            return howToInvoke.call();
+        }
+        Object result = interceptor.beforeInvoke(object, methodName, arguments);
+        if (interceptor.doInvoke()) {
+            result = howToInvoke.call();
+        }
+        result = interceptor.afterInvoke(object, methodName, arguments, result);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Range.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Range.java b/src/main/groovy/groovy/lang/Range.java
new file mode 100644
index 0000000..99f30de
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Range.java
@@ -0,0 +1,109 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.List;
+
+/**
+ * A Range represents the list of discrete items between some starting (or <code>from</code>)
+ * value and <em>working up</em> towards some ending (or <code>to</code>) value.
+ * For a reverse range, the list is obtained by starting at the <code>to</code> value and
+ * <em>working down</em> towards the <code>from</code> value.
+ *
+ * The concept of <em>working up</em> and <em>working down</em> is dependent on the range implementation.
+ * In the general case, working up involves successive calls to the first item's <code>next()</code>
+ * method while working down involves calling the <code>previous()</code> method. Optimized
+ * numerical ranges may apply numeric addition or subtraction of some numerical step size.
+ *
+ * Particular range implementations may also support the notion of inclusivity
+ * and exclusivity with respect to the ending value in the range.
+ * E.g. <code>1..3 == [1, 2, 3]</code>; but <code>1..<3 == [1, 2]</code>.
+ *
+ * In general, the second boundary may not be contained in the range,
+ * and <code>a..b</code> may produce a different set of elements than <code>(b..a).reversed()</code>.
+ * E.g.  <code>1..2.5 == [1, 2]</code>; but <code>2.5..1 == [2.5, 1.5]</code>.
+ *
+ * Implementations can be memory efficient by storing just the <code>from</code> and <code>to</code> boundary
+ * values rather than eagerly creating all discrete items in the conceptual list. The actual discrete items
+ * can be lazily calculated on an as needed basis (e.g. when calling methods from the <code>java.util.List</code>
+ * interface or the additional <code>step</code> methods in the <code>Range</code> interface).
+ *
+ * In addition to the methods related to a Range's "discrete items" abstraction, there is a method,
+ * <code>containsWithinBounds</code> which, for numerical ranges, allows checking within the continuous
+ * interval between the Range's boundary values.
+ */
+public interface Range<T extends Comparable> extends List<T> {
+    /**
+     * The lower value in the range.
+     *
+     * @return the lower value in the range.
+     */
+    T getFrom();
+
+    /**
+     * The upper value in the range.
+     *
+     * @return the upper value in the range
+     */
+    T getTo();
+
+    /**
+     * Indicates whether this is a reverse range which iterates backwards
+     * starting from the to value and ending on the from value
+     *
+     * @return <code>true</code> if this is a reverse range
+     */
+    boolean isReverse();
+
+    /**
+     * Indicates whether an object is greater than or equal to the <code>from</code>
+     * value for the range and less than or equal to the <code>to</code> value.
+     * <p>
+     * This may be true even for values not contained in the range.
+     *
+     * Example: from = 1.5, to = 3, next() increments by 1
+     * containsWithinBounds(2) == true
+     * contains(2) == false
+     *
+     * @param o the object to check against the boundaries of the range
+     * @return <code>true</code> if the object is between the from and to values
+     */
+    boolean containsWithinBounds(Object o);
+
+    /**
+     * Steps through the range, calling a closure for each item.
+     *
+     * @param step    the amount by which to step. If negative, steps through the range backwards.
+     * @param closure the {@link Closure} to call
+     */
+    void step(int step, Closure closure);
+
+    /**
+     * Forms a list by stepping through the range by the indicated interval.
+     *
+     * @param step the amount by which to step. If negative, steps through the range backwards.
+     * @return the list formed by stepping through the range by the indicated interval.
+     */
+    List<T> step(int step);
+
+    /**
+     * @return the verbose {@link String} representation of this {@link Range} as would be typed into a console to create the {@link Range} instance
+     */
+    String inspect();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ReadOnlyPropertyException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ReadOnlyPropertyException.java b/src/main/groovy/groovy/lang/ReadOnlyPropertyException.java
new file mode 100644
index 0000000..342a182
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ReadOnlyPropertyException.java
@@ -0,0 +1,36 @@
+/*
+ *  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 groovy.lang;
+
+
+/**
+ * This exception is thrown if an attempt is made to set a read only property
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ReadOnlyPropertyException extends MissingPropertyException {
+
+    public ReadOnlyPropertyException(final String property, final Class type) {
+        super("Cannot set readonly property: " + property + " for class: " + type.getName(), property, type);
+    }
+
+    public ReadOnlyPropertyException(final String property, final String classname) {
+        super("Cannot set readonly property: " + property + " for class: " + classname);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Reference.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Reference.java b/src/main/groovy/groovy/lang/Reference.java
new file mode 100644
index 0000000..c4bf21d
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Reference.java
@@ -0,0 +1,82 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.Serializable;
+
+/**
+ * Represents a reference to a value
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Reference<T> extends GroovyObjectSupport implements Serializable {
+
+    private static final long serialVersionUID = 4963704631487573488L;
+    private T value;
+
+    public Reference() {
+    }
+
+    public Reference(T value) {
+        this.value = value;
+    }
+
+    public Object getProperty(String property) {
+        Object value = get();
+        if (value != null) {
+            return InvokerHelper.getProperty(value, property);
+        }
+        return super.getProperty(property);
+    }
+
+    public void setProperty(String property, Object newValue) {
+        Object value = get();
+        if (value != null) {
+            InvokerHelper.setProperty(value, property, newValue);
+        }
+        else {
+            super.setProperty(property, newValue);
+        }
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        Object value = get();
+        if (value != null) {
+            try {
+                return InvokerHelper.invokeMethod(value, name, args);
+            }
+            catch (Exception e) {
+                return super.invokeMethod(name, args);
+            }
+        }
+        else {
+            return super.invokeMethod(name, args);
+        }
+    }
+
+    public T get() {
+        return value;
+    }
+
+    public void set(T value) {
+        this.value = value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Script.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Script.java b/src/main/groovy/groovy/lang/Script.java
new file mode 100644
index 0000000..196c74c
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Script.java
@@ -0,0 +1,231 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This object represents a Groovy script
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Guillaume Laforge
+ */
+public abstract class Script extends GroovyObjectSupport {
+    private Binding binding;
+
+    protected Script() {
+        this(new Binding());
+    }
+
+    protected Script(Binding binding) {
+        this.binding = binding;
+    }
+
+    public Binding getBinding() {
+        return binding;
+    }
+
+    public void setBinding(Binding binding) {
+        this.binding = binding;
+    }
+
+    public Object getProperty(String property) {
+        try {
+            return binding.getVariable(property);
+        } catch (MissingPropertyException e) {
+            return super.getProperty(property);
+        }
+    }
+
+    public void setProperty(String property, Object newValue) {
+        if ("binding".equals(property))
+            setBinding((Binding) newValue);
+        else if("metaClass".equals(property))
+            setMetaClass((MetaClass)newValue);
+        else
+            binding.setVariable(property, newValue);
+    }
+
+    /**
+     * Invoke a method (or closure in the binding) defined.
+     *
+     * @param name method to call
+     * @param args arguments to pass to the method
+     * @return value
+     */
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return super.invokeMethod(name, args);
+        }
+        // if the method was not found in the current scope (the script's methods)
+        // let's try to see if there's a method closure with the same name in the binding
+        catch (MissingMethodException mme) {
+            try {
+                if (name.equals(mme.getMethod())) {
+                    Object boundClosure = getProperty(name);
+                    if (boundClosure != null && boundClosure instanceof Closure) {
+                        return ((Closure) boundClosure).call((Object[])args);
+                    } else {
+                        throw mme;
+                    }
+                } else {
+                    throw mme;
+                }
+            } catch (MissingPropertyException mpe) {
+                throw mme;
+            }
+        }
+    }
+
+    /**
+     * The main instance method of a script which has variables in scope
+     * as defined by the current {@link Binding} instance.
+     */
+    public abstract Object run();
+
+    // println helper methods
+
+    /**
+     * Prints a newline to the current 'out' variable which should be a PrintWriter
+     * or at least have a println() method defined on it.
+     * If there is no 'out' property then print to standard out.
+     */
+    public void println() {
+        Object object;
+
+        try {
+            object = getProperty("out");
+        } catch (MissingPropertyException e) {
+            System.out.println();
+            return;
+        }
+
+        InvokerHelper.invokeMethod(object, "println", ArgumentListExpression.EMPTY_ARRAY);
+    }
+
+    /**
+     * Prints the value to the current 'out' variable which should be a PrintWriter
+     * or at least have a print() method defined on it.
+     * If there is no 'out' property then print to standard out.
+     */
+    public void print(Object value) {
+        Object object;
+
+        try {
+            object = getProperty("out");
+        } catch (MissingPropertyException e) {
+            DefaultGroovyMethods.print(System.out,value);
+            return;
+        }
+
+        InvokerHelper.invokeMethod(object, "print", new Object[]{value});
+    }
+
+    /**
+     * Prints the value and a newline to the current 'out' variable which should be a PrintWriter
+     * or at least have a println() method defined on it.
+     * If there is no 'out' property then print to standard out.
+     */
+    public void println(Object value) {
+        Object object;
+
+        try {
+            object = getProperty("out");
+        } catch (MissingPropertyException e) {
+            DefaultGroovyMethods.println(System.out,value);
+            return;
+        }
+
+        InvokerHelper.invokeMethod(object, "println", new Object[]{value});
+    }
+
+    /**
+     * Prints a formatted string using the specified format string and argument.
+     *
+     * @param format the format to follow
+     * @param value the value to be formatted
+     */
+    public void printf(String format, Object value) {
+        Object object;
+
+        try {
+            object = getProperty("out");
+        } catch (MissingPropertyException e) {
+            DefaultGroovyMethods.printf(System.out, format, value);
+            return;
+        }
+
+        InvokerHelper.invokeMethod(object, "printf", new Object[] { format, value });
+    }
+
+    /**
+     * Prints a formatted string using the specified format string and arguments.
+     *
+     * @param format the format to follow
+     * @param values an array of values to be formatted
+     */
+    public void printf(String format, Object[] values) {
+        Object object;
+
+        try {
+            object = getProperty("out");
+        } catch (MissingPropertyException e) {
+            DefaultGroovyMethods.printf(System.out, format, values);
+            return;
+        }
+
+        InvokerHelper.invokeMethod(object, "printf", new Object[] { format, values });
+    }
+
+    /**
+     * A helper method to allow the dynamic evaluation of groovy expressions using this
+     * scripts binding as the variable scope
+     *
+     * @param expression is the Groovy script expression to evaluate
+     */
+    public Object evaluate(String expression) throws CompilationFailedException {
+        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
+        return shell.evaluate(expression);
+    }
+
+    /**
+     * A helper method to allow the dynamic evaluation of groovy expressions using this
+     * scripts binding as the variable scope
+     *
+     * @param file is the Groovy script to evaluate
+     */
+    public Object evaluate(File file) throws CompilationFailedException, IOException {
+        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
+        return shell.evaluate(file);
+    }
+
+    /**
+     * A helper method to allow scripts to be run taking command line arguments
+     */
+    public void run(File file, String[] arguments) throws CompilationFailedException, IOException {
+        GroovyShell shell = new GroovyShell(getClass().getClassLoader(), binding);
+        shell.run(file, arguments);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Sequence.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Sequence.java b/src/main/groovy/groovy/lang/Sequence.java
new file mode 100644
index 0000000..2b4316c
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Sequence.java
@@ -0,0 +1,224 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Represents a sequence of objects which represents zero or many instances of
+ * of objects of a given type. The type can be omitted in which case any type of
+ * object can be added.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Sequence extends ArrayList implements GroovyObject {
+
+    private MetaClass metaClass = InvokerHelper.getMetaClass(getClass());
+    private final Class type;
+    private int hashCode;
+
+    public Sequence() {
+        this(null);
+    }
+
+    public Sequence(Class type) {
+        this.type = type;
+    }
+
+    public Sequence(Class type, List content) {
+        super(content.size());
+        this.type = type;
+        addAll(content);
+    }
+
+    /**
+     * Sets the contents of this sequence to that
+     * of the given collection.
+     */
+    public void set(Collection collection) {
+        checkCollectionType(collection);
+        clear();
+        addAll(collection);
+    }
+    
+    public boolean equals(Object that) {
+        if (that instanceof Sequence) {
+            return equals((Sequence) that);
+        }
+        return false;
+    }
+
+    public boolean equals(Sequence that) {
+        if (size() == that.size()) {
+            for (int i = 0; i < size(); i++) {
+                if (!DefaultTypeTransformation.compareEqual(this.get(i), that.get(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        if (hashCode == 0) {
+            for (int i = 0; i < size(); i++) {
+                Object value = get(i);
+                int hash = (value != null) ? value.hashCode() : 0xbabe;
+                hashCode ^= hash;
+            }
+            if (hashCode == 0) {
+                hashCode = 0xbabe;
+            }
+        }
+        return hashCode;
+    }
+
+    public int minimumSize() {
+        return 0;
+    }
+
+    /**
+     * @return the type of the elements in the sequence or null if there is no
+     * type constraint on this sequence
+     */
+    public Class type() {
+        return type;
+    }
+    
+    public void add(int index, Object element) {
+        checkType(element);
+        hashCode = 0;
+        super.add(index, element);
+    }
+
+    public boolean add(Object element) {
+        checkType(element);
+        hashCode = 0;
+        return super.add(element);
+    }
+
+    public boolean addAll(Collection c) {
+        checkCollectionType(c);
+        hashCode = 0;
+        return super.addAll(c);
+    }
+
+    public boolean addAll(int index, Collection c) {
+        checkCollectionType(c);
+        hashCode = 0;
+        return super.addAll(index, c);
+    }
+
+    public void clear() {
+        hashCode = 0;
+        super.clear();
+    }
+
+    public Object remove(int index) {
+        hashCode = 0;
+        return super.remove(index);
+    }
+
+    protected void removeRange(int fromIndex, int toIndex) {
+        hashCode = 0;
+        super.removeRange(fromIndex, toIndex);
+    }
+
+    public Object set(int index, Object element) {
+        hashCode = 0;
+        return super.set(index, element);
+    }
+
+    // GroovyObject interface
+    //-------------------------------------------------------------------------
+    public Object invokeMethod(String name, Object args) {
+        try {
+        return getMetaClass().invokeMethod(this, name, args);
+        }
+        catch (MissingMethodException e) {
+            // lets apply the method to each item in the collection
+            List answer = new ArrayList(size());
+            for (Iterator iter = iterator(); iter.hasNext(); ) {
+                Object element = iter.next();
+                Object value = InvokerHelper.invokeMethod(element, name, args);
+                answer.add(value);
+            }
+            return answer;
+        }
+    }
+
+    public Object getProperty(String property) {
+        return getMetaClass().getProperty(this, property);
+    }
+
+    public void setProperty(String property, Object newValue) {
+        getMetaClass().setProperty(this, property, newValue);
+    }
+
+    public MetaClass getMetaClass() {
+        return metaClass;
+    }
+
+    public void setMetaClass(MetaClass metaClass) {
+        this.metaClass = metaClass;
+    }
+
+    // Implementation methods
+    //-------------------------------------------------------------------------
+    
+    /**
+     * Checks that each member of the given collection are of the correct
+     * type
+     */
+    protected void checkCollectionType(Collection c) {
+        if (type != null) {
+            for (Iterator iter = c.iterator(); iter.hasNext(); ) {
+                Object element = iter.next();
+                checkType(element);
+            }
+        }
+    }
+
+
+    /** 
+     * Checks that the given object instance is of the correct type
+     * otherwise a runtime exception is thrown
+     */
+    protected void checkType(Object object) {
+        if (object == null) {
+            throw new NullPointerException("Sequences cannot contain null, use a List instead");
+        }
+        if (type != null) {
+            if (!type.isInstance(object)) {
+                throw new IllegalArgumentException(
+                    "Invalid type of argument for sequence of type: "
+                        + type.getName()
+                        + " cannot add object: "
+                        + object);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Singleton.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Singleton.java b/src/main/groovy/groovy/lang/Singleton.java
new file mode 100644
index 0000000..9b86c8b
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Singleton.java
@@ -0,0 +1,66 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation to make a singleton class. The singleton is obtained through normal property access using the singleton property (defaults to "instance").
+ *
+ * Such classes can be initialized during normal static initialization of the class or lazily (on first access).
+ * To make the singleton lazy use {@code @Singleton(lazy=true)}.
+ * Lazy singletons are implemented with double-checked locking and a volatile backing field.
+ * By default, no explicit constructors are allowed. To create one or more explicit constructors
+ * use {@code @Singleton(strict=false)}.
+ * This could be used to:
+ * <ul>
+ * <li>provide your own custom initialization logic in your own no-arg constructor - you
+ * will be responsible for the entire code (the {@code @Singleton} annotation becomes merely documentation)</li>
+ * <li>provide one or more constructors with arguments for a quasi-singleton - these constructors will be used
+ * to create instances that are independent of the singleton instance returned by the singleton property</li>
+ * </ul>
+ *
+ * @author Alex Tkachman
+ * @author Paul King
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.SingletonASTTransformation")
+public @interface Singleton {
+    /**
+     * @return if this singleton should be lazy
+     */
+    boolean lazy() default false;
+
+    /**
+     * @return if this singleton should have strict semantics
+     */
+    boolean strict() default true;
+
+    /**
+     * @return the singleton property name
+     */
+    String property() default "instance";
+}


[41/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/TypedOption.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/TypedOption.java b/src/main/groovy/groovy/cli/TypedOption.java
new file mode 100644
index 0000000..e669324
--- /dev/null
+++ b/src/main/groovy/groovy/cli/TypedOption.java
@@ -0,0 +1,27 @@
+/*
+ *  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 groovy.cli;
+
+import java.util.HashMap;
+
+public class TypedOption<T> extends HashMap<String, T> {
+    public T defaultValue() {
+        return (T) super.get("defaultValue");
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/Unparsed.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/Unparsed.java b/src/main/groovy/groovy/cli/Unparsed.java
new file mode 100644
index 0000000..a741413
--- /dev/null
+++ b/src/main/groovy/groovy/cli/Unparsed.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 groovy.cli;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a method or property will contain the remaining arguments.
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.FIELD})
+public @interface Unparsed {
+    /**
+     * The description for the remaining non-option arguments
+     *
+     * @return the description for the remaining non-option arguments
+     */
+    String description() default "ARGUMENTS";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/UnparsedField.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/UnparsedField.groovy b/src/main/groovy/groovy/cli/UnparsedField.groovy
new file mode 100644
index 0000000..b185431
--- /dev/null
+++ b/src/main/groovy/groovy/cli/UnparsedField.groovy
@@ -0,0 +1,27 @@
+/*
+ *  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 groovy.cli
+
+import groovy.transform.AnnotationCollector
+import groovy.transform.Field
+
+@Unparsed
+@Field
+@AnnotationCollector
+@interface UnparsedField { }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/grape/GrabAnnotationTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/grape/GrabAnnotationTransformation.java b/src/main/groovy/groovy/grape/GrabAnnotationTransformation.java
new file mode 100644
index 0000000..dd55ff9
--- /dev/null
+++ b/src/main/groovy/groovy/grape/GrabAnnotationTransformation.java
@@ -0,0 +1,639 @@
+/*
+ *  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 groovy.grape;
+
+import groovy.lang.Grab;
+import groovy.lang.GrabConfig;
+import groovy.lang.GrabExclude;
+import groovy.lang.GrabResolver;
+import groovy.lang.Grapes;
+import groovy.transform.CompilationUnitAware;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ImportNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.ListExpression;
+import org.codehaus.groovy.ast.expr.MapExpression;
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.io.StringReaderSource;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.tools.GrapeUtil;
+import org.codehaus.groovy.transform.ASTTransformation;
+import org.codehaus.groovy.transform.ASTTransformationVisitor;
+import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.codehaus.groovy.transform.GroovyASTTransformation;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.eqX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
+
+/**
+ * Transformation for declarative dependency management.
+ */
+@GroovyASTTransformation(phase=CompilePhase.CONVERSION)
+public class GrabAnnotationTransformation extends ClassCodeVisitorSupport implements ASTTransformation, CompilationUnitAware {
+    private static final String GRAB_CLASS_NAME = Grab.class.getName();
+    private static final String GRAB_DOT_NAME = GRAB_CLASS_NAME.substring(GRAB_CLASS_NAME.lastIndexOf("."));
+    private static final String GRAB_SHORT_NAME = GRAB_DOT_NAME.substring(1);
+
+    private static final String GRABEXCLUDE_CLASS_NAME = GrabExclude.class.getName();
+    private static final String GRABEXCLUDE_DOT_NAME = dotName(GRABEXCLUDE_CLASS_NAME);
+    private static final String GRABEXCLUDE_SHORT_NAME = shortName(GRABEXCLUDE_DOT_NAME);
+
+    private static final String GRABCONFIG_CLASS_NAME = GrabConfig.class.getName();
+    private static final String GRABCONFIG_DOT_NAME = dotName(GRABCONFIG_CLASS_NAME);
+    private static final String GRABCONFIG_SHORT_NAME = shortName(GRABCONFIG_DOT_NAME);
+
+    private static final String GRAPES_CLASS_NAME = Grapes.class.getName();
+    private static final String GRAPES_DOT_NAME = dotName(GRAPES_CLASS_NAME);
+    private static final String GRAPES_SHORT_NAME = shortName(GRAPES_DOT_NAME);
+
+    private static final String GRABRESOLVER_CLASS_NAME = GrabResolver.class.getName();
+    private static final String GRABRESOLVER_DOT_NAME = dotName(GRABRESOLVER_CLASS_NAME);
+    private static final String GRABRESOLVER_SHORT_NAME = shortName(GRABRESOLVER_DOT_NAME);
+
+    private static final ClassNode THREAD_CLASSNODE = ClassHelper.make(Thread.class);
+    private static final ClassNode SYSTEM_CLASSNODE = ClassHelper.make(System.class);
+
+    private static final List<String> GRABEXCLUDE_REQUIRED = Arrays.asList("group", "module");
+    private static final List<String> GRABRESOLVER_REQUIRED = Arrays.asList("name", "root");
+    private static final List<String> GRAB_REQUIRED = Arrays.asList("group", "module", "version");
+    private static final List<String> GRAB_OPTIONAL = Arrays.asList("classifier", "transitive", "conf", "ext", "type", "changing", "force", "initClass");
+    private static final List<String> GRAB_BOOLEAN = Arrays.asList("transitive", "changing", "force", "initClass");
+    private static final Collection<String> GRAB_ALL = DefaultGroovyMethods.plus(GRAB_REQUIRED, GRAB_OPTIONAL);
+    private static final Pattern IVY_PATTERN = Pattern.compile("([a-zA-Z0-9-/._+=]+)#([a-zA-Z0-9-/._+=]+)(;([a-zA-Z0-9-/.\\(\\)\\[\\]\\{\\}_+=,:@][a-zA-Z0-9-/.\\(\\)\\]\\{\\}_+=,:@]*))?(\\[([a-zA-Z0-9-/._+=,]*)\\])?");
+    private static final Pattern ATTRIBUTES_PATTERN = Pattern.compile("(.*;|^)([a-zA-Z0-9]+)=([a-zA-Z0-9.*\\[\\]\\-\\(\\),]*)$");
+
+    private static final String AUTO_DOWNLOAD_SETTING = Grape.AUTO_DOWNLOAD_SETTING;
+    private static final String DISABLE_CHECKSUMS_SETTING = Grape.DISABLE_CHECKSUMS_SETTING;
+    private static final String SYSTEM_PROPERTIES_SETTING = Grape.SYSTEM_PROPERTIES_SETTING;
+
+    private static String dotName(String className) {
+        return className.substring(className.lastIndexOf("."));
+    }
+
+    private static String shortName(String className) {
+        return className.substring(1);
+    }
+
+    boolean allowShortGrab;
+    Set<String> grabAliases;
+    List<AnnotationNode> grabAnnotations;
+
+    boolean allowShortGrabExcludes;
+    Set<String> grabExcludeAliases;
+    List<AnnotationNode> grabExcludeAnnotations;
+
+    boolean allowShortGrabConfig;
+    Set<String> grabConfigAliases;
+    List<AnnotationNode> grabConfigAnnotations;
+
+    boolean allowShortGrapes;
+    Set<String> grapesAliases;
+    List<AnnotationNode> grapesAnnotations;
+
+    boolean allowShortGrabResolver;
+    Set<String> grabResolverAliases;
+    List<AnnotationNode> grabResolverAnnotations;
+
+    CompilationUnit compilationUnit;
+    SourceUnit sourceUnit;
+    ClassLoader loader;
+    boolean initContextClassLoader;
+    Boolean autoDownload;
+    Boolean disableChecksums;
+    Map<String, String> systemProperties;
+
+    public SourceUnit getSourceUnit() {
+        return sourceUnit;
+    }
+
+    public void setCompilationUnit(final CompilationUnit compilationUnit) {
+        this.compilationUnit = compilationUnit;
+    }
+
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        sourceUnit = source;
+        loader = null;
+        initContextClassLoader = false;
+
+        ModuleNode mn = (ModuleNode) nodes[0];
+
+        allowShortGrab = true;
+        allowShortGrabExcludes = true;
+        allowShortGrabConfig = true;
+        allowShortGrapes = true;
+        allowShortGrabResolver = true;
+        grabAliases = new HashSet<String>();
+        grabExcludeAliases = new HashSet<String>();
+        grabConfigAliases = new HashSet<String>();
+        grapesAliases = new HashSet<String>();
+        grabResolverAliases = new HashSet<String>();
+        for (ImportNode im : mn.getImports()) {
+            String alias = im.getAlias();
+            String className = im.getClassName();
+            if ((className.endsWith(GRAB_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
+                || (GRAB_CLASS_NAME.equals(alias)))
+            {
+                allowShortGrab = false;
+            } else if (GRAB_CLASS_NAME.equals(className)) {
+                grabAliases.add(im.getAlias());
+            }
+            if ((className.endsWith(GRAPES_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
+                || (GRAPES_CLASS_NAME.equals(alias)))
+            {
+                allowShortGrapes = false;
+            } else if (GRAPES_CLASS_NAME.equals(className)) {
+                grapesAliases.add(im.getAlias());
+            }
+            if ((className.endsWith(GRABRESOLVER_DOT_NAME) && ((alias == null) || (alias.length() == 0)))
+                || (GRABRESOLVER_CLASS_NAME.equals(alias)))
+            {
+                allowShortGrabResolver = false;
+            } else if (GRABRESOLVER_CLASS_NAME.equals(className)) {
+                grabResolverAliases.add(im.getAlias());
+            }
+        }
+
+        List<Map<String,Object>> grabMaps = new ArrayList<Map<String,Object>>();
+        List<Map<String,Object>> grabMapsInit = new ArrayList<Map<String,Object>>();
+        List<Map<String,Object>> grabExcludeMaps = new ArrayList<Map<String,Object>>();
+
+        for (ClassNode classNode : sourceUnit.getAST().getClasses()) {
+            grabAnnotations = new ArrayList<AnnotationNode>();
+            grabExcludeAnnotations = new ArrayList<AnnotationNode>();
+            grabConfigAnnotations = new ArrayList<AnnotationNode>();
+            grapesAnnotations = new ArrayList<AnnotationNode>();
+            grabResolverAnnotations = new ArrayList<AnnotationNode>();
+
+            visitClass(classNode);
+
+            ClassNode grapeClassNode = ClassHelper.make(Grape.class);
+
+            List<Statement> grabResolverInitializers = new ArrayList<Statement>();
+
+            if (!grapesAnnotations.isEmpty()) {
+                for (AnnotationNode node : grapesAnnotations) {
+                    Expression init = node.getMember("initClass");
+                    Expression value = node.getMember("value");
+                    if (value instanceof ListExpression) {
+                        for (Object o : ((ListExpression)value).getExpressions()) {
+                            if (o instanceof ConstantExpression) {
+                                extractGrab(init, (ConstantExpression) o);
+                            }
+                        }
+                    } else if (value instanceof ConstantExpression) {
+                        extractGrab(init, (ConstantExpression) value);
+                    }
+                    // don't worry if it's not a ListExpression, or AnnotationConstant, etc.
+                    // the rest of GroovyC will flag it as a syntax error later, so we don't
+                    // need to raise the error ourselves
+                }
+            }
+
+            if (!grabResolverAnnotations.isEmpty()) {
+                grabResolverAnnotationLoop:
+                for (AnnotationNode node : grabResolverAnnotations) {
+                    Map<String, Object> grabResolverMap = new HashMap<String, Object>();
+                    String sval = getMemberStringValue(node, "value");
+                    if (sval != null && sval.length() > 0) {
+                        for (String s : GRABRESOLVER_REQUIRED) {
+                            String mval = getMemberStringValue(node, s);
+                            if (mval != null && mval.isEmpty()) mval = null;
+                            if (mval != null) {
+                                addError("The attribute \"" + s + "\" conflicts with attribute 'value' in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                                continue grabResolverAnnotationLoop;
+                            }
+                        }
+                        grabResolverMap.put("name", sval);
+                        grabResolverMap.put("root", sval);
+                    } else {
+                        for (String s : GRABRESOLVER_REQUIRED) {
+                            String mval = getMemberStringValue(node, s);
+                            Expression member = node.getMember(s);
+                            if (member == null || (mval != null && mval.isEmpty())) {
+                                addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                                continue grabResolverAnnotationLoop;
+                            } else if (mval == null) {
+                                addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant String in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                                continue grabResolverAnnotationLoop;
+                            }
+                            grabResolverMap.put(s, mval);
+                        }
+                    }
+
+                    // If no scheme is specified for the repository root,
+                    // then turn it into a URI relative to that of the source file.
+                    String root = (String) grabResolverMap.get("root");
+                    if (root != null && !root.contains(":")) {
+                        URI sourceURI = null;
+                        // Since we use the data: scheme for StringReaderSources (which are fairly common)
+                        // and those are not hierarchical we can't use them for making an absolute URI.
+                        if (!(getSourceUnit().getSource() instanceof StringReaderSource)) {
+                            // Otherwise let's trust the source to know where it is from.
+                            // And actually InputStreamReaderSource doesn't know what to do and so returns null.
+                            sourceURI = getSourceUnit().getSource().getURI();
+                        }
+                        // If source doesn't know how to get a reference to itself,
+                        // then let's use the current working directory, since the repo can be relative to that.
+                        if (sourceURI == null) {
+                            sourceURI = new File(".").toURI();
+                        }
+                        try {
+                            URI rootURI = sourceURI.resolve(new URI(root));
+                            grabResolverMap.put("root", rootURI.toString());
+                        } catch (URISyntaxException e) {
+                            // We'll be silent here.
+                            // If the URI scheme is unknown or not hierarchical, then we just can't help them and shouldn't cause any trouble either.
+                            // addError("Attribute \"root\" has value '" + root + "' which can't be turned into a valid URI relative to it's source '" + getSourceUnit().getName() + "' @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                        }
+                    }
+
+                    Grape.addResolver(grabResolverMap);
+                    addGrabResolverAsStaticInitIfNeeded(grapeClassNode, node, grabResolverInitializers, grabResolverMap);
+                }
+            }
+
+            if (!grabConfigAnnotations.isEmpty()) {
+                for (AnnotationNode node : grabConfigAnnotations) {
+                    checkForClassLoader(node);
+                    checkForInitContextClassLoader(node);
+                    checkForAutoDownload(node);
+                    checkForSystemProperties(node);
+                    checkForDisableChecksums(node);
+                }
+                addInitContextClassLoaderIfNeeded(classNode);
+            }
+
+            if (!grabExcludeAnnotations.isEmpty()) {
+                grabExcludeAnnotationLoop:
+                for (AnnotationNode node : grabExcludeAnnotations) {
+                    Map<String, Object> grabExcludeMap = new HashMap<String, Object>();
+                    checkForConvenienceForm(node, true);
+                    for (String s : GRABEXCLUDE_REQUIRED) {
+                        Expression member = node.getMember(s);
+                        if (member == null) {
+                            addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                            continue grabExcludeAnnotationLoop;
+                        } else if (member != null && !(member instanceof ConstantExpression)) {
+                            addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                            continue grabExcludeAnnotationLoop;
+                        }
+                        grabExcludeMap.put(s, ((ConstantExpression)member).getValue());
+                    }
+                    grabExcludeMaps.add(grabExcludeMap);
+                }
+            }
+
+            if (!grabAnnotations.isEmpty()) {
+                grabAnnotationLoop:
+                for (AnnotationNode node : grabAnnotations) {
+                    Map<String, Object> grabMap = new HashMap<String, Object>();
+                    checkForConvenienceForm(node, false);
+                    for (String s : GRAB_ALL) {
+                        Expression member = node.getMember(s);
+                        String mval = getMemberStringValue(node, s);
+                        if (mval != null && mval.isEmpty()) member = null;
+                        if (member == null && !GRAB_OPTIONAL.contains(s)) {
+                            addError("The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                            continue grabAnnotationLoop;
+                        } else if (member != null && !(member instanceof ConstantExpression)) {
+                            addError("Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node);
+                            continue grabAnnotationLoop;
+                        }
+                        if (node.getMember(s) != null) {
+                            grabMap.put(s, ((ConstantExpression)member).getValue());
+                        }
+                    }
+                    grabMaps.add(grabMap);
+                    if ((node.getMember("initClass") == null) || (node.getMember("initClass") == ConstantExpression.TRUE)) {
+                        grabMapsInit.add(grabMap);
+                    }
+                }
+                callGrabAsStaticInitIfNeeded(classNode, grapeClassNode, grabMapsInit, grabExcludeMaps);
+            }
+
+            if (!grabResolverInitializers.isEmpty()) {
+                classNode.addStaticInitializerStatements(grabResolverInitializers, true);
+            }
+        }
+
+        if (!grabMaps.isEmpty()) {
+            Map<String, Object> basicArgs = new HashMap<String, Object>();
+            basicArgs.put("classLoader", loader != null ? loader : sourceUnit.getClassLoader());
+            if (!grabExcludeMaps.isEmpty()) basicArgs.put("excludes", grabExcludeMaps);
+            if (autoDownload != null) basicArgs.put(AUTO_DOWNLOAD_SETTING, autoDownload);
+            if (disableChecksums != null) basicArgs.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
+            if (systemProperties != null) basicArgs.put(SYSTEM_PROPERTIES_SETTING, systemProperties);
+
+            try {
+                Grape.grab(basicArgs, grabMaps.toArray(new Map[grabMaps.size()]));
+                // grab may have added more transformations through new URLs added to classpath, so do one more scan
+                if (compilationUnit!=null) {
+                    ASTTransformationVisitor.addGlobalTransformsAfterGrab(compilationUnit.getASTTransformationsContext());
+                }
+            } catch (RuntimeException re) {
+                // Decided against syntax exception since this is not a syntax error.
+                // The down side is we lose line number information for the offending
+                // @Grab annotation.
+                source.addException(re);
+            }
+        }
+    }
+
+    private void callGrabAsStaticInitIfNeeded(ClassNode classNode, ClassNode grapeClassNode, List<Map<String,Object>> grabMapsInit, List<Map<String, Object>> grabExcludeMaps) {
+        List<Statement> grabInitializers = new ArrayList<Statement>();
+        MapExpression basicArgs = new MapExpression();
+        if (autoDownload != null)  {
+            basicArgs.addMapEntryExpression(constX(AUTO_DOWNLOAD_SETTING), constX(autoDownload));
+        }
+
+        if (disableChecksums != null)  {
+            basicArgs.addMapEntryExpression(constX(DISABLE_CHECKSUMS_SETTING), constX(disableChecksums));
+        }
+
+        if (systemProperties != null && !systemProperties.isEmpty()) {
+            BlockStatement block = new BlockStatement();
+            for(Map.Entry e : systemProperties.entrySet()) {
+                block.addStatement(stmt(callX(SYSTEM_CLASSNODE, "setProperty", args(constX(e.getKey()), constX(e.getValue())))));
+            }
+            StaticMethodCallExpression enabled = callX(SYSTEM_CLASSNODE, "getProperty", args(constX("groovy.grape.enable"), constX("true")));
+            grabInitializers.add(ifS(eqX(enabled, constX("true")), block));
+        }
+
+        if (!grabExcludeMaps.isEmpty()) {
+            ListExpression list = new ListExpression();
+            for (Map<String, Object> map : grabExcludeMaps) {
+                Set<Map.Entry<String, Object>> entries = map.entrySet();
+                MapExpression inner = new MapExpression();
+                for (Map.Entry<String, Object> entry : entries) {
+                    inner.addMapEntryExpression(constX(entry.getKey()), constX(entry.getValue()));
+                }
+                list.addExpression(inner);
+            }
+            basicArgs.addMapEntryExpression(constX("excludes"), list);
+        }
+
+        List<Expression> argList = new ArrayList<Expression>();
+        argList.add(basicArgs);
+        if (grabMapsInit.isEmpty()) return;
+        for (Map<String, Object> grabMap : grabMapsInit) {
+            // add Grape.grab(excludeArgs, [group:group, module:module, version:version, classifier:classifier])
+            // or Grape.grab([group:group, module:module, version:version, classifier:classifier])
+            MapExpression dependencyArg = new MapExpression();
+            for (String s : GRAB_REQUIRED) {
+                dependencyArg.addMapEntryExpression(constX(s), constX(grabMap.get(s)));
+            }
+            for (String s : GRAB_OPTIONAL) {
+                if (grabMap.containsKey(s))
+                    dependencyArg.addMapEntryExpression(constX(s), constX(grabMap.get(s)));
+            }
+            argList.add(dependencyArg);
+        }
+        grabInitializers.add(stmt(callX(grapeClassNode, "grab", args(argList))));
+
+        // insert at beginning so we have the classloader set up before the class is called
+        classNode.addStaticInitializerStatements(grabInitializers, true);
+    }
+
+    private static void addGrabResolverAsStaticInitIfNeeded(ClassNode grapeClassNode, AnnotationNode node,
+                                                      List<Statement> grabResolverInitializers, Map<String, Object> grabResolverMap) {
+        if ((node.getMember("initClass") == null)
+            || (node.getMember("initClass") == ConstantExpression.TRUE))
+        {
+            MapExpression resolverArgs = new MapExpression();
+            for (Map.Entry<String, Object> next : grabResolverMap.entrySet()) {
+                resolverArgs.addMapEntryExpression(constX(next.getKey()), constX(next.getValue()));
+            }
+            grabResolverInitializers.add(stmt(callX(grapeClassNode, "addResolver", args(resolverArgs))));
+        }
+    }
+
+    private void addInitContextClassLoaderIfNeeded(ClassNode classNode) {
+        if (initContextClassLoader) {
+            Statement initStatement = stmt(callX(
+                            callX(THREAD_CLASSNODE, "currentThread"),
+                            "setContextClassLoader",
+                            callX(callThisX("getClass"), "getClassLoader")
+                    )
+            );
+            classNode.addObjectInitializerStatements(initStatement);
+        }
+    }
+
+    private void checkForClassLoader(AnnotationNode node) {
+        Object val = node.getMember("systemClassLoader");
+        if (val == null || !(val instanceof ConstantExpression)) return;
+        Object systemClassLoaderObject = ((ConstantExpression)val).getValue();
+        if (!(systemClassLoaderObject instanceof Boolean)) return;
+        Boolean systemClassLoader = (Boolean) systemClassLoaderObject;
+        if (systemClassLoader) loader = ClassLoader.getSystemClassLoader();
+    }
+
+    private void checkForInitContextClassLoader(AnnotationNode node) {
+        Object val = node.getMember("initContextClassLoader");
+        if (val == null || !(val instanceof ConstantExpression)) return;
+        Object initContextClassLoaderObject = ((ConstantExpression)val).getValue();
+        if (!(initContextClassLoaderObject instanceof Boolean)) return;
+        initContextClassLoader = (Boolean) initContextClassLoaderObject;
+    }
+
+    private void checkForAutoDownload(AnnotationNode node) {
+        Object val = node.getMember(AUTO_DOWNLOAD_SETTING);
+        if (val == null || !(val instanceof ConstantExpression)) return;
+        Object autoDownloadValue = ((ConstantExpression)val).getValue();
+        if (!(autoDownloadValue instanceof Boolean)) return;
+        autoDownload = (Boolean) autoDownloadValue;
+    }
+
+    private void checkForDisableChecksums(AnnotationNode node) {
+        Object val = node.getMember(DISABLE_CHECKSUMS_SETTING);
+        if (val == null || !(val instanceof ConstantExpression)) return;
+        Object disableChecksumsValue = ((ConstantExpression)val).getValue();
+        if (!(disableChecksumsValue instanceof Boolean)) return;
+        disableChecksums = (Boolean) disableChecksumsValue;
+    }
+
+    private void checkForSystemProperties(AnnotationNode node) {
+        systemProperties = new HashMap<String, String>();
+        List<String> nameValueList = AbstractASTTransformation.getMemberStringList(node, SYSTEM_PROPERTIES_SETTING);
+        if (nameValueList != null) {
+            for (String nameValue : nameValueList) {
+                int equalsDelim = nameValue.indexOf('=');
+                if (equalsDelim != -1) {
+                    systemProperties.put(nameValue.substring(0, equalsDelim), nameValue.substring(equalsDelim + 1));
+                }
+            }
+        }
+    }
+
+    private static void checkForConvenienceForm(AnnotationNode node, boolean exclude) {
+        Object val = node.getMember("value");
+        if (val == null || !(val instanceof ConstantExpression)) return;
+        Object allParts = ((ConstantExpression)val).getValue();
+        if (!(allParts instanceof String)) return;
+        String allstr = (String) allParts;
+
+        // strip off trailing attributes
+        boolean done = false;
+        while (!done) {
+            Matcher attrs = ATTRIBUTES_PATTERN.matcher(allstr);
+            if (attrs.find()) {
+                String attrName = attrs.group(2);
+                String attrValue = attrs.group(3);
+                if (attrName == null || attrValue == null) continue;
+                boolean isBool = GRAB_BOOLEAN.contains(attrName);
+                ConstantExpression value = constX(isBool ? Boolean.valueOf(attrValue) : attrValue);
+                value.setSourcePosition(node);
+                node.addMember(attrName, value);
+                int lastSemi = allstr.lastIndexOf(';');
+                if (lastSemi == -1) {
+                    allstr = "";
+                    break;
+                }
+                allstr = allstr.substring(0, lastSemi);
+            } else {
+                done = true;
+            }
+        }
+
+        if (allstr.contains("#")) {
+            // see: http://ant.apache.org/ivy/history/latest-milestone/textual.html
+            Matcher m = IVY_PATTERN.matcher(allstr);
+            if (!m.find()) return;
+            if (m.group(1) == null || m.group(2) == null) return;
+            node.addMember("module", constX(m.group(2)));
+            node.addMember("group", constX(m.group(1)));
+            if (m.group(6) != null) node.addMember("conf", constX(m.group(6)));
+            if (m.group(4) != null) node.addMember("version", constX(m.group(4)));
+            else if (!exclude && node.getMember("version") == null) node.addMember("version", constX("*"));
+            node.getMembers().remove("value");
+        } else if (allstr.contains(":")) {
+            // assume gradle syntax
+            // see: http://www.gradle.org/latest/docs/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
+            Map<String, Object> parts = GrapeUtil.getIvyParts(allstr);
+            for (Map.Entry<String, Object> entry : parts.entrySet()) {
+                String key = entry.getKey();
+                String value = entry.getValue().toString();
+                if (!key.equals("version") || !value.equals("*") || !exclude) {
+                    node.addMember(key, constX(value));
+                }
+            }
+            node.getMembers().remove("value");
+        }
+    }
+
+    private void extractGrab(Expression init, ConstantExpression ce) {
+        if (ce.getValue() instanceof AnnotationNode) {
+            AnnotationNode annotation = (AnnotationNode) ce.getValue();
+            if ((init != null) && (annotation.getMember("initClass") != null)) {
+                annotation.setMember("initClass", init);
+            }
+            String name = annotation.getClassNode().getName();
+            if ((GRAB_CLASS_NAME.equals(name))
+                    || (allowShortGrab && GRAB_SHORT_NAME.equals(name))
+                    || (grabAliases.contains(name))) {
+                grabAnnotations.add(annotation);
+            }
+            if ((GRABEXCLUDE_CLASS_NAME.equals(name))
+                    || (allowShortGrabExcludes && GRABEXCLUDE_SHORT_NAME.equals(name))
+                    || (grabExcludeAliases.contains(name))) {
+                grabExcludeAnnotations.add(annotation);
+            }
+            if ((GRABCONFIG_CLASS_NAME.equals(name))
+                    || (allowShortGrabConfig && GRABCONFIG_SHORT_NAME.equals(name))
+                    || (grabConfigAliases.contains(name))) {
+                grabConfigAnnotations.add(annotation);
+            }
+            if ((GRABRESOLVER_CLASS_NAME.equals(name))
+                    || (allowShortGrabResolver && GRABRESOLVER_SHORT_NAME.equals(name))
+                    || (grabResolverAliases.contains(name))) {
+                grabResolverAnnotations.add(annotation);
+            }
+        }
+    }
+
+    /**
+     * Adds the annotation to the internal target list if a match is found.
+     *
+     * @param node the AST node we are processing
+     */
+    public void visitAnnotations(AnnotatedNode node) {
+        super.visitAnnotations(node);
+        for (AnnotationNode an : node.getAnnotations()) {
+            String name = an.getClassNode().getName();
+            if ((GRAB_CLASS_NAME.equals(name))
+                    || (allowShortGrab && GRAB_SHORT_NAME.equals(name))
+                    || (grabAliases.contains(name))) {
+                grabAnnotations.add(an);
+            }
+            if ((GRABEXCLUDE_CLASS_NAME.equals(name))
+                    || (allowShortGrabExcludes && GRABEXCLUDE_SHORT_NAME.equals(name))
+                    || (grabExcludeAliases.contains(name))) {
+                grabExcludeAnnotations.add(an);
+            }
+            if ((GRABCONFIG_CLASS_NAME.equals(name))
+                    || (allowShortGrabConfig && GRABCONFIG_SHORT_NAME.equals(name))
+                    || (grabConfigAliases.contains(name))) {
+                grabConfigAnnotations.add(an);
+            }
+            if ((GRAPES_CLASS_NAME.equals(name))
+                    || (allowShortGrapes && GRAPES_SHORT_NAME.equals(name))
+                    || (grapesAliases.contains(name))) {
+                grapesAnnotations.add(an);
+            }
+            if ((GRABRESOLVER_CLASS_NAME.equals(name))
+                    || (allowShortGrabResolver && GRABRESOLVER_SHORT_NAME.equals(name))
+                    || (grabResolverAliases.contains(name))) {
+                grabResolverAnnotations.add(an);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/grape/Grape.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/grape/Grape.java b/src/main/groovy/groovy/grape/Grape.java
new file mode 100644
index 0000000..ad89a20
--- /dev/null
+++ b/src/main/groovy/groovy/grape/Grape.java
@@ -0,0 +1,236 @@
+/*
+ *  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 groovy.grape;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Facade to GrapeEngine.
+ */
+public class Grape {
+
+    public static final String AUTO_DOWNLOAD_SETTING = "autoDownload";
+    public static final String DISABLE_CHECKSUMS_SETTING = "disableChecksums";
+    public static final String SYSTEM_PROPERTIES_SETTING = "systemProperties";
+
+    private static boolean enableGrapes = Boolean.valueOf(System.getProperty("groovy.grape.enable", "true"));
+    private static boolean enableAutoDownload = Boolean.valueOf(System.getProperty("groovy.grape.autoDownload", "true"));
+    private static boolean disableChecksums = Boolean.valueOf(System.getProperty("groovy.grape.disableChecksums", "false"));
+    protected static GrapeEngine instance;
+
+    /**
+     * This is a static access kill-switch.  All of the static shortcut
+     * methods in this class will not work if this property is set to false.
+     * By default it is set to true.
+     */
+    public static boolean getEnableGrapes() {
+        return enableGrapes;
+    }
+
+    /**
+     * This is a static access kill-switch.  All of the static shortcut
+     * methods in this class will not work if this property is set to false.
+     * By default it is set to true.
+     */
+    public static void setEnableGrapes(boolean enableGrapes) {
+        Grape.enableGrapes = enableGrapes;
+    }
+
+    /**
+     * This is a static access auto download enabler.  It will set the
+     * 'autoDownload' value to the passed in arguments map if not already set.
+     * If 'autoDownload' is set the value will not be adjusted.
+     * <p>
+     * This applies to the grab and resolve calls.
+     * <p>
+     * If it is set to false, only previously downloaded grapes
+     * will be used.  This may cause failure in the grape call
+     * if the library has not yet been downloaded
+     * <p>
+     * If it is set to true, then any jars not already downloaded will
+     * automatically be downloaded.  Also, any versions expressed as a range
+     * will be checked for new versions and downloaded (with dependencies)
+     * if found.
+     * <p>
+     * By default it is set to true.
+     */
+    public static boolean getEnableAutoDownload() {
+        return enableAutoDownload;
+    }
+
+    /**
+     * This is a static access auto download enabler.  It will set the
+     * 'autoDownload' value to the passed in arguments map if not already
+     * set.  If 'autoDownload' is set the value will not be adjusted.
+     * <p>
+     * This applies to the grab and resolve calls.
+     * <p>
+     * If it is set to false, only previously downloaded grapes
+     * will be used.  This may cause failure in the grape call
+     * if the library has not yet been downloaded.
+     * <p>
+     * If it is set to true, then any jars not already downloaded will
+     * automatically be downloaded.  Also, any versions expressed as a range
+     * will be checked for new versions and downloaded (with dependencies)
+     * if found. By default it is set to true.
+     */
+    public static void setEnableAutoDownload(boolean enableAutoDownload) {
+        Grape.enableAutoDownload = enableAutoDownload;
+    }
+
+    /**
+     * Global flag to ignore checksums.
+     * By default it is set to false.
+     */
+    public static boolean getDisableChecksums() {
+        return disableChecksums;
+    }
+
+    /**
+     * Set global flag to ignore checksums.
+     * By default it is set to false.
+     */
+    public static void setDisableChecksums(boolean disableChecksums) {
+        Grape.disableChecksums = disableChecksums;
+    }
+
+    public static synchronized GrapeEngine getInstance() {
+        if (instance == null) {
+            try {
+                // by default use GrapeIvy
+                //TODO META-INF/services resolver?
+                instance = (GrapeEngine) Class.forName("groovy.grape.GrapeIvy").newInstance();
+            } catch (InstantiationException e) {
+                //LOGME
+            } catch (IllegalAccessException e) {
+                //LOGME
+            } catch (ClassNotFoundException e) {
+                //LOGME
+            }
+        }
+        return instance;
+    }
+
+    public static void grab(String endorsed) {
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                instance.grab(endorsed);
+            }
+        }
+    }
+
+    public static void grab(Map<String, Object> dependency) {
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                if (!dependency.containsKey(AUTO_DOWNLOAD_SETTING)) {
+                    dependency.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
+                }
+                if (!dependency.containsKey(DISABLE_CHECKSUMS_SETTING)) {
+                    dependency.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
+                }
+                instance.grab(dependency);
+            }
+        }
+    }
+
+    public static void grab(Map<String, Object> args, Map... dependencies) {
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                if (!args.containsKey(AUTO_DOWNLOAD_SETTING)) {
+                    args.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
+                }
+                if (!args.containsKey(DISABLE_CHECKSUMS_SETTING)) {
+                    args.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
+                }
+                instance.grab(args, dependencies);
+            }
+        }
+    }
+
+    public static Map<String, Map<String, List<String>>> enumerateGrapes() {
+        Map<String, Map<String, List<String>>> grapes = null;
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                grapes = instance.enumerateGrapes();
+            }
+        }
+        if (grapes == null) {
+            return Collections.emptyMap();
+        } else {
+            return grapes;
+        }
+    }
+
+    public static URI[] resolve(Map<String, Object> args, Map... dependencies) {
+        return resolve(args, null, dependencies);
+    }
+    
+    public static URI[] resolve(Map<String, Object> args, List depsInfo, Map... dependencies) {
+        URI[] uris = null;
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                if (!args.containsKey(AUTO_DOWNLOAD_SETTING)) {
+                    args.put(AUTO_DOWNLOAD_SETTING, enableAutoDownload);
+                }
+                if (!args.containsKey(DISABLE_CHECKSUMS_SETTING)) {
+                    args.put(DISABLE_CHECKSUMS_SETTING, disableChecksums);
+                }
+                uris = instance.resolve(args, depsInfo, dependencies);
+            }
+        }
+        if (uris == null) {
+            return new URI[0];
+        } else {
+            return uris;
+        }
+    }
+
+    public static Map[] listDependencies(ClassLoader cl) {
+        Map[] maps = null;
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                maps = instance.listDependencies(cl);
+            }
+        }
+        if (maps == null) {
+            return new Map[0];
+        } else {
+            return maps;
+        }
+
+    }
+    
+    public static void addResolver(Map<String, Object> args) {
+        if (enableGrapes) {
+            GrapeEngine instance = getInstance();
+            if (instance != null) {
+                instance.addResolver(args);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/grape/GrapeEngine.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/grape/GrapeEngine.java b/src/main/groovy/groovy/grape/GrapeEngine.java
new file mode 100644
index 0000000..d98882f
--- /dev/null
+++ b/src/main/groovy/groovy/grape/GrapeEngine.java
@@ -0,0 +1,46 @@
+/*
+ *  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 groovy.grape;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Danno Ferrin
+ */
+public interface GrapeEngine {
+
+    Object grab(String endorsedModule);
+
+    Object grab(Map args);
+
+    Object grab(Map args, Map... dependencies);
+
+    Map<String, Map<String, List<String>>> enumerateGrapes();
+
+    URI[] resolve(Map args, Map... dependencies);
+
+    URI[] resolve(Map args, List depsInfo, Map... dependencies);
+
+    Map[] listDependencies(ClassLoader classLoader);
+
+    void addResolver(Map<String, Object> args);
+}
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/grape/GrapeIvy.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/grape/GrapeIvy.groovy b/src/main/groovy/groovy/grape/GrapeIvy.groovy
new file mode 100644
index 0000000..a2c22a8
--- /dev/null
+++ b/src/main/groovy/groovy/grape/GrapeIvy.groovy
@@ -0,0 +1,729 @@
+/*
+ *  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 groovy.grape
+
+import org.apache.groovy.plugin.GroovyRunner
+import org.apache.groovy.plugin.GroovyRunnerRegistry
+import org.apache.ivy.Ivy
+import org.apache.ivy.core.cache.ResolutionCacheManager
+import org.apache.ivy.core.event.IvyListener
+import org.apache.ivy.core.event.download.PrepareDownloadEvent
+import org.apache.ivy.core.event.resolve.StartResolveEvent
+import org.apache.ivy.core.module.descriptor.Configuration
+import org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor
+import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
+import org.apache.ivy.core.module.descriptor.DefaultExcludeRule
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor
+import org.apache.ivy.core.module.id.ArtifactId
+import org.apache.ivy.core.module.id.ModuleId
+import org.apache.ivy.core.module.id.ModuleRevisionId
+import org.apache.ivy.core.report.ArtifactDownloadReport
+import org.apache.ivy.core.report.ResolveReport
+import org.apache.ivy.core.resolve.ResolveOptions
+import org.apache.ivy.core.settings.IvySettings
+import org.apache.ivy.plugins.matcher.ExactPatternMatcher
+import org.apache.ivy.plugins.matcher.PatternMatcher
+import org.apache.ivy.plugins.resolver.ChainResolver
+import org.apache.ivy.plugins.resolver.IBiblioResolver
+import org.apache.ivy.util.DefaultMessageLogger
+import org.apache.ivy.util.Message
+import org.codehaus.groovy.reflection.CachedClass
+import org.codehaus.groovy.reflection.ClassInfo
+import org.codehaus.groovy.reflection.ReflectionUtils
+import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl
+
+import javax.xml.parsers.DocumentBuilderFactory
+import java.util.jar.JarFile
+import java.util.regex.Pattern
+import java.util.zip.ZipEntry
+import java.util.zip.ZipException
+import java.util.zip.ZipFile
+
+/**
+ * @author Danno Ferrin
+ * @author Paul King
+ * @author Roshan Dawrani (roshandawrani)
+ */
+class GrapeIvy implements GrapeEngine {
+
+    static final int DEFAULT_DEPTH = 3
+
+    private static final String METAINF_PREFIX = 'META-INF/services/'
+    private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.class.getName()
+
+    private final exclusiveGrabArgs = [
+            ['group', 'groupId', 'organisation', 'organization', 'org'],
+            ['module', 'artifactId', 'artifact'],
+            ['version', 'revision', 'rev'],
+            ['conf', 'scope', 'configuration'],
+        ].inject([:], {m, g -> g.each {a -> m[a] = (g - a) as Set};  m})
+
+    boolean enableGrapes
+    Ivy ivyInstance
+    Set<String> resolvedDependencies
+    Set<String> downloadedArtifacts
+    // weak hash map so we don't leak loaders directly
+    Map<ClassLoader, Set<IvyGrabRecord>> loadedDeps = new WeakHashMap<ClassLoader, Set<IvyGrabRecord>>()
+    // set that stores the IvyGrabRecord(s) for all the dependencies in each grab() call
+    Set<IvyGrabRecord> grabRecordsForCurrDependencies = new LinkedHashSet<IvyGrabRecord>()
+    // we keep the settings so that addResolver can add to the resolver chain
+    IvySettings settings
+
+    public GrapeIvy() {
+        // if we are already initialized, quit
+        if (enableGrapes) return
+
+        // start ivy
+        Message.defaultLogger = new DefaultMessageLogger(System.getProperty("ivy.message.logger.level", "-1") as int)
+        settings = new IvySettings()
+
+        // configure settings
+        def grapeConfig = getLocalGrapeConfig()
+        if (!grapeConfig.exists()) {
+            grapeConfig = GrapeIvy.getResource("defaultGrapeConfig.xml")
+        }
+        try {
+            settings.load(grapeConfig) // exploit multi-methods for convenience
+        } catch (java.text.ParseException ex) {
+            def configLocation = grapeConfig instanceof File ? grapeConfig.canonicalPath : grapeConfig.toString()
+            System.err.println "Local Ivy config file '$configLocation' appears corrupt - ignoring it and using default config instead\nError was: " + ex.message
+            grapeConfig = GrapeIvy.getResource("defaultGrapeConfig.xml")
+            settings.load(grapeConfig)
+        }
+
+        // set up the cache dirs
+        settings.defaultCache = getGrapeCacheDir()
+
+        settings.setVariable("ivy.default.configuration.m2compatible", "true")
+        ivyInstance = Ivy.newInstance(settings)
+        org.apache.ivy.core.IvyContext.getContext().setIvy(ivyInstance);
+        resolvedDependencies = []
+        downloadedArtifacts = []
+
+        //TODO add grab to the DGM??
+
+        enableGrapes = true
+    }
+
+    public File getGroovyRoot() {
+        String root = System.getProperty("groovy.root")
+        def groovyRoot
+        if (root == null) {
+            groovyRoot = new File(System.getProperty("user.home"), ".groovy")
+        } else {
+            groovyRoot = new File(root)
+        }
+        try {
+            groovyRoot = groovyRoot.canonicalFile
+        } catch (IOException e) {
+            // skip canonicalization then, it may not exist yet
+        }
+        return groovyRoot
+    }
+
+    public File getLocalGrapeConfig() {
+        String grapeConfig = System.getProperty("grape.config")
+        if(grapeConfig) {
+            return new File(grapeConfig)
+        }
+        return new File(getGrapeDir(), 'grapeConfig.xml')
+    }
+
+    public File getGrapeDir() {
+        String root = System.getProperty("grape.root")
+        if(root == null) {
+            return getGroovyRoot()
+        }
+        File grapeRoot = new File(root)
+        try {
+            grapeRoot = grapeRoot.canonicalFile
+        } catch (IOException e) {
+            // skip canonicalization then, it may not exist yet
+        }
+        return grapeRoot
+    }
+
+    public File getGrapeCacheDir() {
+        File cache =  new File(getGrapeDir(), 'grapes')
+        if (!cache.exists()) {
+            cache.mkdirs()
+        } else if (!cache.isDirectory()) {
+            throw new RuntimeException("The grape cache dir $cache is not a directory")
+        }
+        return cache
+    }
+
+    public def chooseClassLoader(Map args) {
+        def loader = args.classLoader
+        if (!isValidTargetClassLoader(loader)) {
+            loader = (args.refObject?.class
+                        ?:ReflectionUtils.getCallingClass(args.calleeDepth?:1)
+                      )?.classLoader
+            while (loader && !isValidTargetClassLoader(loader)) {
+                loader = loader.parent
+            }
+            //if (!isValidTargetClassLoader(loader)) {
+            //    loader = Thread.currentThread().contextClassLoader
+            //}
+            //if (!isValidTargetClassLoader(loader)) {
+            //    loader = GrapeIvy.class.classLoader
+            //}
+            if (!isValidTargetClassLoader(loader)) {
+                throw new RuntimeException("No suitable ClassLoader found for grab")
+            }
+        }
+        return loader
+    }
+
+    private boolean isValidTargetClassLoader(loader) {
+        return isValidTargetClassLoaderClass(loader?.class)
+    }
+
+    private boolean isValidTargetClassLoaderClass(Class loaderClass) {
+        return (loaderClass != null) &&
+            (
+             (loaderClass.name == 'groovy.lang.GroovyClassLoader') ||
+             (loaderClass.name == 'org.codehaus.groovy.tools.RootLoader') ||
+             isValidTargetClassLoaderClass(loaderClass.superclass)
+            )
+    }
+
+    public IvyGrabRecord createGrabRecord(Map deps) {
+        // parse the actual dependency arguments
+        String module =  deps.module ?: deps.artifactId ?: deps.artifact
+        if (!module) {
+            throw new RuntimeException('grab requires at least a module: or artifactId: or artifact: argument')
+        }
+
+        String groupId = deps.group ?: deps.groupId ?: deps.organisation ?: deps.organization ?: deps.org ?: ''
+        String ext = deps.ext ?: deps.type ?: ''
+        String type = deps.type ?: ''
+
+        //TODO accept ranges and decode them?  except '1.0.0'..<'2.0.0' won't work in groovy
+        String version = deps.version ?: deps.revision ?: deps.rev ?: '*'
+        if ('*' == version) version = 'latest.default'
+
+        ModuleRevisionId mrid = ModuleRevisionId.newInstance(groupId, module, version)
+
+        boolean force      = deps.containsKey('force')      ? deps.force      : true
+        boolean changing   = deps.containsKey('changing')   ? deps.changing   : false
+        boolean transitive = deps.containsKey('transitive') ? deps.transitive : true
+        def conf = deps.conf ?: deps.scope ?: deps.configuration ?: ['default']
+        if (conf instanceof String) {
+            if (conf.startsWith("[") && conf.endsWith("]")) conf = conf[1..-2]
+            conf = conf.split(",").toList()
+        }
+        def classifier = deps.classifier ?: null
+
+        return new IvyGrabRecord(mrid:mrid, conf:conf, changing:changing, transitive:transitive, force:force, classifier:classifier, ext:ext, type:type)
+    }
+
+    public grab(String endorsedModule) {
+        return grab(group:'groovy.endorsed', module:endorsedModule, version:GroovySystem.version)
+    }
+
+    public grab(Map args) {
+        args.calleeDepth = args.calleeDepth?:DEFAULT_DEPTH + 1
+        return grab(args, args)
+    }
+
+    public grab(Map args, Map... dependencies) {
+        ClassLoader loader = null
+        grabRecordsForCurrDependencies.clear()
+
+        try {
+            // identify the target classloader early, so we fail before checking repositories
+            loader = chooseClassLoader(
+                classLoader:args.remove('classLoader'),
+                refObject:args.remove('refObject'),
+                calleeDepth:args.calleeDepth?:DEFAULT_DEPTH,
+            )
+
+            // check for non-fail null.
+            // If we were in fail mode we would have already thrown an exception
+            if (!loader) return
+
+            def uris = resolve(loader, args, dependencies)
+            for (URI uri in uris) {
+                loader.addURL(uri.toURL())
+            }
+            boolean runnerServicesFound = false
+            for (URI uri in uris) {
+                //TODO check artifact type, jar vs library, etc
+                File file = new File(uri)
+                processCategoryMethods(loader, file)
+                Collection<String> services = processMetaInfServices(loader, file)
+                if (!runnerServicesFound) {
+                    runnerServicesFound = services.contains(RUNNER_PROVIDER_CONFIG)
+                }
+            }
+            if (runnerServicesFound) {
+                GroovyRunnerRegistry.getInstance().load(loader)
+            }
+        } catch (Exception e) {
+            // clean-up the state first
+            Set<IvyGrabRecord> grabRecordsForCurrLoader = getLoadedDepsForLoader(loader)
+            grabRecordsForCurrLoader.removeAll(grabRecordsForCurrDependencies)
+            grabRecordsForCurrDependencies.clear()
+
+            if (args.noExceptions) {
+                return e
+            }
+            throw e
+        }
+        return null
+    }
+
+    private processCategoryMethods(ClassLoader loader, File file) {
+        // register extension methods if jar
+        if (file.name.toLowerCase().endsWith(".jar")) {
+            def mcRegistry = GroovySystem.metaClassRegistry
+            if (mcRegistry instanceof MetaClassRegistryImpl) {
+                try {
+                    JarFile jar = new JarFile(file)
+                    def entry = jar.getEntry(MetaClassRegistryImpl.MODULE_META_INF_FILE)
+                    if (entry) {
+                        Properties props = new Properties()
+                        props.load(jar.getInputStream(entry))
+                        Map<CachedClass, List<MetaMethod>> metaMethods = new HashMap<CachedClass, List<MetaMethod>>()
+                        mcRegistry.registerExtensionModuleFromProperties(props, loader, metaMethods)
+                        // add old methods to the map
+                        metaMethods.each { CachedClass c, List<MetaMethod> methods ->
+                            // GROOVY-5543: if a module was loaded using grab, there are chances that subclasses
+                            // have their own ClassInfo, and we must change them as well!
+                            Set<CachedClass> classesToBeUpdated = [c]
+                            ClassInfo.onAllClassInfo { ClassInfo info ->
+                                if (c.theClass.isAssignableFrom(info.cachedClass.theClass)) {
+                                    classesToBeUpdated << info.cachedClass
+                                }
+                            }
+                            classesToBeUpdated*.addNewMopMethods(methods)
+                        }
+                    }
+                }
+                catch(ZipException zipException) {
+                    throw new RuntimeException("Grape could not load jar '$file'", zipException)
+                }
+            }
+        }
+    }
+
+    void processOtherServices(ClassLoader loader, File f) {
+        processMetaInfServices(loader, f) // ignore result
+    }
+
+    /**
+     * Searches the given File for known service provider
+     * configuration files to process.
+     *
+     * @param loader used to locate service provider files
+     * @param f ZipFile in which to search for services
+     * @return a collection of service provider files that were found
+     */
+    private Collection<String> processMetaInfServices(ClassLoader loader, File f) {
+        List<String> services = new ArrayList<>()
+        try {
+            ZipFile zf = new ZipFile(f)
+            String providerConfig = 'org.codehaus.groovy.runtime.SerializedCategoryMethods'
+            ZipEntry serializedCategoryMethods = zf.getEntry(METAINF_PREFIX + providerConfig)
+            if (serializedCategoryMethods != null) {
+                services.add(providerConfig)
+                processSerializedCategoryMethods(zf.getInputStream(serializedCategoryMethods))
+            }
+            // TODO: remove in a future release (replaced by GroovyRunnerRegistry)
+            providerConfig = 'org.codehaus.groovy.plugins.Runners'
+            ZipEntry pluginRunners = zf.getEntry(METAINF_PREFIX + providerConfig)
+            if (pluginRunners != null) {
+                services.add(providerConfig)
+                processRunners(zf.getInputStream(pluginRunners), f.getName(), loader)
+            }
+            // GroovyRunners are loaded per ClassLoader using a ServiceLoader so here
+            // it only needs to be indicated that the service provider file was found
+            if (zf.getEntry(METAINF_PREFIX + RUNNER_PROVIDER_CONFIG) != null) {
+                services.add(RUNNER_PROVIDER_CONFIG)
+            }
+        } catch(ZipException ignore) {
+            // ignore files we can't process, e.g. non-jar/zip artifacts
+            // TODO log a warning
+        }
+        return services
+    }
+
+    void processSerializedCategoryMethods(InputStream is) {
+        is.text.readLines().each {
+            println it.trim() // TODO implement this or delete it
+        }
+    }
+
+    void processRunners(InputStream is, String name, ClassLoader loader) {
+        GroovyRunnerRegistry registry = GroovyRunnerRegistry.getInstance()
+        is.text.readLines()*.trim().findAll{ !it.isEmpty() && it[0] != '#' }.each {
+            try {
+                registry[name] = loader.loadClass(it).newInstance()
+            } catch (Exception ex) {
+                throw new IllegalStateException("Error registering runner class '" + it + "'", ex)
+            }
+        }
+    }
+
+    public ResolveReport getDependencies(Map args, IvyGrabRecord... grabRecords) {
+        ResolutionCacheManager cacheManager = ivyInstance.resolutionCacheManager
+
+        def millis = System.currentTimeMillis()
+        def md = new DefaultModuleDescriptor(ModuleRevisionId
+                .newInstance("caller", "all-caller", "working" + millis.toString()[-2..-1]), "integration", null, true)
+        md.addConfiguration(new Configuration('default'))
+        md.setLastModified(millis)
+
+        addExcludesIfNeeded(args, md)
+
+        for (IvyGrabRecord grabRecord : grabRecords) {
+            def conf = grabRecord.conf ?: ['*']
+            DefaultDependencyDescriptor dd = md.dependencies.find {it.dependencyRevisionId.equals(grabRecord.mrid)}
+            if (dd) {
+                createAndAddDependencyArtifactDescriptor(dd, grabRecord, conf)
+            } else {
+                dd = new DefaultDependencyDescriptor(md, grabRecord.mrid, grabRecord.force,
+                        grabRecord.changing, grabRecord.transitive)
+                conf.each {dd.addDependencyConfiguration('default', it)}
+                createAndAddDependencyArtifactDescriptor(dd, grabRecord, conf)
+                md.addDependency(dd)
+            }
+        }
+
+       // resolve grab and dependencies
+        ResolveOptions resolveOptions = new ResolveOptions()\
+            .setConfs(['default'] as String[])\
+            .setOutputReport(false)\
+            .setValidate(args.containsKey('validate') ? args.validate : false)
+
+        ivyInstance.settings.defaultResolver = args.autoDownload ? 'downloadGrapes' : 'cachedGrapes'
+        if (args.disableChecksums) {
+            ivyInstance.settings.setVariable('ivy.checksums', '')
+        }
+        boolean reportDownloads = System.getProperty('groovy.grape.report.downloads', 'false') == 'true'
+        if (reportDownloads) {
+            ivyInstance.eventManager.addIvyListener([progress:{ ivyEvent -> switch(ivyEvent) {
+                case StartResolveEvent:
+                    ivyEvent.moduleDescriptor.dependencies.each { it ->
+                        def name = it.toString()
+                        if (!resolvedDependencies.contains(name)) {
+                            resolvedDependencies << name
+                            System.err.println "Resolving " + name
+                        }
+                    }
+                    break
+                case PrepareDownloadEvent:
+                    ivyEvent.artifacts.each { it ->
+                        def name = it.toString()
+                        if (!downloadedArtifacts.contains(name)) {
+                            downloadedArtifacts << name
+                            System.err.println "Preparing to download artifact " + name
+                        }
+                    }
+                    break
+            } } ] as IvyListener)
+        }
+
+        ResolveReport report = null
+        int attempt = 8 // max of 8 times
+        while (true) {
+            try {
+                report = ivyInstance.resolve(md, resolveOptions)
+                break
+            } catch(IOException ioe) {
+                if (attempt--) {
+                    if (reportDownloads)
+                        System.err.println "Grab Error: retrying..."
+                    sleep attempt > 4 ? 350 : 1000
+                    continue
+                }
+                throw new RuntimeException("Error grabbing grapes -- $ioe.message")
+            }
+        }
+
+        if (report.hasError()) {
+            throw new RuntimeException("Error grabbing Grapes -- $report.allProblemMessages")
+        }
+        if (report.downloadSize && reportDownloads) {
+            System.err.println "Downloaded ${report.downloadSize >> 10} Kbytes in ${report.downloadTime}ms:\n  ${report.allArtifactsReports*.toString().join('\n  ')}"
+        }
+        md = report.moduleDescriptor
+
+        if (!args.preserveFiles) {
+            cacheManager.getResolvedIvyFileInCache(md.moduleRevisionId).delete()
+            cacheManager.getResolvedIvyPropertiesInCache(md.moduleRevisionId).delete()
+        }
+
+        return report
+    }
+
+    private void createAndAddDependencyArtifactDescriptor(DefaultDependencyDescriptor dd, IvyGrabRecord grabRecord, List<String> conf) {
+        // TODO: find out "unknown" reason and change comment below - also, confirm conf[0] check vs conf.contains('optional')
+        if (conf[0]!="optional" || grabRecord.classifier) {  // for some unknown reason optional dependencies should not have an artifactDescriptor
+            def dad = new DefaultDependencyArtifactDescriptor(dd,
+                    grabRecord.mrid.name, grabRecord.type ?: 'jar', grabRecord.ext ?: 'jar', null, grabRecord.classifier ? [classifier: grabRecord.classifier] : null)
+            conf.each { dad.addConfiguration(it) }
+            dd.addDependencyArtifact('default', dad)
+        }
+    }
+
+    public void uninstallArtifact(String group, String module, String rev) {
+        // TODO consider transitive uninstall as an option
+        Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
+        grapeCacheDir.eachDir { File groupDir ->
+            if (groupDir.name == group) groupDir.eachDir { File moduleDir ->
+                if (moduleDir.name == module) moduleDir.eachFileMatch(ivyFilePattern) { File ivyFile ->
+                    def m = ivyFilePattern.matcher(ivyFile.name)
+                    if (m.matches() && m.group(1) == rev) {
+                        // TODO handle other types? e.g. 'dlls'
+                        def jardir = new File(moduleDir, 'jars')
+                        if (!jardir.exists()) return
+                        def dbf = DocumentBuilderFactory.newInstance()
+                        def db = dbf.newDocumentBuilder()
+                        def root = db.parse(ivyFile).documentElement
+                        def publis = root.getElementsByTagName('publications')
+                        for (int i=0; i<publis.length;i++) {
+                            def artifacts = publis.item(i).getElementsByTagName('artifact')
+                            for (int j=0; j<artifacts.length; j++) {
+                                def artifact = artifacts.item(j)
+                                def attrs = artifact.attributes
+                                def name = attrs.getNamedItem('name').getTextContent() + "-$rev"
+                                def classifier = attrs.getNamedItemNS("m", "classifier")?.getTextContent()
+                                if (classifier) name += "-$classifier"
+                                name += ".${attrs.getNamedItem('ext').getTextContent()}"
+                                def jarfile = new File(jardir, name)
+                                if (jarfile.exists()) {
+                                    println "Deleting ${jarfile.name}"
+                                    jarfile.delete()
+                                }
+                            }
+                        }
+                        ivyFile.delete()
+                    }
+                }
+            }
+        }
+    }
+
+    private addExcludesIfNeeded(Map args, DefaultModuleDescriptor md) {
+        if (!args.containsKey('excludes')) return
+        args.excludes.each{ map ->
+            def excludeRule = new DefaultExcludeRule(new ArtifactId(
+                    new ModuleId(map.group, map.module), PatternMatcher.ANY_EXPRESSION,
+                    PatternMatcher.ANY_EXPRESSION,
+                    PatternMatcher.ANY_EXPRESSION),
+                    ExactPatternMatcher.INSTANCE, null)
+            excludeRule.addConfiguration('default')
+            md.addExcludeRule(excludeRule)
+        }
+    }
+
+    public Map<String, Map<String, List<String>>> enumerateGrapes() {
+        Map<String, Map<String, List<String>>> bunches = [:]
+        Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
+        grapeCacheDir.eachDir {File groupDir ->
+            Map<String, List<String>> grapes = [:]
+            bunches[groupDir.name] = grapes
+            groupDir.eachDir { File moduleDir ->
+                def versions = []
+                moduleDir.eachFileMatch(ivyFilePattern) {File ivyFile ->
+                    def m = ivyFilePattern.matcher(ivyFile.name)
+                    if (m.matches()) versions += m.group(1)
+                }
+                grapes[moduleDir.name] = versions
+            }
+        }
+        return bunches
+    }
+
+    public URI[] resolve(Map args, Map ... dependencies) {
+        resolve(args, null, dependencies)
+    }
+
+    public URI[] resolve(Map args, List depsInfo, Map ... dependencies) {
+        // identify the target classloader early, so we fail before checking repositories
+        def loader = chooseClassLoader(
+                classLoader: args.remove('classLoader'),
+                refObject: args.remove('refObject'),
+                calleeDepth: args.calleeDepth ?: DEFAULT_DEPTH,
+        )
+
+        // check for non-fail null.
+        // If we were in fail mode we would have already thrown an exception
+        if (!loader) return
+
+        resolve(loader, args, depsInfo, dependencies)
+    }
+
+    URI [] resolve(ClassLoader loader, Map args, Map... dependencies) {
+        return resolve(loader, args, null, dependencies)
+    }
+
+    URI [] resolve(ClassLoader loader, Map args, List depsInfo, Map... dependencies) {
+        // check for mutually exclusive arguments
+        Set keys = args.keySet()
+        keys.each {a ->
+            Set badArgs = exclusiveGrabArgs[a]
+            if (badArgs && !badArgs.disjoint(keys)) {
+                throw new RuntimeException("Mutually exclusive arguments passed into grab: ${keys.intersect(badArgs) + a}")
+            }
+        }
+
+        // check the kill switch
+        if (!enableGrapes) { return }
+
+        boolean populateDepsInfo = (depsInfo != null)
+
+        Set<IvyGrabRecord> localDeps = getLoadedDepsForLoader(loader)
+
+        dependencies.each {
+            IvyGrabRecord igr = createGrabRecord(it)
+            grabRecordsForCurrDependencies.add(igr)
+            localDeps.add(igr)
+        }
+        // the call to reverse ensures that the newest additions are in
+        // front causing existing dependencies to come last and thus
+        // claiming higher priority.  Thus when module versions clash we
+        // err on the side of using the class already loaded into the
+        // classloader rather than adding another jar of the same module
+        // with a different version
+        ResolveReport report = null
+        try {
+            report = getDependencies(args, *localDeps.asList().reverse())
+        } catch (Exception e) {
+            // clean-up the state first
+            localDeps.removeAll(grabRecordsForCurrDependencies)
+            grabRecordsForCurrDependencies.clear()
+            throw e
+        }
+
+        List<URI> results = []
+        for (ArtifactDownloadReport adl in report.allArtifactsReports) {
+            //TODO check artifact type, jar vs library, etc
+            if (adl.localFile) {
+                results += adl.localFile.toURI()
+            }
+        }
+
+        if (populateDepsInfo) {
+            def deps = report.dependencies
+            deps.each { depNode ->
+                def id = depNode.id
+                depsInfo << ['group' : id.organisation, 'module' : id.name, 'revision' : id.revision]
+            }
+        }
+
+        return results as URI[]
+    }
+
+    private Set<IvyGrabRecord> getLoadedDepsForLoader(ClassLoader loader) {
+        Set<IvyGrabRecord> localDeps = loadedDeps.get(loader)
+        if (localDeps == null) {
+            // use a linked set to preserve initial insertion order
+            localDeps = new LinkedHashSet<IvyGrabRecord>()
+            loadedDeps.put(loader, localDeps)
+        }
+        return localDeps
+    }
+
+    public Map[] listDependencies (ClassLoader classLoader) {
+        if (loadedDeps.containsKey(classLoader)) {
+            List<Map> results = []
+            loadedDeps[classLoader].each { IvyGrabRecord grabbed ->
+                def dep =  [
+                    group : grabbed.mrid.organisation,
+                    module : grabbed.mrid.name,
+                    version : grabbed.mrid.revision
+                ]
+                if (grabbed.conf != ['default']) {
+                    dep.conf = grabbed.conf
+                }
+                if (grabbed.changing) {
+                    dep.changing = grabbed.changing
+                }
+                if (!grabbed.transitive) {
+                    dep.transitive = grabbed.transitive
+                }
+                if (!grabbed.force) {
+                    dep.force = grabbed.force
+                }
+                if (grabbed.classifier) {
+                    dep.classifier = grabbed.classifier
+                }
+                if (grabbed.ext) {
+                    dep.ext = grabbed.ext
+                }
+                if (grabbed.type) {
+                    dep.type = grabbed.type
+                }
+                results << dep
+            }
+            return results
+        }
+        return null
+    }
+
+    public void addResolver(Map<String, Object> args) {
+        ChainResolver chainResolver = settings.getResolver("downloadGrapes")
+
+        IBiblioResolver resolver = new IBiblioResolver(name: args.name, root:args.root,
+              m2compatible:(args.m2Compatible ?: true), settings:settings)
+
+        chainResolver.add(resolver)
+
+        ivyInstance = Ivy.newInstance(settings)
+        resolvedDependencies = []
+        downloadedArtifacts = []
+    }
+}
+
+class IvyGrabRecord {
+    ModuleRevisionId mrid
+    List<String> conf
+    boolean changing
+    boolean transitive
+    boolean force
+    String classifier
+    String ext
+    String type
+
+    public int hashCode() {
+        return (mrid.hashCode() ^ conf.hashCode()
+            ^ (changing ? 0xaaaaaaaa : 0x55555555)
+            ^ (transitive ? 0xbbbbbbbb : 0x66666666)
+            ^ (force ? 0xcccccccc: 0x77777777)
+            ^ (classifier ? classifier.hashCode() : 0)
+            ^ (ext ? ext.hashCode() : 0)
+            ^ (type ? type.hashCode() : 0))
+    }
+
+    public boolean equals(Object o) {
+        return ((o.class == IvyGrabRecord)
+            && (changing == o.changing)
+            && (transitive == o.transitive)
+            && (force== o.force)
+            && (mrid == o.mrid)
+            && (conf == o.conf)
+            && (classifier == o.classifier)
+            && (ext == o.ext)
+            && (type == o.type))
+    }
+
+}


[35/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/MetaClassImpl.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/MetaClassImpl.java b/src/main/groovy/groovy/lang/MetaClassImpl.java
new file mode 100644
index 0000000..601d5bb
--- /dev/null
+++ b/src/main/groovy/groovy/lang/MetaClassImpl.java
@@ -0,0 +1,3958 @@
+/*
+ *  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 groovy.lang;
+
+import org.apache.groovy.internal.util.UncheckedThrow;
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.classgen.asm.BytecodeHelper;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.Phases;
+import org.codehaus.groovy.reflection.CacheAccessControlException;
+import org.codehaus.groovy.reflection.CachedClass;
+import org.codehaus.groovy.reflection.CachedConstructor;
+import org.codehaus.groovy.reflection.CachedField;
+import org.codehaus.groovy.reflection.CachedMethod;
+import org.codehaus.groovy.reflection.ClassInfo;
+import org.codehaus.groovy.reflection.GeneratedMetaMethod;
+import org.codehaus.groovy.reflection.ParameterTypes;
+import org.codehaus.groovy.reflection.ReflectionCache;
+import org.codehaus.groovy.reflection.android.AndroidSupport;
+import org.codehaus.groovy.runtime.ConvertedClosure;
+import org.codehaus.groovy.runtime.CurriedClosure;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.GeneratedClosure;
+import org.codehaus.groovy.runtime.GroovyCategorySupport;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.runtime.MethodClosure;
+import org.codehaus.groovy.runtime.callsite.AbstractCallSite;
+import org.codehaus.groovy.runtime.callsite.CallSite;
+import org.codehaus.groovy.runtime.callsite.ConstructorSite;
+import org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite;
+import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
+import org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite;
+import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
+import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
+import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
+import org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite;
+import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
+import org.codehaus.groovy.runtime.metaclass.MetaMethodIndex;
+import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty;
+import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty;
+import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
+import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
+import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
+import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
+import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty;
+import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.NewMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
+import org.codehaus.groovy.runtime.metaclass.TransformMetaMethod;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+import org.codehaus.groovy.runtime.typehandling.NumberMathModificationInfo;
+import org.codehaus.groovy.runtime.wrappers.Wrapper;
+import org.codehaus.groovy.util.ComplexKeyHashMap;
+import org.codehaus.groovy.util.FastArray;
+import org.codehaus.groovy.util.SingleKeyHashMap;
+import org.objectweb.asm.ClassVisitor;
+
+import java.beans.BeanInfo;
+import java.beans.EventSetDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
+import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;
+
+/**
+ * Allows methods to be dynamically added to existing classes at runtime
+ * @see groovy.lang.MetaClass
+ */
+public class MetaClassImpl implements MetaClass, MutableMetaClass {
+
+    public static final Object[] EMPTY_ARGUMENTS = {};
+
+    protected static final String STATIC_METHOD_MISSING = "$static_methodMissing";
+    protected static final String STATIC_PROPERTY_MISSING = "$static_propertyMissing";
+    protected static final String METHOD_MISSING = "methodMissing";
+    protected static final String PROPERTY_MISSING = "propertyMissing";
+    protected static final String INVOKE_METHOD_METHOD = "invokeMethod";
+
+    private static final String CLOSURE_CALL_METHOD = "call";
+    private static final String CLOSURE_DO_CALL_METHOD = "doCall";
+    private static final String GET_PROPERTY_METHOD = "getProperty";
+    private static final String SET_PROPERTY_METHOD = "setProperty";
+    private static final Class[] METHOD_MISSING_ARGS = new Class[]{String.class, Object.class};
+    private static final Class[] GETTER_MISSING_ARGS = new Class[]{String.class};
+    private static final Class[] SETTER_MISSING_ARGS = METHOD_MISSING_ARGS;
+    private static final Comparator<CachedClass> CACHED_CLASS_NAME_COMPARATOR = new Comparator<CachedClass>() {
+        public int compare(final CachedClass o1, final CachedClass o2) {
+            return o1.getName().compareTo(o2.getName());
+        }
+    };
+    private static final MetaMethod[] EMPTY = new MetaMethod[0];
+    private static final MetaMethod AMBIGUOUS_LISTENER_METHOD = new DummyMetaMethod();
+
+    protected final Class theClass;
+    protected final CachedClass theCachedClass;
+    protected final boolean isGroovyObject;
+    protected final boolean isMap;
+    protected final MetaMethodIndex metaMethodIndex;
+
+    private final Index classPropertyIndex = new MethodIndex();
+    private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
+    private final Map<String, MetaMethod> listeners = new HashMap<String, MetaMethod>();
+    private final List<MetaMethod> allMethods = new ArrayList<MetaMethod>();
+    // we only need one of these that can be reused over and over.
+    private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
+    private final Index classPropertyIndexForSuper = new MethodIndex();
+    private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<MetaMethod>();
+    private final MetaMethod [] myNewMetaMethods;
+    private final MetaMethod [] additionalMetaMethods;
+
+    protected MetaMethod getPropertyMethod;
+    protected MetaMethod invokeMethodMethod;
+    protected MetaMethod setPropertyMethod;
+    protected MetaClassRegistry registry;
+    private ClassNode classNode;
+    private FastArray constructors;
+    private volatile boolean initialized;
+    private MetaMethod genericGetMethod;
+    private MetaMethod genericSetMethod;
+    private MetaMethod propertyMissingGet;
+    private MetaMethod propertyMissingSet;
+    private MetaMethod methodMissing;
+    private MetaMethodIndex.Header mainClassMethodHeader;
+
+     /**
+      * Constructor
+      *
+      * @param theClass The class this is the metaclass dor
+      * @param add The methods for this class
+      */
+    public MetaClassImpl(final Class theClass, MetaMethod [] add) {
+        this.theClass = theClass;
+        theCachedClass = ReflectionCache.getCachedClass(theClass);
+        this.isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
+        this.isMap = Map.class.isAssignableFrom(theClass);
+        this.registry = GroovySystem.getMetaClassRegistry();
+        metaMethodIndex = new MetaMethodIndex(theCachedClass);
+        final MetaMethod[] metaMethods = theCachedClass.getNewMetaMethods();
+        if (add != null && !(add.length == 0)) {
+            List<MetaMethod> arr = new ArrayList<MetaMethod>();
+            arr.addAll(Arrays.asList(metaMethods));
+            arr.addAll(Arrays.asList(add));
+            myNewMetaMethods = arr.toArray(new MetaMethod[arr.size()]);
+            additionalMetaMethods = metaMethods;
+        }
+        else {
+            myNewMetaMethods = metaMethods;
+            additionalMetaMethods = EMPTY;
+        }
+    }
+
+    /**
+      * Constructor that sets the methods to null
+      *
+      * @param theClass The class this is the metaclass dor
+      */
+    public MetaClassImpl(final Class theClass) {
+        this(theClass, null);
+    }
+
+    /**
+     * Constructor with registry
+     *
+     * @param registry The metaclass registry for this MetaClass
+     * @param theClass The class
+     * @param add The methods
+     */
+    public MetaClassImpl(MetaClassRegistry registry, final Class theClass, MetaMethod add []) {
+        this(theClass, add);
+        this.registry = registry;
+        this.constructors = new FastArray(theCachedClass.getConstructors());
+    }
+
+    /**
+     * Constructor with registry setting methods to null
+     *
+     * @param registry The metaclass registry for this MetaClass
+     * @param theClass The class
+     */
+    public MetaClassImpl(MetaClassRegistry registry, final Class theClass) {
+        this(registry, theClass, null);
+    }
+
+    /**
+     * Returns the cached class for this metaclass
+     *
+     * @return The cached class.
+     */
+    public final CachedClass getTheCachedClass() {
+        return theCachedClass;
+    }
+
+    /**
+     * Returns the registry for this metaclass
+     * 
+     * @return The resgistry
+     */
+    public MetaClassRegistry getRegistry() {
+        return registry;
+    }
+
+    /**
+     * @see MetaObjectProtocol#respondsTo(Object, String, Object[])
+     */
+    public List respondsTo(Object obj, String name, Object[] argTypes) {
+        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        MetaMethod m = getMetaMethod(name, classes);
+        if (m!=null) {
+            return Collections.singletonList(m);
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * @see MetaObjectProtocol#respondsTo(Object, String)
+     */
+    public List respondsTo(final Object obj, final String name) {
+        final Object o = getMethods(getTheClass(), name, false);
+        if (o instanceof FastArray)
+            return ((FastArray) o).toList();
+        else
+            return Collections.singletonList(o);
+    }
+
+    /**
+     * @see MetaObjectProtocol#hasProperty(Object,String)
+     */
+    public MetaProperty hasProperty(Object obj, String name) {
+        return getMetaProperty(name);
+    }
+
+    /**
+     * @see MetaObjectProtocol#getMetaProperty(String)
+     */
+    public MetaProperty getMetaProperty(String name) {
+        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
+        if (propertyMap.containsKey(name)) {
+            return (MetaProperty) propertyMap.get(name);
+        } else if (staticPropertyIndex.containsKey(name)) {
+            return (MetaProperty) staticPropertyIndex.get(name);
+        } else {
+            propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
+            if (propertyMap.containsKey(name))
+                return (MetaProperty) propertyMap.get(name);
+            else {
+                CachedClass superClass = theCachedClass;
+                while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
+                    final MetaBeanProperty property = findPropertyInClassHierarchy(name, superClass);
+                    if (property != null) {
+                        onSuperPropertyFoundInHierarchy(property);
+                        return property;
+                    }
+                    superClass = superClass.getCachedSuperClass();
+                }
+                return null;
+            }
+        }
+    }
+
+    /**
+     * @see MetaObjectProtocol#getStaticMetaMethod(String, Object[])
+     */
+    public MetaMethod getStaticMetaMethod(String name, Object[] argTypes) {
+        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        return pickStaticMethod(name, classes);
+    }
+
+
+    /**
+     * @see MetaObjectProtocol#getMetaMethod(String, Object[])
+     */
+    public MetaMethod getMetaMethod(String name, Object[] argTypes) {
+        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        return pickMethod(name, classes);
+    }
+
+    /**
+     *Returns the class this object this is the metaclass of.
+     * 
+     * @return The class contained by this metaclass
+     */
+    public Class getTheClass() {
+        return this.theClass;
+    }
+
+    /**
+     * Return wether the class represented by this metaclass instance is an instance of the GroovyObject class
+     *
+     * @return true if this is a groovy class, false otherwise.
+     */
+    public boolean isGroovyObject() {
+        return isGroovyObject;
+    }
+
+    /**
+     * Fills the method index
+     */
+    private void fillMethodIndex() {
+        mainClassMethodHeader = metaMethodIndex.getHeader(theClass);
+        LinkedList<CachedClass> superClasses = getSuperClasses();
+        CachedClass firstGroovySuper = calcFirstGroovySuperClass(superClasses);
+
+        Set<CachedClass> interfaces = theCachedClass.getInterfaces();
+        addInterfaceMethods(interfaces);
+
+        populateMethods(superClasses, firstGroovySuper);
+
+        inheritInterfaceNewMetaMethods(interfaces);
+        if (isGroovyObject) {
+          metaMethodIndex.copyMethodsToSuper();
+
+          connectMultimethods(superClasses, firstGroovySuper);
+          removeMultimethodsOverloadedWithPrivateMethods();
+
+          replaceWithMOPCalls(theCachedClass.mopMethods);
+        }
+    }
+
+    private void populateMethods(LinkedList<CachedClass> superClasses, CachedClass firstGroovySuper) {
+
+        MetaMethodIndex.Header header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
+        CachedClass c;
+        Iterator<CachedClass> iter = superClasses.iterator();
+        for (; iter.hasNext();) {
+            c = iter.next();
+
+            CachedMethod[] cachedMethods = c.getMethods();
+            for (CachedMethod metaMethod : cachedMethods) {
+                addToAllMethodsIfPublic(metaMethod);
+                if (!metaMethod.isPrivate() || c == firstGroovySuper)
+                    addMetaMethodToIndex(metaMethod, header);
+            }
+
+            MetaMethod[] cachedMethods1 = getNewMetaMethods(c);
+            for (final MetaMethod method : cachedMethods1) {
+                if (!newGroovyMethodsSet.contains(method)) {
+                    newGroovyMethodsSet.add(method);
+                    addMetaMethodToIndex(method, header);
+                }
+            }
+
+            if (c == firstGroovySuper)
+              break;
+        }
+
+        MetaMethodIndex.Header last = header;
+        for (;iter.hasNext();) {
+            c = iter.next();
+            header = metaMethodIndex.getHeader(c.getTheClass());
+
+            if (last != null) {
+                metaMethodIndex.copyNonPrivateMethods(last, header);
+            }
+            last = header;
+
+            for (CachedMethod metaMethod : c.getMethods()) {
+                addToAllMethodsIfPublic(metaMethod);
+                addMetaMethodToIndex(metaMethod, header);
+            }
+
+            for (final MetaMethod method : getNewMetaMethods(c)) {
+                if (method.getName().equals("<init>") && !method.getDeclaringClass().equals(theCachedClass)) continue;
+                if (!newGroovyMethodsSet.contains(method)) {
+                    newGroovyMethodsSet.add(method);
+                    addMetaMethodToIndex(method, header);
+                }
+            }
+        }
+    }
+
+    private MetaMethod[] getNewMetaMethods(CachedClass c) {
+        if (theCachedClass != c)
+          return c.getNewMetaMethods();
+
+        return myNewMetaMethods;
+    }
+
+    private void addInterfaceMethods(Set<CachedClass> interfaces) {
+        MetaMethodIndex.Header header = metaMethodIndex.getHeader(theClass);
+        for (CachedClass c : interfaces) {
+            final CachedMethod[] m = c.getMethods();
+            for (int i = 0; i != m.length; ++i) {
+                MetaMethod method = m[i];
+                addMetaMethodToIndex(method, header);
+            }
+        }
+    }
+
+    protected LinkedList<CachedClass> getSuperClasses() {
+        LinkedList<CachedClass> superClasses = new LinkedList<CachedClass>();
+
+        if (theClass.isInterface()) {
+            superClasses.addFirst(ReflectionCache.OBJECT_CLASS);
+        } else {
+            for (CachedClass c = theCachedClass; c != null; c = c.getCachedSuperClass()) {
+                superClasses.addFirst(c);
+            }
+            if (theCachedClass.isArray && theClass != Object[].class && !theClass.getComponentType().isPrimitive()) {
+                superClasses.addFirst(ReflectionCache.OBJECT_ARRAY_CLASS);
+            }
+        }
+        return superClasses;
+    }
+
+    private void removeMultimethodsOverloadedWithPrivateMethods() {
+        MethodIndexAction mia = new MethodIndexAction() {
+            public boolean skipClass(Class clazz) {
+                return clazz == theClass;
+            }
+
+            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
+                if (e.methods == null)
+                  return;
+
+                boolean hasPrivate = false;
+                if (e.methods instanceof FastArray) {
+                    FastArray methods = (FastArray) e.methods;
+                    final int len = methods.size();
+                    final Object[] data = methods.getArray();
+                    for (int i = 0; i != len; ++i) {
+                        MetaMethod method = (MetaMethod) data[i];
+                        if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
+                            hasPrivate = true;
+                            break;
+                        }
+                    }
+                }
+                else {
+                    MetaMethod method = (MetaMethod) e.methods;
+                    if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
+                       hasPrivate = true;
+                    }
+                }
+
+                if (!hasPrivate) return;
+
+                // We have private methods for that name, so remove the
+                // multimethods. That is the same as in our index for
+                // super, so just copy the list from there. It is not
+                // possible to use a pointer here, because the methods
+                // in the index for super are replaced later by MOP
+                // methods like super$5$foo
+                final Object o = e.methodsForSuper;
+                if (o instanceof FastArray)
+                  e.methods = ((FastArray) o).copy();
+                else
+                  e.methods = o;
+            }
+        };
+        mia.iterate();
+    }
+
+
+    private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
+        // no MOP methods if not a child of GroovyObject
+        if (!isGroovyObject) return;
+
+        class MOPIter extends MethodIndexAction {
+            boolean useThis;
+
+            @Override
+            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
+                if (useThis) {
+                    if (e.methods == null)
+                      return;
+
+                    if (e.methods instanceof FastArray) {
+                        FastArray methods = (FastArray) e.methods;
+                        processFastArray(methods);
+                    }
+                    else {
+                        MetaMethod method = (MetaMethod) e.methods;
+                        if (method instanceof NewMetaMethod)
+                          return;
+                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
+                        String mopName = method.getMopName();
+                        int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
+                        if (index >= 0) {
+                            int from = index;
+                            while (from > 0 && mopMethods[from-1].getName().equals(mopName))
+                              from--;
+                            int to = index;
+                            while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
+                              to++;
+
+                            int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
+                            if (matchingMethod != -1) {
+                                e.methods = mopMethods[matchingMethod];
+                            }
+                        }
+                    }
+                }
+                else {
+                    if (e.methodsForSuper == null)
+                      return;
+
+                    if (e.methodsForSuper instanceof FastArray) {
+                        FastArray methods = (FastArray) e.methodsForSuper;
+                        processFastArray(methods);
+                    }
+                    else {
+                        MetaMethod method = (MetaMethod) e.methodsForSuper;
+                        if (method instanceof NewMetaMethod)
+                          return;
+                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
+                        String mopName = method.getMopName();
+                        // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
+                        // with the highest number. If we don't, no method may be found, leading to a stack overflow
+                        String[] decomposedMopName = decomposeMopName(mopName);
+                        int distance = Integer.parseInt(decomposedMopName[1]);
+                        while (distance>0) {
+                            String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
+                            int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
+                            if (index >= 0) {
+                                int from = index;
+                                while (from > 0 && mopMethods[from-1].getName().equals(fixedMopName))
+                                  from--;
+                                int to = index;
+                                while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(fixedMopName))
+                                  to++;
+    
+                                int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
+                                if (matchingMethod != -1) {
+                                    e.methodsForSuper = mopMethods[matchingMethod];
+                                    distance = 0;
+                                }
+                            }
+                            distance--;
+                        }
+                    }
+                }
+            }
+
+            private String[] decomposeMopName(final String mopName) {
+                int idx = mopName.indexOf("$");
+                if (idx>0) {
+                    int eidx = mopName.indexOf("$", idx+1);
+                    if (eidx>0) {
+                        return new String[] {
+                                mopName.substring(0, idx+1),
+                                mopName.substring(idx+1, eidx),
+                                mopName.substring(eidx)
+                        };
+                    }
+                }
+                return new String[]{"","0",mopName};
+            }
+
+            private void processFastArray(FastArray methods) {
+                final int len = methods.size();
+                final Object[] data = methods.getArray();
+                for (int i = 0; i != len; ++i) {
+                    MetaMethod method = (MetaMethod) data[i];
+                    if (method instanceof NewMetaMethod) continue;
+                    boolean isPrivate = Modifier.isPrivate(method.getModifiers());
+                    if (useThis ^ isPrivate) continue;
+                    String mopName = method.getMopName();
+                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
+                    if (index >= 0) {
+                        int from = index;
+                        while (from > 0 && mopMethods[from-1].getName().equals(mopName))
+                          from--;
+                        int to = index;
+                        while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
+                          to++;
+
+                        int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
+                        if (matchingMethod != -1) {
+                            methods.set(i, mopMethods[matchingMethod]);
+                        }
+                    }
+                }
+            }
+        }
+        MOPIter iter = new MOPIter();
+
+        // replace all calls for super with the correct MOP method
+        iter.useThis = false;
+        iter.iterate();
+        // replace all calls for this with the correct MOP method
+        iter.useThis = true;
+        iter.iterate();
+    }
+
+    private void inheritInterfaceNewMetaMethods(Set<CachedClass> interfaces) {
+        // add methods declared by DGM for interfaces
+        for (CachedClass cls : interfaces) {
+            MetaMethod methods[] = getNewMetaMethods(cls);
+            for (MetaMethod method : methods) {
+                boolean skip = false;
+                // skip DGM methods on an interface if the class already has the method
+                // but don't skip for GroovyObject-related methods as it breaks things :-(
+                if (method instanceof GeneratedMetaMethod && !isAssignableFrom(GroovyObject.class, method.getDeclaringClass().getTheClass())) {
+                    for (Method m : theClass.getMethods()) {
+                        if (method.getName().equals(m.getName())
+                                // below not true for DGM#push and also co-variant return scenarios
+                                //&& method.getReturnType().equals(m.getReturnType())
+                                && MetaMethod.equal(method.getParameterTypes(), m.getParameterTypes())) {
+                            skip = true;
+                            break;
+                        }
+                    }
+                }
+                if (!skip) {
+                    if (!newGroovyMethodsSet.contains(method)) {
+                        newGroovyMethodsSet.add(method);
+                    }
+                    addMetaMethodToIndex(method, mainClassMethodHeader);
+                }
+            }
+        }
+    }
+
+    private void connectMultimethods(List<CachedClass> superClasses, CachedClass firstGroovyClass) {
+        superClasses = DefaultGroovyMethods.reverse(superClasses);
+        MetaMethodIndex.Header last = null;
+        for (final CachedClass c : superClasses) {
+            MetaMethodIndex.Header methodIndex = metaMethodIndex.getHeader(c.getTheClass());
+            // We don't copy DGM methods to superclasses' indexes
+            // The reason we can do that is particular set of DGM methods in use,
+            // if at some point we will define DGM method for some Groovy class or
+            // for a class derived from such, we will need to revise this condition.
+            // It saves us a lot of space and some noticeable time
+            if (last != null) metaMethodIndex.copyNonPrivateNonNewMetaMethods(last, methodIndex);
+            last = methodIndex;
+
+            if (c == firstGroovyClass)
+                break;
+        }
+    }
+
+    private CachedClass calcFirstGroovySuperClass(Collection superClasses) {
+        if (theCachedClass.isInterface)
+          return ReflectionCache.OBJECT_CLASS;
+
+        CachedClass firstGroovy = null;
+        Iterator iter = superClasses.iterator();
+        for (; iter.hasNext();) {
+            CachedClass c = (CachedClass) iter.next();
+            if (GroovyObject.class.isAssignableFrom(c.getTheClass())) {
+              firstGroovy = c;
+              break;
+            }
+        }
+
+        if (firstGroovy == null)
+          firstGroovy = theCachedClass;
+        else {
+            if (firstGroovy.getTheClass() == GroovyObjectSupport.class && iter.hasNext()) {
+                firstGroovy = (CachedClass) iter.next();
+                if (firstGroovy.getTheClass() == Closure.class && iter.hasNext()) {
+                    firstGroovy = (CachedClass) iter.next();
+                }
+            }
+        }
+
+        return GroovyObject.class.isAssignableFrom(firstGroovy.getTheClass()) ? firstGroovy.getCachedSuperClass() : firstGroovy;
+    }
+
+    /**
+     * Gets all instance methods available on this class for the given name
+     *
+     * @return all the normal instance methods available on this class for the
+     *         given name
+     */
+    private Object getMethods(Class sender, String name, boolean isCallToSuper) {
+        Object answer;
+
+        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
+        if (entry == null)
+            answer = FastArray.EMPTY_LIST;
+        else
+            if (isCallToSuper) {
+                answer = entry.methodsForSuper;
+            } else {
+                answer = entry.methods;
+            }
+
+        if (answer == null) answer = FastArray.EMPTY_LIST;
+
+        if (!isCallToSuper) {
+            List used = GroovyCategorySupport.getCategoryMethods(name);
+            if (used != null) {
+                FastArray arr;
+                if (answer instanceof MetaMethod) {
+                    arr = new FastArray();
+                    arr.add(answer);
+                }
+                else
+                    arr = ((FastArray) answer).copy();
+
+                for (Iterator iter = used.iterator(); iter.hasNext();) {
+                    MetaMethod element = (MetaMethod) iter.next();
+                    if (!element.getDeclaringClass().getTheClass().isAssignableFrom(sender))
+                      continue;
+                    filterMatchingMethodForCategory(arr, element);
+                }
+                answer = arr;
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Returns all the normal static methods on this class for the given name 
+     *
+     * @return all the normal static methods available on this class for the
+     *         given name
+     */
+    private Object getStaticMethods(Class sender, String name) {
+        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
+        if (entry == null)
+            return FastArray.EMPTY_LIST;
+        Object answer = entry.staticMethods;
+        if (answer == null)
+            return FastArray.EMPTY_LIST;
+        return answer;
+    }
+
+    /**
+     * Returns whether this MetaClassImpl has been modified. Since MetaClassImpl
+     * is not designed for modification this method always returns false
+     *
+     * @return false
+     */
+    public boolean isModified() {
+        return false;  // MetaClassImpl not designed for modification, just return false
+    }
+
+    /**
+     *Adds an instance method to this metaclass.
+     *
+     * @param method The method to be added
+     */
+    public void addNewInstanceMethod(Method method) {
+        final CachedMethod cachedMethod = CachedMethod.find(method);
+        NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
+        final CachedClass declaringClass = newMethod.getDeclaringClass();
+        addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
+    }
+
+    private void addNewInstanceMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
+        if (!newGroovyMethodsSet.contains(newMethod)) {
+            newGroovyMethodsSet.add(newMethod);
+            addMetaMethodToIndex(newMethod, header);
+        }
+    }
+
+    /**
+     *Adds a static method to this metaclass.
+     *
+     * @param method The method to be added
+     */
+    public void addNewStaticMethod(Method method) {
+        final CachedMethod cachedMethod = CachedMethod.find(method);
+        NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
+        final CachedClass declaringClass = newMethod.getDeclaringClass();
+        addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
+    }
+
+    private void addNewStaticMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
+        if (!newGroovyMethodsSet.contains(newMethod)) {
+            newGroovyMethodsSet.add(newMethod);
+            addMetaMethodToIndex(newMethod, header);
+        }
+    }
+
+    /**
+     * Invoke a method on the given object with the given arguments.
+     *
+     * @param object The object the method should be invoked on.
+     * @param methodName The name of the method to invoke.
+     * @param arguments The arguments to the invoked method as null, a Tuple, an array or a single argument of any type.
+     *
+     * @return The result of the method invocation.
+     */
+    public Object invokeMethod(Object object, String methodName, Object arguments) {
+        if (arguments == null) {
+            return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
+        }
+        if (arguments instanceof Tuple) {
+            Tuple tuple = (Tuple) arguments;
+            return invokeMethod(object, methodName, tuple.toArray());
+        }
+        if (arguments instanceof Object[]) {
+            return invokeMethod(object, methodName, (Object[]) arguments);
+        } else {
+            return invokeMethod(object, methodName, new Object[]{arguments});
+        }
+    }
+
+    /**
+     * Invoke a missing method on the given object with the given arguments.
+     *
+     * @param instance The object the method should be invoked on.
+     * @param methodName The name of the method to invoke.
+     * @param arguments The arguments to the invoked method.
+     *
+     * @return The result of the method invocation.
+     */
+    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
+        return invokeMissingMethod(instance, methodName, arguments, null, false);
+    }
+    
+    /**
+     * Invoke a missing property on the given object with the given arguments.
+     *
+     * @param instance The object the method should be invoked on.
+     * @param propertyName The name of the property to invoke.
+     * @param optionalValue The (optional) new value for the property
+     * @param isGetter Wether the method is a getter
+     *
+     * @return The result of the method invocation.
+     */
+    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
+        Class theClass = instance instanceof Class ? (Class)instance : instance.getClass();
+        CachedClass superClass = theCachedClass;
+        while(superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
+            final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
+            if(property != null) {
+                onSuperPropertyFoundInHierarchy(property);
+                if(!isGetter) {
+                    property.setProperty(instance, optionalValue);
+                    return null;
+                }
+                else {
+                    return property.getProperty(instance);
+                }
+            }
+            superClass = superClass.getCachedSuperClass();
+        }
+        // got here to property not found, look for getProperty or setProperty overrides
+        if(isGetter) {
+            final Class[] getPropertyArgs = {String.class};
+            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
+            if(method != null && method instanceof ClosureMetaMethod) {
+                onGetPropertyFoundInHierarchy(method);
+                return method.invoke(instance,new Object[]{propertyName});
+            }
+        }
+        else {
+            final Class[] setPropertyArgs = {String.class, Object.class};
+            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
+            if(method != null && method instanceof ClosureMetaMethod) {
+                onSetPropertyFoundInHierarchy(method);
+                return method.invoke(instance, new Object[]{propertyName, optionalValue});
+            }
+        }
+
+        try {
+            if (!(instance instanceof Class)) {
+                if (isGetter) {
+                    if (propertyMissingGet != null) {
+                        return propertyMissingGet.invoke(instance, new Object[]{propertyName});
+                    }
+                } else {
+                    if (propertyMissingSet != null) {
+                        return propertyMissingSet.invoke(instance, new Object[]{propertyName, optionalValue});
+                    }
+                }
+            }
+        } catch (InvokerInvocationException iie) {
+            boolean shouldHandle = isGetter && propertyMissingGet != null;
+            if (!shouldHandle) shouldHandle = !isGetter && propertyMissingSet != null;
+            if (shouldHandle &&  iie.getCause() instanceof MissingPropertyException) {
+                throw (MissingPropertyException) iie.getCause();
+            }
+            throw iie;
+        }
+
+        if (instance instanceof Class && theClass != Class.class) {
+           final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
+           if (metaProperty != null)
+             if (isGetter)
+               return metaProperty.getProperty(instance);
+             else {
+               metaProperty.setProperty(instance, optionalValue);
+               return null;
+             }
+        }
+        throw new MissingPropertyExceptionNoStack(propertyName, theClass);
+    }
+
+    private Object invokeMissingMethod(Object instance, String methodName, Object[] arguments, RuntimeException original, boolean isCallToSuper) {
+        if (!isCallToSuper) {
+            Class instanceKlazz = instance.getClass();
+            if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
+              instanceKlazz = theClass;
+
+            Class[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);
+
+            MetaMethod method = findMixinMethod(methodName, argClasses);
+            if(method != null) {
+                onMixinMethodFound(method);
+                return method.invoke(instance, arguments);
+            }
+
+            method = findMethodInClassHierarchy(instanceKlazz, methodName, argClasses, this);
+            if(method != null) {
+                onSuperMethodFoundInHierarchy(method);
+                return method.invoke(instance, arguments);
+            }
+
+            // still not method here, so see if there is an invokeMethod method up the hierarchy
+            final Class[] invokeMethodArgs = {String.class, Object[].class};
+            method = findMethodInClassHierarchy(instanceKlazz, INVOKE_METHOD_METHOD, invokeMethodArgs, this );
+            if(method != null && method instanceof ClosureMetaMethod) {
+                onInvokeMethodFoundInHierarchy(method);
+                return method.invoke(instance, invokeMethodArgs);
+            }
+        }
+
+        if (methodMissing != null) {
+            try {
+                return methodMissing.invoke(instance, new Object[]{methodName, arguments});
+            } catch (InvokerInvocationException iie) {
+                if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
+                    MissingMethodException mme =  (MissingMethodException) iie.getCause();
+                    throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
+                                                            mme.getArguments(),mme.isStatic(),mme);
+                }
+                throw iie;
+            } catch (MissingMethodException mme) {
+                if (methodMissing instanceof ClosureMetaMethod)
+                    throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
+                                                        mme.getArguments(),mme.isStatic(),mme);
+                else
+                    throw mme;
+            }
+        } else if (original != null) throw original;
+        else throw new MissingMethodExceptionNoStack(methodName, theClass, arguments, false);
+    }
+
+    protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
+    }
+
+    protected void onMixinMethodFound(MetaMethod method) {
+    }
+
+    protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
+    }
+
+    protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
+    }
+
+    protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
+    }
+
+    protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
+    }
+
+
+    /**
+     * Hook to deal with the case of MissingProperty for static properties. The method will look attempt to look up
+     * "propertyMissing" handlers and invoke them otherwise thrown a MissingPropertyException
+     *
+     * @param instance      The instance
+     * @param propertyName  The name of the property
+     * @param optionalValue The value in the case of a setter
+     * @param isGetter      True if its a getter
+     * @return The value in the case of a getter or a MissingPropertyException
+     */
+    protected Object invokeStaticMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
+        MetaClass mc = instance instanceof Class ? registry.getMetaClass((Class) instance) : this;
+        if (isGetter) {
+            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, GETTER_MISSING_ARGS);
+            if (propertyMissing != null) {
+                return propertyMissing.invoke(instance, new Object[]{propertyName});
+            }
+        } else {
+            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, SETTER_MISSING_ARGS);
+            if (propertyMissing != null) {
+                return propertyMissing.invoke(instance, new Object[]{propertyName, optionalValue});
+            }
+        }
+
+        if (instance instanceof Class) {
+            throw new MissingPropertyException(propertyName, (Class) instance);
+        }
+        throw new MissingPropertyException(propertyName, theClass);
+    }
+
+    
+    /**
+     * Invokes a method on the given receiver for the specified arguments. 
+     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
+     *
+     *
+     * @param object The object which the method was invoked on
+     * @param methodName The name of the method
+     * @param originalArguments The arguments to the method
+     *
+     * @return The return value of the method
+     * 
+     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
+     */
+    public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
+        return invokeMethod(theClass, object, methodName, originalArguments, false, false);
+    }
+
+
+    /**
+     * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
+     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
+     *
+     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
+     * to the super class if necessary
+     *
+     * @param sender The java.lang.Class instance that invoked the method
+     * @param object The object which the method was invoked on
+     * @param methodName The name of the method
+     * @param originalArguments The arguments to the method
+     * @param isCallToSuper Whether the method is a call to a super class method
+     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
+     *
+     * @return The return value of the method
+     *
+     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
+     */
+    public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
+        checkInitalised();
+        if (object == null) {
+            throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
+        }
+
+        final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS : originalArguments;
+//        final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+//
+//        unwrap(arguments);
+
+        MetaMethod method = null;
+        if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
+            method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
+        } 
+        if (method==null) {
+            method = getMethodWithCaching(sender, methodName, arguments, isCallToSuper);
+        }
+        MetaClassHelper.unwrap(arguments);
+
+        if (method == null)
+            method = tryListParamMetaMethod(sender, methodName, isCallToSuper, arguments);
+
+        final boolean isClosure = object instanceof Closure;
+        if (isClosure) {
+            final Closure closure = (Closure) object;
+
+            final Object owner = closure.getOwner();
+
+            if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
+                final Class objectClass = object.getClass();
+                if (objectClass == MethodClosure.class) {
+                    final MethodClosure mc = (MethodClosure) object;
+                    methodName = mc.getMethod();
+                    final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
+                    final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
+                    return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
+                } else if (objectClass == CurriedClosure.class) {
+                    final CurriedClosure cc = (CurriedClosure) object;
+                    // change the arguments for an uncurried call
+                    final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
+                    final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
+                    final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
+                    return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
+                }
+                if (method==null) invokeMissingMethod(object,methodName,arguments);
+            }
+
+            final Object delegate = closure.getDelegate();
+            final boolean isClosureNotOwner = owner != closure;
+            final int resolveStrategy = closure.getResolveStrategy();
+
+            final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+
+            switch (resolveStrategy) {
+                case Closure.TO_SELF:
+                    method = closure.getMetaClass().pickMethod(methodName, argClasses);
+                    if (method != null) return method.invoke(closure, arguments);
+                    break;
+                case Closure.DELEGATE_ONLY:
+                    if (method == null && delegate != closure && delegate != null) {
+                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
+                        method = delegateMetaClass.pickMethod(methodName, argClasses);
+                        if (method != null)
+                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
+                        else if (delegate != closure && (delegate instanceof GroovyObject)) {
+                            return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
+                        }
+                    }
+                    break;
+                case Closure.OWNER_ONLY:
+                    if (method == null && owner != closure) {
+                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
+                        return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
+                    }
+                    break;
+                case Closure.DELEGATE_FIRST:
+                    if (method == null && delegate != closure && delegate != null) {
+                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
+                        method = delegateMetaClass.pickMethod(methodName, argClasses);
+                        if (method != null)
+                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
+                    }
+                    if (method == null && owner != closure) {
+                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
+                        method = ownerMetaClass.pickMethod(methodName, argClasses);
+                        if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
+                    }
+                    if (method == null && resolveStrategy != Closure.TO_SELF) {
+                        // still no methods found, test if delegate or owner are GroovyObjects
+                        // and invoke the method on them if so.
+                        MissingMethodException last = null;
+                        if (delegate != closure && (delegate instanceof GroovyObject)) {
+                            try {
+                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
+                            } catch (MissingMethodException mme) {
+                                if (last == null) last = mme;
+                            }
+                        }
+                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
+                            try {
+                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
+                            } catch (MissingMethodException mme) {
+                                last = mme;
+                            }
+                        }
+                        if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
+                    }
+
+                    break;
+                default:
+                    if (method == null && owner != closure) {
+                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
+                        method = ownerMetaClass.pickMethod(methodName, argClasses);
+                        if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
+                    }
+                    if (method == null && delegate != closure && delegate != null) {
+                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
+                        method = delegateMetaClass.pickMethod(methodName, argClasses);
+                        if (method != null)
+                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
+                    }
+                    if (method == null && resolveStrategy != Closure.TO_SELF) {
+                        // still no methods found, test if delegate or owner are GroovyObjects
+                        // and invoke the method on them if so.
+                        MissingMethodException last = null;
+                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
+                            try {
+                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
+                            } catch (MissingMethodException mme) {
+                                if (methodName.equals(mme.getMethod())) {
+                                    if (last == null) last = mme;
+                                } else {
+                                    throw mme;
+                                }
+                            }
+                            catch (InvokerInvocationException iie) {
+                                if (iie.getCause() instanceof MissingMethodException) {
+                                    MissingMethodException mme = (MissingMethodException) iie.getCause();
+                                    if (methodName.equals(mme.getMethod())) {
+                                        if (last == null) last = mme;
+                                    } else {
+                                        throw iie;
+                                    }
+                                }
+                                else
+                                  throw iie;
+                            }
+                        }
+                        if (delegate != closure && (delegate instanceof GroovyObject)) {
+                            try {
+                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
+                            } catch (MissingMethodException mme) {
+                                last = mme;
+                            }
+                            catch (InvokerInvocationException iie) {
+                                if (iie.getCause() instanceof MissingMethodException) {
+                                    last = (MissingMethodException) iie.getCause();
+                                }
+                                else
+                                  throw iie;
+                            }
+                        }
+                        if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
+                    }
+            }
+        }
+
+        if (method != null) {
+            return method.doMethodInvoke(object, arguments);
+        } else {
+            return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
+        }
+    }
+
+    private MetaMethod tryListParamMetaMethod(Class sender, String methodName, boolean isCallToSuper, Object[] arguments) {
+        MetaMethod method = null;
+        if (arguments.length == 1 && arguments[0] instanceof List) {
+            Object[] newArguments = ((List) arguments[0]).toArray();
+            method = createTransformMetaMethod(getMethodWithCaching(sender, methodName, newArguments, isCallToSuper));
+        }
+        return method;
+    }
+
+    protected MetaMethod createTransformMetaMethod(MetaMethod method) {
+        if (method == null) {
+            return null;
+        }
+
+        return new TransformMetaMethod(method) {
+            public Object invoke(Object object, Object[] arguments) {
+                Object firstArgument = arguments[0];
+                List list = (List) firstArgument;
+                arguments = list.toArray();
+                return super.invoke(object, arguments);
+            }
+        };
+    }
+
+    private Object invokePropertyOrMissing(Object object, String methodName, Object[] originalArguments, boolean fromInsideClass, boolean isCallToSuper) {
+        // if no method was found, try to find a closure defined as a field of the class and run it
+        Object value = null;
+        final MetaProperty metaProperty = this.getMetaProperty(methodName, false);
+        if (metaProperty != null)
+          value = metaProperty.getProperty(object);
+        else {
+            if (object instanceof Map)
+              value = ((Map)object).get(methodName);
+        }
+
+        if (value instanceof Closure) {  // This test ensures that value != this If you ever change this ensure that value != this
+            Closure closure = (Closure) value;
+            MetaClass delegateMetaClass = closure.getMetaClass();
+            return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
+        }
+
+        if (object instanceof Script) {
+            Object bindingVar = ((Script) object).getBinding().getVariables().get(methodName);
+            if (bindingVar != null) {
+                MetaClass bindingVarMC = ((MetaClassRegistryImpl) registry).getMetaClass(bindingVar);
+                return bindingVarMC.invokeMethod(bindingVar, CLOSURE_CALL_METHOD, originalArguments);
+            }
+        }
+        return invokeMissingMethod(object, methodName, originalArguments, null, isCallToSuper);
+    }
+
+    private MetaClass lookupObjectMetaClass(Object object) {
+        if (object instanceof GroovyObject) {
+            GroovyObject go = (GroovyObject) object;
+            return go.getMetaClass();
+        }
+        Class ownerClass = object.getClass();
+        if (ownerClass == Class.class) ownerClass = (Class) object;
+        MetaClass metaClass = registry.getMetaClass(ownerClass);
+        return metaClass;
+    }
+
+    private static Object invokeMethodOnGroovyObject(String methodName, Object[] originalArguments, Object owner) {
+        GroovyObject go = (GroovyObject) owner;
+        return go.invokeMethod(methodName, originalArguments);
+    }
+
+    public MetaMethod getMethodWithCaching(Class sender, String methodName, Object[] arguments, boolean isCallToSuper) {
+        // let's try use the cache to find the method
+        if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
+            return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
+        } else {
+            final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, methodName);
+            if (e == null)
+              return null;
+
+            return isCallToSuper ? getSuperMethodWithCaching(arguments, e) : getNormalMethodWithCaching(arguments, e);
+        }
+    }
+
+    private static boolean sameClasses(Class[] params, Class[] arguments) {
+        // we do here a null check because the params field might not have been set yet
+        if (params == null) return false;
+
+        if (params.length != arguments.length)
+            return false;
+
+        for (int i = params.length - 1; i >= 0; i--) {
+            Object arg = arguments[i];
+            if (arg != null) {
+                if (params[i] != arguments[i]) return false;
+            } else return false;
+        }
+
+        return true;
+    }
+
+    // This method should be called by CallSite only
+    private MetaMethod getMethodWithCachingInternal (Class sender, CallSite site, Class [] params) {
+        if (GroovyCategorySupport.hasCategoryInCurrentThread())
+            return getMethodWithoutCaching(sender, site.getName (), params, false);
+
+        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, site.getName());
+        if (e == null) {
+            return null;
+        }
+
+        MetaMethodIndex.CacheEntry cacheEntry;
+        final Object methods = e.methods;
+        if (methods == null)
+          return null;
+
+        cacheEntry = e.cachedMethod;
+        if (cacheEntry != null && (sameClasses(cacheEntry.params, params))) {
+             return cacheEntry.method;
+        }
+
+        cacheEntry = new MetaMethodIndex.CacheEntry (params, (MetaMethod) chooseMethod(e.name, methods, params));
+        e.cachedMethod = cacheEntry;
+        return cacheEntry.method;
+    }
+
+    private MetaMethod getSuperMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
+        MetaMethodIndex.CacheEntry cacheEntry;
+        if (e.methodsForSuper == null)
+          return null;
+
+        cacheEntry = e.cachedMethodForSuper;
+
+        if (cacheEntry != null &&
+            MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methodsForSuper instanceof MetaMethod))
+        {
+            MetaMethod method = cacheEntry.method;
+            if (method!=null) return method;
+        }
+
+        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
+        MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methodsForSuper, classes);
+        cacheEntry = new MetaMethodIndex.CacheEntry (classes, method.isAbstract()?null:method);
+
+        e.cachedMethodForSuper = cacheEntry;
+
+        return cacheEntry.method;
+    }
+
+    private MetaMethod getNormalMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
+        MetaMethodIndex.CacheEntry cacheEntry;
+        final Object methods = e.methods;
+        if (methods == null)
+          return null;
+
+        cacheEntry = e.cachedMethod;
+
+        if (cacheEntry != null &&
+            MetaClassHelper.sameClasses(cacheEntry.params, arguments, methods instanceof MetaMethod))
+        {
+            MetaMethod method = cacheEntry.method;
+            if (method!=null) return method;
+        }
+
+        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
+        cacheEntry = new MetaMethodIndex.CacheEntry (classes, (MetaMethod) chooseMethod(e.name, methods, classes));
+
+        e.cachedMethod = cacheEntry;
+
+        return cacheEntry.method;
+    }
+
+    public Constructor retrieveConstructor(Class[] arguments) {
+        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
+        if (constructor != null) {
+            return constructor.cachedConstructor;
+        }
+        constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
+        if (constructor != null) {
+            return constructor.cachedConstructor;
+        }
+        return null;
+    }
+
+    public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
+        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(theClass, methodName);
+        MetaMethodIndex.CacheEntry cacheEntry;
+        if (e != null) {
+            cacheEntry = e.cachedStaticMethod;
+
+            if (cacheEntry != null &&
+                MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.staticMethods instanceof MetaMethod))
+            {
+                 return cacheEntry.method;
+            }
+
+            final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
+            cacheEntry = new MetaMethodIndex.CacheEntry (classes, pickStaticMethod(methodName, classes));
+
+            e.cachedStaticMethod = cacheEntry;
+
+            return cacheEntry.method;
+        }
+        else
+          return pickStaticMethod(methodName, MetaClassHelper.convertToTypeArray(arguments));
+    }
+
+    public MetaMethod getMethodWithoutCaching(Class sender, String methodName, Class[] arguments, boolean isCallToSuper) {
+        MetaMethod method = null;
+        Object methods = getMethods(sender, methodName, isCallToSuper);
+        if (methods != null) {
+            method = (MetaMethod) chooseMethod(methodName, methods, arguments);
+        }
+        return method;
+    }
+
+    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
+        checkInitalised();
+
+        final Class sender = object instanceof Class ? (Class) object : object.getClass();
+        if (sender != theClass) {
+            MetaClass mc = registry.getMetaClass(sender);
+            return mc.invokeStaticMethod(sender, methodName, arguments);
+        }
+        if (sender == Class.class) {
+            return invokeMethod(object, methodName, arguments);
+        }
+
+        if (arguments == null) arguments = EMPTY_ARGUMENTS;
+//        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+
+        MetaMethod method = retrieveStaticMethod(methodName, arguments);
+        // let's try use the cache to find the method
+
+        if (method != null) {
+            MetaClassHelper.unwrap(arguments);
+            return method.doMethodInvoke(object, arguments);
+        }
+        Object prop = null;
+        try {
+            prop = getProperty(theClass, theClass, methodName, false, false);
+        } catch (MissingPropertyException mpe) {
+            // ignore
+        }
+
+        if (prop instanceof Closure) {
+            return invokeStaticClosureProperty(arguments, prop);
+        }
+
+        Object[] originalArguments = arguments.clone();
+        MetaClassHelper.unwrap(arguments);
+
+        Class superClass = sender.getSuperclass();
+        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+        while (superClass != Object.class && superClass != null) {
+            MetaClass mc = registry.getMetaClass(superClass);
+            method = mc.getStaticMetaMethod(methodName, argClasses);
+            if (method != null) return method.doMethodInvoke(object, arguments);
+
+            try {
+                prop = mc.getProperty(superClass, superClass, methodName, false, false);
+            } catch (MissingPropertyException mpe) {
+                // ignore
+            }
+
+            if (prop instanceof Closure) {
+                return invokeStaticClosureProperty(originalArguments, prop);
+            }
+
+            superClass = superClass.getSuperclass();
+        }
+
+        if (prop != null) {
+            MetaClass propMC = registry.getMetaClass(prop.getClass());
+            return propMC.invokeMethod(prop, CLOSURE_CALL_METHOD, arguments);
+        }
+
+        return invokeStaticMissingMethod(sender, methodName, arguments);
+    }
+
+    private static Object invokeStaticClosureProperty(Object[] originalArguments, Object prop) {
+        Closure closure = (Closure) prop;
+        MetaClass delegateMetaClass = closure.getMetaClass();
+        return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, false);
+    }
+
+    private Object invokeStaticMissingMethod(Class sender, String methodName, Object[] arguments) {
+        MetaMethod metaMethod = getStaticMetaMethod(STATIC_METHOD_MISSING, METHOD_MISSING_ARGS);
+        if (metaMethod != null) {
+            return metaMethod.invoke(sender, new Object[]{methodName, arguments});
+        }
+        throw new MissingMethodException(methodName, sender, arguments, true);
+    }
+
+    private MetaMethod pickStaticMethod(String methodName, Class[] arguments) {
+        MetaMethod method = null;
+        MethodSelectionException mse = null;
+        Object methods = getStaticMethods(theClass, methodName);
+
+        if (!(methods instanceof FastArray) || !((FastArray)methods).isEmpty()) {
+            try {
+                method = (MetaMethod) chooseMethod(methodName, methods, arguments);
+            } catch(MethodSelectionException msex) {
+                mse = msex;
+            }
+        }
+        if (method == null && theClass != Class.class) {
+            MetaClass classMetaClass = registry.getMetaClass(Class.class);
+            method = classMetaClass.pickMethod(methodName, arguments);
+        }
+        if (method == null) {
+            method = (MetaMethod) chooseMethod(methodName, methods, MetaClassHelper.convertToTypeArray(arguments));
+        }
+
+        if (method == null && mse != null) {
+            throw mse;
+        } else {
+            return method;
+        }
+    }
+
+    public Object invokeConstructor(Object[] arguments) {
+        return invokeConstructor(theClass, arguments);
+    }
+
+    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
+        if (numberOfConstructors==-1) {
+            return selectConstructorAndTransformArguments1(arguments);
+        } else {
+            // falling back to pre 2.1.9 selection algorithm
+            // in practice this branch will only be reached if the class calling this code is a Groovy class
+            // compiled with an earlier version of the Groovy compiler
+            return selectConstructorAndTransformArguments0(numberOfConstructors, arguments);
+        }
+
+
+    }
+
+    private int selectConstructorAndTransformArguments0(final int numberOfConstructors, Object[] arguments) {
+        //TODO: that is just a quick prototype, not the real thing!
+        if (numberOfConstructors != constructors.size()) {
+            throw new IncompatibleClassChangeError("the number of constructors during runtime and compile time for " +
+                    this.theClass.getName() + " do not match. Expected " + numberOfConstructors + " but got " + constructors.size());
+        }
+
+        CachedConstructor constructor = createCachedConstructor(arguments);
+        List l = new ArrayList(constructors.toList());
+        Comparator comp = new Comparator() {
+            public int compare(Object arg0, Object arg1) {
+                CachedConstructor c0 = (CachedConstructor) arg0;
+                CachedConstructor c1 = (CachedConstructor) arg1;
+                String descriptor0 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c0.getNativeParameterTypes());
+                String descriptor1 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c1.getNativeParameterTypes());
+                return descriptor0.compareTo(descriptor1);
+            }
+        };
+        Collections.sort(l, comp);
+        int found = -1;
+        for (int i = 0; i < l.size(); i++) {
+            if (l.get(i) != constructor) continue;
+            found = i;
+            break;
+        }
+        // NOTE: must be changed to "1 |" if constructor was vargs
+        return 0 | (found << 8);
+    }
+
+    private CachedConstructor createCachedConstructor(Object[] arguments) {
+        if (arguments == null) arguments = EMPTY_ARGUMENTS;
+        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+        MetaClassHelper.unwrap(arguments);
+        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
+        if (constructor == null) {
+            constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
+        }
+        if (constructor == null) {
+            throw new GroovyRuntimeException(
+                    "Could not find matching constructor for: "
+                            + theClass.getName()
+                            + "(" + InvokerHelper.toTypeString(arguments) + ")");
+        }
+        return constructor;
+    }
+
+    /**
+     * Constructor selection algorithm for Groovy 2.1.9+.
+     * This selection algorithm was introduced as a workaround for GROOVY-6080. Instead of generating an index between
+     * 0 and N where N is the number of super constructors at the time the class is compiled, this algorithm uses
+     * a hash of the constructor descriptor instead.
+     *
+     * This has the advantage of letting the super class add new constructors while being binary compatible. But there
+     * are still problems with this approach:
+     * <ul>
+     *     <li>There's a risk of hash collision, even if it's very low (two constructors of the same class must have the same hash)</li>
+     *     <li>If the super class adds a new constructor which takes as an argument a superclass of an existing constructor parameter and
+     *     that this new constructor is selected at runtime, it would not find it.</li>
+     * </ul>
+     *
+     * Hopefully in the last case, the error message is much nicer now since it explains that it's a binary incompatible change.
+     *
+     * @param arguments the actual constructor call arguments
+     * @return a hash used to identify the constructor to be called
+     * @since 2.1.9
+     */
+    private int selectConstructorAndTransformArguments1(Object[] arguments) {
+        CachedConstructor constructor = createCachedConstructor(arguments);
+        final String methodDescriptor = BytecodeHelper.getMethodDescriptor(Void.TYPE, constructor.getNativeParameterTypes());
+        // keeping 3 bits for additional information such as vargs
+        return BytecodeHelper.hashCode(methodDescriptor);
+    }
+
+
+    /**
+     * checks if the initialisation of the class id complete.
+     * This method should be called as a form of assert, it is no
+     * way to test if there is still initialisation work to be done.
+     * Such logic must be implemented in a different way.
+     *
+     * @throws IllegalStateException if the initialisation is incomplete yet
+     */
+    protected void checkInitalised() {
+        if (!isInitialized())
+            throw new IllegalStateException(
+                    "initialize must be called for meta " +
+                            "class of " + theClass +
+                            "(" + this.getClass() + ") " +
+                            "to complete initialisation process " +
+                            "before any invocation or field/property " +
+                            "access can be done");
+    }
+    
+    /**
+     * This is a helper class introduced in Groovy 2.1.0, which is used only by
+     * indy. This class is for internal use only.
+     * @since Groovy 2.1.0
+     */
+    public static final class MetaConstructor extends MetaMethod {
+        private final CachedConstructor cc;
+        private final boolean beanConstructor;
+        private MetaConstructor(CachedConstructor cc, boolean bean) {
+            super(cc.getNativeParameterTypes());
+            this.setParametersTypes(cc.getParameterTypes());
+            this.cc = cc;
+            this.beanConstructor = bean;
+        }
+        @Override
+        public int getModifiers() { return cc.getModifiers(); }
+        @Override
+        public String getName() { return "<init>"; }
+        @Override
+        public Class getReturnType() { return cc.getCachedClass().getTheClass(); }
+        @Override
+        public CachedClass getDeclaringClass() { return cc.getCachedClass(); }
+        @Override
+        public Object invoke(Object object, Object[] arguments) {
+            return cc.doConstructorInvoke(arguments);
+        }
+        public CachedConstructor getCachedConstrcutor() { return cc; }
+        public boolean isBeanConstructor() { return beanConstructor; }
+    }
+    
+    /**
+     * This is a helper method added in Groovy 2.1.0, which is used only by indy.
+     * This method is for internal use only.
+     * @since Groovy 2.1.0
+     */
+    public MetaMethod retrieveConstructor(Object[] arguments) {
+        checkInitalised();
+        if (arguments == null) arguments = EMPTY_ARGUMENTS;
+        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+        MetaClassHelper.unwrap(arguments);
+        Object res = chooseMethod("<init>", constructors, argClasses);
+        if (res instanceof MetaMethod) return (MetaMethod) res;
+        CachedConstructor constructor = (CachedConstructor) res;
+        if (constructor != null) return new MetaConstructor(constructor, false);
+        if (arguments.length == 1 && arguments[0] instanceof Map) {
+            res = chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
+        } else if (
+                arguments.length == 2 && arguments[1] instanceof Map && 
+                theClass.getEnclosingClass()!=null && 
+                theClass.getEnclosingClass().isAssignableFrom(argClasses[0])) 
+        {
+            res = chooseMethod("<init>", constructors, new Class[]{argClasses[0]});
+        }
+        if (res instanceof MetaMethod) return (MetaMethod) res;
+        constructor = (CachedConstructor) res;
+        if (constructor != null) return new MetaConstructor(constructor, true);
+
+        return null;
+    }
+    
+    private Object invokeConstructor(Class at, Object[] arguments) {
+        checkInitalised();
+        if (arguments == null) arguments = EMPTY_ARGUMENTS;
+        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
+        MetaClassHelper.unwrap(arguments);
+        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
+        if (constructor != null) {
+            return constructor.doConstructorInvoke(arguments);
+        }
+
+        if (arguments.length == 1) {
+            Object firstArgument = arguments[0];
+            if (firstArgument instanceof Map) {
+                constructor = (CachedConstructor) chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
+                if (constructor != null) {
+                    Object bean = constructor.doConstructorInvoke(MetaClassHelper.EMPTY_ARRAY);
+                    setProperties(bean, ((Map) firstArgument));
+                    return bean;
+                }
+            }
+        }
+        throw new GroovyRuntimeException(
+                "Could not find matching constructor for: "
+                        + theClass.getName()
+                        + "(" + InvokerHelper.toTypeString(arguments) + ")");
+    }
+
+    /**
+     * Sets a number of bean properties from the given Map where the keys are
+     * the String names of properties and the values are the values of the
+     * properties to set
+     */
+    public void setProperties(Object bean, Map map) {
+        checkInitalised();
+        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            String key = entry.getKey().toString();
+
+            Object value = entry.getValue();
+            setProperty(bean, key, value);
+        }
+    }
+
+    /**
+     * @return the given property's value on the object
+     */
+    public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {
+
+        //----------------------------------------------------------------------
+        // handling of static
+        //----------------------------------------------------------------------
+        boolean isStatic = theClass != Class.class && object instanceof Class;
+        if (isStatic && object != theClass) {
+            MetaClass mc = registry.getMetaClass((Class) object);
+            return mc.getProperty(sender, object, name, useSuper, false);
+        }
+
+        checkInitalised();
+
+        //----------------------------------------------------------------------
+        // turn getProperty on a Map to get on the Map itself
+        //----------------------------------------------------------------------
+        if (!isStatic && this.isMap) {
+            return ((Map) object).get(name);
+        }
+
+        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, sender, name, useSuper, isStatic);
+        MetaMethod method = methodAndProperty.getFirst();
+
+        //----------------------------------------------------------------------
+        // getter
+        //----------------------------------------------------------------------
+        MetaProperty mp = methodAndProperty.getSecond();
+
+        //----------------------------------------------------------------------
+        // field
+        //----------------------------------------------------------------------
+        if (method == null && mp != null) {
+            try {
+                return mp.getProperty(object);
+            } catch (IllegalArgumentException e) {
+                // can't access the field directly but there may be a getter
+                mp = null;
+            } catch (CacheAccessControlException e) {
+                // can't access the field directly but there may be a getter
+                mp = null;
+            }
+        }
+
+        //----------------------------------------------------------------------
+        // generic get method
+        //----------------------------------------------------------------------
+        // check for a generic get method provided through a category
+        Object[] arguments = EMPTY_ARGUMENTS;
+        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
+            method = getCategoryMethodGetter(sender, "get", true);
+            if (method != null) arguments = new Object[]{name};
+        }
+
+        // the generic method is valid, if available (!=null), if static or
+        // if it is not static and we do no static access
+        if (method == null && genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
+            arguments = new Object[]{name};
+            method = genericGetMethod;
+        }
+
+        //----------------------------------------------------------------------
+        // special cases
+        //----------------------------------------------------------------------
+        if (method == null) {
+            /** todo these special cases should be special MetaClasses maybe */
+            if (theClass != Class.class && object instanceof Class) {
+                MetaClass mc = registry.getMetaClass(Class.class);
+                return mc.getProperty(Class.class, object, name, useSuper, false);
+            } else if (object instanceof Collection) {
+                return DefaultGroovyMethods.getAt((Collection) object, name);
+            } else if (object instanceof Object[]) {
+                return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), name);
+            } else {
+                MetaMethod addListenerMethod = listeners.get(name);
+                if (addListenerMethod != null) {
+                    //TODO: one day we could try return the previously registered Closure listener for easy removal
+                    return null;
+                }
+            }
+        } else {
+
+            //----------------------------------------------------------------------
+            // executing the getter method
+            //----------------------------------------------------------------------
+            return method.doMethodInvoke(object, arguments);
+        }
+
+        //----------------------------------------------------------------------
+        // error due to missing method/field
+        //----------------------------------------------------------------------
+        if (isStatic || object instanceof Class)
+            return invokeStaticMissingProperty(object, name, null, true);
+        else
+            return invokeMissingProperty(object, name, null, true);
+    }
+
+    public MetaProperty getEffectiveGetMetaProperty(final Class sender, final Object object, String name, final boolean useSuper) {
+
+        //----------------------------------------------------------------------
+        // handling of static
+        //----------------------------------------------------------------------
+        boolean isStatic = theClass != Class.class && object instanceof Class;
+        if (isStatic && object != theClass) {
+            return new MetaProperty(name, Object.class) {
+                final MetaClass mc = registry.getMetaClass((Class) object);
+
+                public Object getProperty(Object object) {
+                    return mc.getProperty(sender, object, name, useSuper,false);
+                }
+
+                public void setProperty(Object object, Object newValue) {
+                    throw new UnsupportedOperationException();
+                }
+            };
+        }
+
+        checkInitalised();
+
+        //----------------------------------------------------------------------
+        // turn getProperty on a Map to get on the Map itself
+        //----------------------------------------------------------------------
+        if (!isStatic && this.isMap) {
+            return new MetaProperty(name, Object.class) {
+                public Object getProperty(Object object) {
+                    return ((Map) object).get(name);
+                }
+
+                public void setProperty(Object object, Object newValue) {
+                    throw new UnsupportedOperationException();
+                }
+            };
+        }
+
+        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, theClass, name, useSuper, isStatic);
+        MetaMethod method = methodAndProperty.getFirst();
+
+        //----------------------------------------------------------------------
+        // getter
+        //----------------------------------------------------------------------
+        MetaProperty mp = methodAndProperty.getSecond();
+
+        //----------------------------------------------------------------------
+        // field
+        //----------------------------------------------------------------------
+        if (method != null)
+            return new GetBeanMethodMetaProperty(name, method);
+
+        if (mp != null) {
+            return mp;
+//            try {
+//                return mp.getProperty(object);
+//            } catch (IllegalArgumentException e) {
+//                // can't access the field directly but there may be a getter
+//                mp = null;
+//            }
+        }
+
+        //----------------------------------------------------------------------
+        // generic get method
+        //----------------------------------------------------------------------
+        // check for a generic get method provided through a category
+        if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
+            method = getCategoryMethodGetter(sender, "get", true);
+            if (method != null)
+                return new GetMethodMetaProperty(name, method);
+        }
+
+        // the generic method is valid, if available (!=null), if static or
+        // if it is not static and we do no static access
+        if (genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
+            method = genericGetMethod;
+            return new GetMethodMetaProperty(name, method);
+        }
+
+        //----------------------------------------------------------------------
+        // special cases
+        //----------------------------------------------------------------------
+        /** todo these special cases should be special MetaClasses maybe */
+        if (theClass != Class.class && object instanceof Class) {
+            return new MetaProperty(name, Object.class) {
+            

<TRUNCATED>

[30/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Generated.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Generated.java b/src/main/groovy/groovy/transform/Generated.java
new file mode 100644
index 0000000..98eaf5b
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Generated.java
@@ -0,0 +1,32 @@
+/*
+ *  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 groovy.transform;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Generated annotation is used to mark members that have been generated.
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Generated {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Immutable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Immutable.java b/src/main/groovy/groovy/transform/Immutable.java
new file mode 100644
index 0000000..5f6bf90
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Immutable.java
@@ -0,0 +1,249 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of immutable classes.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.Immutable} class Customer {
+ *     String first, last
+ *     int age
+ *     Date since
+ *     Collection favItems
+ * }
+ * def d = new Date()
+ * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:d, favItems:['Books', 'Games'])
+ * def c2 = new Customer('Tom', 'Jones', 21, d, ['Books', 'Games'])
+ * assert c1 == c2
+ * </pre>
+ * The {@code @Immutable} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary getters, constructors,
+ * equals, hashCode and other helper methods that are typically written
+ * when creating immutable classes with the defined properties.
+ * <p>
+ * A class created in this way has the following characteristics:
+ * <ul>
+ * <li>The class is automatically made final.
+ * <li>Properties must be of an immutable type or a type with a strategy for handling non-immutable
+ * characteristics. Specifically, the type must be one of the primitive or wrapper types, Strings, enums,
+ * other {@code @Immutable} classes or known immutables (e.g. java.awt.Color, java.net.URI, java.util.UUID).
+ * Also handled are Cloneable classes, collections, maps and arrays, other "effectively immutable"
+ * classes with special handling (e.g. java.util.Date), and usages of java.util.Optional where the
+ * contained type is immutable (e.g. Optional&lt;String&gt;).
+ * <li>Properties automatically have private, final backing fields with getters.
+ * Attempts to update the property will result in a {@code ReadOnlyPropertyException}.
+ * <li>A map-based constructor is provided which allows you to set properties by name.
+ * <li>A tuple-style constructor is provided which allows you to set properties in the same order as they are defined.
+ * <li>Default {@code equals}, {@code hashCode} and {@code toString} methods are provided based on the property values.
+ * Though not normally required, you may write your own implementations of these methods. For {@code equals} and {@code hashCode},
+ * if you do write your own method, it is up to you to obey the general contract for {@code equals} methods and supply
+ * a corresponding matching {@code hashCode} method.
+ * If you do provide one of these methods explicitly, the default implementation will be made available in a private
+ * "underscore" variant which you can call. E.g., you could provide a (not very elegant) multi-line formatted
+ * {@code toString} method for {@code Customer} above as follows:
+ * <pre>
+ *     String toString() {
+ *        _toString().replaceAll(/\(/, '(\n\t').replaceAll(/\)/, '\n)').replaceAll(/, /, '\n\t')
+ *    }
+ * </pre>
+ * If an "underscore" version of the respective method already exists, then no default implementation is provided.
+ * <li>{@code Date}s, {@code Cloneable}s and arrays are defensively copied on the way in (constructor) and out (getters).
+ * Arrays and {@code Cloneable} objects use the {@code clone} method. For your own classes,
+ * it is up to you to define this method and use deep cloning if appropriate.
+ * <li>{@code Collection}s and {@code Map}s are wrapped by immutable wrapper classes (but not deeply cloned!).
+ * Attempts to update them will result in an {@code UnsupportedOperationException}.
+ * <li>Fields that are enums or other {@code @Immutable} classes are allowed but for an
+ * otherwise possible mutable property type, an error is thrown.
+ * <li>You don't have to follow Groovy's normal property conventions, e.g. you can create an explicit private field and
+ * then you can write explicit get and set methods. Such an approach, isn't currently prohibited (to give you some
+ * wiggle room to get around these conventions) but any fields created in this way are deemed not to be part of the
+ * significant state of the object and aren't factored into the {@code equals} or {@code hashCode} methods.
+ * Similarly, you may use static properties (though usually this is discouraged) and these too will be ignored
+ * as far as significant state is concerned. If you do break standard conventions, you do so at your own risk and
+ * your objects may no longer be immutable. It is up to you to ensure that your objects remain immutable at least
+ * to the extent expected in other parts of your program!
+ * </ul>
+ * Immutable classes are particularly useful for functional and concurrent styles of programming
+ * and for use as key values within maps. If you want similar functionality to what this annotation
+ * provides but don't need immutability then consider using {@code @Canonical}.
+ * <p>
+ * Customising behaviour:
+ * <p>
+ * You can customise the toString() method provided for you by {@code @Immutable}
+ * by also adding the {@code @ToString} annotation to your class definition.
+ * <p>
+ * Limitations:
+ * <ul>
+ * <li>
+ * As outlined above, Arrays and {@code Cloneable} objects use the {@code clone} method. For your own classes,
+ * it is up to you to define this method and use deep cloning if appropriate.
+ * </li>
+ * <li>
+ * As outlined above, {@code Collection}s and {@code Map}s are wrapped by immutable wrapper classes (but not deeply cloned!).
+ * </li>
+ * <li>
+ * Currently {@code BigInteger} and {@code BigDecimal} are deemed immutable but see:
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348370
+ * </li>
+ * <li>
+ * {@code java.awt.Color} is treated as "effectively immutable" but is not final so while not normally used with child
+ * classes, it isn't strictly immutable. Use at your own risk.
+ * </li>
+ * <li>
+ * {@code java.util.Date} is treated as "effectively immutable" but is not final so it isn't strictly immutable.
+ * Use at your own risk.
+ * </li>
+ * <li>
+ * Groovy's normal map-style naming conventions will not be available if the first property
+ * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property.
+ * </li>
+ * </ul>
+ * <p>More examples:</p>
+ --------------------------------------------------------------------------------
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ *
+ * &#64;Canonical
+ * class Building {
+ *     String name
+ *     int floors
+ *     boolean officeSpace
+ * }
+ *
+ * // Constructors are added.
+ * def officeSpace = new Building('Initech office', 1, true)
+ *
+ * // toString() added.
+ * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
+ *
+ * // Default values are used if constructor
+ * // arguments are not assigned.
+ * def theOffice = new Building('Wernham Hogg Paper Company')
+ * assert theOffice.floors == 0
+ * theOffice.officeSpace = true
+ *
+ * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
+ *
+ * // equals() method is added.
+ * assert anotherOfficeSpace == officeSpace
+ *
+ * // equals() and hashCode() are added, so duplicate is not in Set.
+ * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
+ * assert offices.size() == 2 
+ * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
+ *
+ * &#64;Canonical
+ * &#64;ToString(excludes='age')  // Customize one of the transformations.
+ * class Person {
+ *     String name
+ *     int age
+ * }
+ *
+ * def mrhaki = new Person('mrhaki', 37)
+ * assert mrhaki.toString() == 'Person(mrhaki)'
+ * </pre>
+ *
+ * @author Paul King
+ * @author Andre Steingress
+ * @see groovy.transform.ToString
+ * @see groovy.transform.Canonical
+ * @since 1.7
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ImmutableASTTransformation")
+public @interface Immutable {
+    /**
+     * Allows you to provide {@code @Immutable} with a list of classes which
+     * are deemed immutable. By supplying a class in this list, you are vouching
+     * for its immutability and {@code @Immutable} will do no further checks.
+     * Example:
+     * <pre>
+     * import groovy.transform.*
+     * {@code @Immutable}(knownImmutableClasses = [Address])
+     * class Person {
+     *     String first, last
+     *     Address address
+     * }
+     *
+     * {@code @TupleConstructor}
+     * class Address {
+     *     final String street
+     * }
+     * </pre>
+     *
+     * @since 1.8.7
+     */
+    Class[] knownImmutableClasses() default {};
+
+    /**
+     * Allows you to provide {@code @Immutable} with a list of property names which
+     * are deemed immutable. By supplying a property's name in this list, you are vouching
+     * for its immutability and {@code @Immutable} will do no further checks.
+     * Example:
+     * <pre>
+     * {@code @groovy.transform.Immutable}(knownImmutables = ['address'])
+     * class Person {
+     *     String first, last
+     *     Address address
+     * }
+     * ...
+     * </pre>
+     *
+     * @since 2.1.0
+     */
+    String[] knownImmutables() default {};
+
+    /**
+     * If {@code true}, this adds a method {@code copyWith} which takes a Map of
+     * new property values and returns a new instance of the Immutable class with
+     * these values set.
+     * Example:
+     * <pre class="groovyTestCase">
+     * {@code @groovy.transform.Immutable}(copyWith = true)
+     * class Person {
+     *     String first, last
+     * }
+     *
+     * def tim   = new Person( 'tim', 'yates' )
+     * def alice = tim.copyWith( first:'alice' )
+     *
+     * assert tim.first   == 'tim'
+     * assert alice.first == 'alice'
+     * </pre>
+     * Unknown keys in the map are ignored, and if the values would not change
+     * the object, then the original object is returned.
+     *
+     * If a method called {@code copyWith} that takes a single parameter already
+     * exists in the class, then this setting is ignored, and no method is generated.
+     *
+     * @since 2.2.0
+     */
+    boolean copyWith() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/IndexedProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/IndexedProperty.java b/src/main/groovy/groovy/transform/IndexedProperty.java
new file mode 100644
index 0000000..b6d47dc
--- /dev/null
+++ b/src/main/groovy/groovy/transform/IndexedProperty.java
@@ -0,0 +1,107 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Field annotation used with properties to provide an indexed getter and setter for the property.
+ * Groovy provides nice GPath syntax support for accessing indexed properties but Java tools
+ * or frameworks may expect the JavaBean style setters and getters.
+ * <p>
+ * <em>Example usage:</em> suppose you have a class with the following properties:
+ * <pre>
+ * {@code @IndexedProperty} FieldType[] someField
+ * {@code @IndexedProperty} List<FieldType> otherField
+ * {@code @IndexedProperty} List furtherField
+ * </pre>
+ * will add the following methods to the class containing the properties:
+ * <pre>
+ * FieldType getSomeField(int index) {
+ *     someField[index]
+ * }
+ * FieldType getOtherField(int index) {
+ *     otherField[index]
+ * }
+ * Object getFurtherField(int index) {
+ *     furtherField[index]
+ * }
+ * void setSomeField(int index, FieldType val) {
+ *     someField[index] = val
+ * }
+ * void setOtherField(int index, FieldType val) {
+ *     otherField[index] = val
+ * }
+ * void setFurtherField(int index, Object val) {
+ *     furtherField[index] = val
+ * }
+ * </pre>
+ * Normal Groovy visibility rules for properties apply
+ * (i.e. no <code>public</code>, <code>private</code> or <code>package</code>
+ * visibility can be specified) or you will receive a compile-time error message.
+ * The normal Groovy property getters and setters will also be created.
+ * <p>
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.IndexedProperty
+ *
+ * class Group {
+ *     String name
+ *     List members = []
+ * }
+ *
+ * class IndexedGroup {
+ *     String name
+ *     &#64;IndexedProperty List members = []
+ * }
+ *
+ * def group = new Group(name: 'Groovy')
+ * group.members[0] = 'mrhaki'
+ * group.members[1] = 'Hubert'
+ * assert 2 == group.members.size()
+ * assert ['mrhaki', 'Hubert'] == group.members
+ *
+ * try {
+ *     group.setMembers(0, 'hubert') // Not index property
+ * } catch (MissingMethodException e) {
+ *     assert e
+ * }
+ *
+ * def indexedGroup = new IndexedGroup(name: 'Grails')
+ * indexedGroup.members[0] = 'mrhaki'
+ * indexedGroup.setMembers 1, 'Hubert'
+ * assert 2 == indexedGroup.members.size()
+ * assert 'mrhaki' == indexedGroup.getMembers(0)
+ * assert 'Hubert' == indexedGroup.members[1]
+ * </pre>
+ *
+ * @author Paul King
+ * @since 1.7.3
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.IndexedPropertyASTTransformation")
+public @interface IndexedProperty {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/InheritConstructors.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/InheritConstructors.java b/src/main/groovy/groovy/transform/InheritConstructors.java
new file mode 100644
index 0000000..ba7758a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/InheritConstructors.java
@@ -0,0 +1,169 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation to make constructors from a super class available in a sub class.
+ * Should be used with care with other annotations which create constructors - see "Known
+ * Limitations" for more details.
+ * <p>
+ * {@code @InheritConstructors} saves you typing some boilerplate code.
+ * <p>
+ * <em>Example usage:</em>
+ * <pre class="groovyTestCase">
+ * class Person {
+ *     String first, last
+ *     Person(String first, String last) {
+ *         this.first = first
+ *         this.last = last.toUpperCase()
+ *     }
+ * }
+ *
+ * {@code @groovy.transform.InheritConstructors}
+ * class PersonAge extends Person {
+ *     int age
+ * }
+ *
+ * def js = new PersonAge('John', 'Smith')
+ * js.age = 25
+ * 
+ * assert "$js.last, $js.first is $js.age years old" == 'SMITH, John is 25 years old'
+ * </pre>
+ * for this case, the <code>PersonAge</code> class will be
+ * equivalent to the following code:
+ * <pre>
+ * class PersonAge extends Person {
+ *     PersonAge(String first, String last) {
+ *         super(first, last)
+ *     }
+ *     int age
+ * }
+ * </pre>
+ * You may add additional constructors in addition to inherited ones.
+ * If the argument types of a supplied constructor exactly match those
+ * of a parent constructor, then that constructor won't be inherited.
+ * <p>
+ * <em>Style note:</em> Don't go overboard using this annotation.
+ * Typical Groovy style is to use named-arg constructors when possible.
+ * This is easy to do for Groovy objects or any objects following JavaBean
+ * conventions. In other cases, inheriting the constructors may be useful.
+ * However, sub-classes often introduce new properties and these are often best
+ * set in a constructor; especially if that matches the style adopted
+ * in parent classes. So, even for the example above, it may have been
+ * better style to define an explicit constructor for <code>PersonAge</code>
+ * that also set the <code>age</code> property. Sometimes, consistent
+ * style is much more important than saving a few keystrokes.
+ * <p>
+ * As another example, this:
+ * <pre>
+ * {@code @InheritConstructors} class CustomException extends RuntimeException { }
+ * </pre>
+ * is equivalent to this:
+ * <pre>
+ * class CustomException extends RuntimeException {
+ *     CustomException() {
+ *         super()
+ *     }
+ *     CustomException(String message) {
+ *         super(message)
+ *     }
+ *     CustomException(String message, Throwable cause) {
+ *         super(message, cause)
+ *     }
+ *     CustomException(Throwable cause) {
+ *         super(cause)
+ *     }
+ * }
+ * </pre>
+ * Known Limitations:
+ * <ul>
+ * <li>This AST transform creates (potentially) numerous constructors.
+ * You should take care to avoid constructors with duplicate signatures if you are defining your own constructors or
+ * combining with other AST transforms which create constructors (e.g. {@code @TupleConstructor});
+ * the order in which the particular transforms are processed becomes important in that case.</li>
+ * <li>If you create Groovy constructors with optional
+ * arguments this leads to multiple constructors created in the byte code.
+ * The expansion to multiple constructors occurs in a later phase to
+ * this AST transformation. This means that you can't override (i.e. not
+ * inherit) the constructors with signatures that Groovy adds later.
+ * If you get it wrong you will get a compile-time error about the duplication.</li>
+ * </ul>
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.InheritConstructors
+ *
+ * &#64;InheritConstructors
+ * class MyException extends Exception {
+ * }
+ *
+ * def e = new MyException()
+ * def e1 = new MyException('message')   // Other constructors are available.
+ * assert 'message' == e1.message
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.InheritConstructors
+
+ * class Person {
+ *     String name
+ *
+ *     Person(String name) {
+ *         this.name = name
+ *     }
+ * }
+ *
+ * &#64;InheritConstructors
+ * class Child extends Person {}
+ *
+ * def child = new Child('Liam')
+ * assert 'Liam' == child.name
+ * </pre>
+ *
+ * @author Paul King
+ * @since 1.7.3
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.InheritConstructorsASTTransformation")
+public @interface InheritConstructors {
+    /**
+     * Whether to carry over annotations on the copied constructors.
+     * Currently Closure annotation members are not supported.
+     *
+     * @return true if copied constructor should keep constructor annotations
+     */
+    boolean constructorAnnotations() default false;
+
+    /**
+     * Whether to carry over parameter annotations on the copied constructors.
+     * Currently Closure annotation members are not supported.
+     *
+     * @return true if copied constructor should keep parameter annotations
+     */
+    boolean parameterAnnotations() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/MapConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/MapConstructor.java b/src/main/groovy/groovy/transform/MapConstructor.java
new file mode 100644
index 0000000..5608001
--- /dev/null
+++ b/src/main/groovy/groovy/transform/MapConstructor.java
@@ -0,0 +1,128 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of map constructors in classes.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ *
+ * {@code @TupleConstructor}
+ * class Person {
+ *     String first, last
+ * }
+ *
+ * {@code @CompileStatic} // optional
+ * {@code @ToString(includeSuperProperties=true)}
+ * {@code @MapConstructor}(pre={ super(args?.first, args?.last); args = args ?: [:] }, post = { first = first?.toUpperCase() })
+ * class Author extends Person {
+ *     String bookName
+ * }
+ *
+ * assert new Author(first: 'Dierk', last: 'Koenig', bookName: 'ReGinA').toString() == 'Author(ReGinA, DIERK, Koenig)'
+ * assert new Author().toString() == 'Author(null, null, null)'
+ * </pre>
+ * The {@code @MapConstructor} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary constructor method to your class.
+ * <p>
+ * A map constructor is created which sets properties, and optionally fields and
+ * super properties if the property/field name is a key within the map.
+ * <p>
+ * For the above example, the generated constructor will be something like:
+ * <pre>
+ * public Author(java.util.Map args) {
+ *     super(args?.first, args?.last)
+ *     args = args ? args : [:]
+ *     if (args.containsKey('bookName')) {
+ *         this.bookName = args['bookName']
+ *     }
+ *     first = first?.toUpperCase()
+ * }
+ * </pre>
+ *
+ * @since 2.5.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.MapConstructorASTTransformation")
+public @interface MapConstructor {
+    /**
+     * List of field and/or property names to exclude from the constructor.
+     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the constructor.
+     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields and/or properties
+     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Include fields in the constructor.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Include properties in the constructor.
+     */
+    boolean includeProperties() default true;
+
+    /**
+     * Include properties from super classes in the constructor.
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * By default, properties are set directly using their respective field.
+     * By setting {@code useSetters=true} then a writable property will be set using its setter.
+     * If turning on this flag we recommend that setters that might be called are
+     * made null-safe wrt the parameter.
+     */
+    boolean useSetters() default false;
+
+    /**
+     * A Closure containing statements which will be prepended to the generated constructor. The first statement within the Closure may be "super(someArgs)" in which case the no-arg super constructor won't be called.
+     */
+    Class pre() default Undefined.CLASS.class;
+
+    /**
+     * A Closure containing statements which will be appended to the end of the generated constructor. Useful for validation steps or tweaking the populated fields/properties.
+     */
+    Class post() default Undefined.CLASS.class;
+
+    /**
+     * Whether to include all fields and/or properties within the constructor, including those with names that are considered internal.
+     */
+    boolean allNames() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Memoized.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Memoized.java b/src/main/groovy/groovy/transform/Memoized.java
new file mode 100644
index 0000000..efecb17
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Memoized.java
@@ -0,0 +1,145 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Method annotation that creates a cache for the results of the execution of the annotated method. Whenever the method
+ * is called, the mapping between the parameters and the return value is preserved in a cache making subsequent calls with
+ * the same arguments fast.
+ * 
+ * <p>
+ * Example usage:
+ * 
+ * <pre>
+ * class MemoizedExample {
+ * 
+ *     {@code @Memoized}
+ *     int sum(int n1, int n2) {
+ *         println "$n1 + $n2 = ${n1 + n2}" 
+ *         n1 + n2
+ *     }
+ * }
+ * </pre>
+ * 
+ * which becomes (approximately):
+ * 
+ * <pre>
+ * class MemoizedExample {
+ * 
+ *     private final Closure memoizedSum = { int n1, int n2 ->
+ *         private$method$memoizedSum(n1,n2)
+ *     }.memoize()
+ * 
+ *     int sum(int n1, int n2) {
+ *         memoizedSum(n1, n2)
+ *     }
+ *
+ *     private private$method$memoizedSum(int n1, int n2) {
+ *         println "$n1 + $n2 = ${n1 + n2}"
+ *         n1 + n2
+ *     }
+ * }
+ * </pre>
+ * 
+ * <p>
+ * Upon execution of this code:
+ * 
+ * <pre>
+ * def instance = new MemoizedExample()
+ * println instance.sum(1, 2)
+ * println instance.sum(1, 2)
+ * println instance.sum(2, 3)
+ * println instance.sum(2, 3)
+ * </pre>
+ * 
+ * The following will be output:
+ * 
+ * <pre>
+ * 1 + 2 = 3
+ * 3
+ * 3
+ * 2 + 3 = 5
+ * 5
+ * 5
+ * </pre>
+ * 
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.*
+ *
+ * // Script variable which is changed when increment()
+ * // method is invoked. 
+ * // If cached method call is invoked then the value
+ * // of this variable will not change.
+ * &#64;Field boolean incrementChange = false
+ *
+ * &#64;Memoized 
+ * int increment(int value) {
+ *     incrementChange = true
+ *     value + 1 
+ * }
+ *
+ * // Invoke increment with argument 10.
+ * increment(10)
+ *
+ * // increment is invoked so incrementChange is true.
+ * assert incrementChange
+ *
+ * // Set incrementChange back to false.
+ * incrementChange = false
+ *
+ * // Invoke increment with argument 10.
+ * increment(10)
+ *
+ * // Now the cached method is used and
+ * // incrementChange is not changed.
+ * assert !incrementChange
+ *
+ * // Invoke increment with other argument value.
+ * increment(11)
+ *
+ * // increment is invoked so incrementChange is true.
+ * assert incrementChange
+ * </pre>
+ * 
+ * @author Andrey Bloschetsov
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ ElementType.METHOD })
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.MemoizedASTTransformation")
+public @interface Memoized {
+    
+    /**
+     * Number of cached return values to protect from garbage collection.
+     */
+    int protectedCacheSize() default 0;
+    
+    /**
+     * The maximum size the cache can grow to.
+     */
+    int maxCacheSize() default 0;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/PackageScope.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/PackageScope.java b/src/main/groovy/groovy/transform/PackageScope.java
new file mode 100644
index 0000000..caa77a7
--- /dev/null
+++ b/src/main/groovy/groovy/transform/PackageScope.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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used for turning off Groovy's auto visibility conventions.
+ * By default, Groovy automatically turns package protected fields into properties
+ * and makes package protected methods, constructors and classes public.
+ * This annotation allows this feature to be turned
+ * off and revert back to Java behavior if needed.
+ *
+ * Place it on classes, fields, constructors or methods of interest as follows:
+ * <pre>
+ * {@code @}PackageScope class Bar {      // package protected
+ *     {@code @}PackageScope int field    // package protected; not a property
+ *     {@code @}PackageScope method(){}   // package protected
+ * }
+ * </pre>
+ * or for greater control, at the class level with one or more
+ * <code>PackageScopeTarget</code> values:
+ * <pre>
+ * import static groovy.transform.PackageScopeTarget.*
+ * {@code @}PackageScope([CLASS, FIELDS])
+ * class Foo {              // class will have package protected scope
+ *     int field1, field2   // both package protected
+ *     def method(){}       // public
+ * }
+ * {@code @}PackageScope(METHODS)
+ * class Bar {         // public
+ *     int field       // treated as a property
+ *     def method1(){} // package protected
+ *     def method2(){} // package protected
+ * }
+ * </pre>
+ *
+ * This transformation is not frequently needed but can be useful in certain testing scenarios
+ * or when using a third-party library or framework which relies upon package scoping.
+ *
+ * @author Paul King
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.PackageScopeASTTransformation")
+public @interface PackageScope {
+    groovy.transform.PackageScopeTarget[] value() default {PackageScopeTarget.CLASS};
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/PackageScopeTarget.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/PackageScopeTarget.java b/src/main/groovy/groovy/transform/PackageScopeTarget.java
new file mode 100644
index 0000000..726d47a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/PackageScopeTarget.java
@@ -0,0 +1,47 @@
+/*
+ *  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 groovy.transform;
+
+/**
+ * Intended target when {@code @}PackageScope is placed at the class level.
+ *
+ * @author Paul King
+ * @since 1.8.0
+ */
+public enum PackageScopeTarget {
+    /**
+     * Make the Class have package protected visibility.
+     */
+    CLASS,
+
+    /**
+     * Make the Class methods have package protected visibility.
+     */
+    METHODS,
+
+    /**
+     * Make the Class fields have package protected visibility.
+     */
+    FIELDS,
+
+    /**
+     * Make the Class constructors have package protected visibility.
+     */
+    CONSTRUCTORS
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/SelfType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/SelfType.java b/src/main/groovy/groovy/transform/SelfType.java
new file mode 100644
index 0000000..5b2ccb3
--- /dev/null
+++ b/src/main/groovy/groovy/transform/SelfType.java
@@ -0,0 +1,82 @@
+/*
+ *  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 groovy.transform;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be added on a trait to declare the list of types that a class
+ * implementing that trait is supposed to extend. This is useful when you want to be
+ * able to call methods from the class implementing the trait without having to declare
+ * all of them as members of the trait.
+ *
+ * Self types are particularly useful in combination with {@link groovy.transform.CompileStatic},
+ * if you know that a trait can only be applied to a specific type but that the trait cannot extend
+ * that type itself. For example, imagine the following code:
+ * <pre><code>
+ *     class Component { void methodInComponent() }
+ *     trait ComponentDecorator {
+ *         void logAndCall() {
+ *             println "Calling method in component"
+ *             methodInComponent()
+ *         }
+ *         // other useful methods
+ *     }
+ *     class DecoratedComponent extends Component implements ComponentDecorator {}
+ * </code></pre>
+ *
+ * This will work because the trait uses the dynamic backend, so there is no check at
+ * compile time that the <i>methodInComponent</i> call in <i>logAndCall</i> is actually
+ * defined. If you annotate the trait with {@link groovy.transform.CompileStatic}, compilation
+ * will fail because the trait does not define the method. To declare that the trait can be
+ * applied on something that will extend <i>Component</i>, you need to add the <i>SelfType</i>
+ * annotation like this:
+ * <pre><code>
+ *     class Component { void methodInComponent() }
+ *
+ *     {@literal @}CompileStatic
+ *     {@literal @}SelfType(Component)
+ *     trait ComponentDecorator {
+ *         void logAndCall() {
+ *             println "Calling method in component"
+ *             methodInComponent()
+ *         }
+ *         // other useful methods
+ *     }
+ *     class DecoratedComponent extends Component implements ComponentDecorator {}
+ * </code></pre>
+ *
+ * This pattern can therefore be used to avoid explicit casts everywhere you need to call a method
+ * that you know is defined in the class that will implement the trait but normally don't have access
+ * to, which is often the case where a trait needs to be applied on a class provided by a third-party
+ * library.
+ *
+ * @author Cédric Champeau
+ * @since 2.4.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface SelfType {
+    Class[] value();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Sortable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Sortable.java b/src/main/groovy/groovy/transform/Sortable.java
new file mode 100644
index 0000000..b235bfa
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Sortable.java
@@ -0,0 +1,179 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A class annotation used to make a class Comparable by multiple Comparators.
+ *
+ * As an example, given this class:
+ * <pre>
+ * {@code @Sortable} class Person {
+ *     String first
+ *     String last
+ *     Integer born
+ * }
+ * </pre>
+ * The generated Groovy class will:
+ * <ul>
+ *     <li>implement the {@code Comparable} interface</li>
+ *     <li>have a {@code compareTo} method based on the {@code first},
+ *     {@code last} and {@code born} properties (priority ordering will be according
+ *     to the ordering of property definition, highest first, unless 'includes' is used; in which case,
+ *     priority will be according to the order given in the includes list)</li>
+ *     <li>have three {@code Comparator} methods named {@code comparatorByFirst},
+ *     {@code comparatorByLast} and {@code comparatorByBorn}</li>
+ *     <li>sort by natural order by default, reversed natural order can be specified</li>
+ * </ul>
+ * The properties within the class must themselves be {@code Comparable} or {@code @Sortable}.
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.Sortable
+ * import groovy.transform.ToString
+ *
+ * &#64;Sortable
+ * &#64;ToString
+ * class Course {
+ *     // Order of properties determines priority when sorting
+ *     String title
+ *     Date beginDate
+ *     Integer maxAttendees  // int doesn't implement Comparable, so use Integer
+ * }
+ *
+ *
+ * final Course groovy = new Course(
+ *         title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
+ * final Course groovy2 = new Course(
+ *         title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
+ * final Course grails = new Course(
+ *         title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)
+ *
+ *
+ * final List&lt;Course&gt; courses = [groovy, groovy2, grails]
+ * assert courses.last().title == 'Grails'
+ *
+ * // Use toSorted() method to sort
+ * final List&lt;Course&gt; sorted = courses.toSorted()
+ *
+ * assert sorted.first().title == 'Grails'
+ * assert sorted.last().title == 'Groovy'
+ * assert sorted.maxAttendees == [20, 50, 40]
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Order of fields for includes determines priority when sorting
+ * import groovy.transform.Sortable
+ * import groovy.transform.ToString
+ *
+ * &#64;Sortable(includes = ['title', 'maxAttendees'])
+ * // Or &#64;Sortable(excludes = ['beginDate'])
+ * &#64;ToString
+ * class Course {
+ *     String title
+ *     Date beginDate
+ *     Integer maxAttendees
+ * }
+ *
+ * final Course groovy = new Course(
+ *         title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
+ * final Course groovy2 = new Course(
+ *         title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
+ * final Course grails = new Course(
+ *         title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)
+ *
+ *
+ * final List&lt;Course&gt; courses = [groovy, groovy2, grails]
+ *
+ * // Use toSorted() method to sort
+ * final List&lt;Course&gt; sorted = courses.toSorted()
+ *
+ * assert sorted.first().title == 'Grails'
+ * assert sorted.last().title == 'Groovy'
+ * assert sorted.maxAttendees == [20, 40, 50]
+ *
+ * //--------------------------------------------------------------------------
+ * // Static methods to create comparators.
+ * final Comparator byMaxAttendees = Course.comparatorByMaxAttendees()
+ * final List&lt;Course&gt; sortedByMaxAttendees = courses.sort(false, byMaxAttendees)
+ *
+ * assert sortedByMaxAttendees.maxAttendees == [20, 40, 50]
+ * // beginDate is not used for sorting
+ * assert sortedByMaxAttendees[2].beginDate &lt; sortedByMaxAttendees[1].beginDate
+ *
+ * assert Course.declaredMethods.name.findAll { it.startsWith('comparatorBy') }.toSorted() == ['comparatorByMaxAttendees', 'comparatorByTitle']
+ *
+ * //--------------------------------------------------------------------------
+ * // Sorting by max attendees using reversed order
+ * import groovy.transform.Sortable
+ * import groovy.transform.ToString
+ *
+ * &#64;Sortable(includes = ['points'], reversed = true)
+ * &#64;ToString
+ * class LeaderBoardEntry {
+ *     String team
+ *     int points
+ * }
+ *
+ *
+ * final LeaderBoardEntry teamA = new LeaderBoardEntry(team: "Team A", points: 30)
+ * final LeaderBoardEntry teamB = new LeaderBoardEntry(team: "Team B", points: 80)
+ * final LeaderBoardEntry teamC = new LeaderBoardEntry(team: "Team C", points: 50)
+ *
+ * final List&lt;LeaderBoardEntry&gt; leaderBoard = [teamA, teamB, teamC].toSorted()
+ *
+ * assert leaderBoard.first().team == 'Team B'
+ * assert leaderBoard.last().team == 'Team A'
+ * assert leaderBoard.points == [80, 50, 30]
+ *
+ * </pre>
+ *
+ * @author Andres Almiray
+ * @author Paul King
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.SortableASTTransformation")
+public @interface Sortable {
+    /**
+     * Property names to include in the comparison algorithm.
+     * Must not be used if 'excludes' is used.
+     * The default value is a special marker value indicating that no includes are defined; all properties
+     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Property names to exclude in the comparison algorithm.
+     * Must not be used if 'includes' is used.
+     */
+    String[] excludes() default {};
+
+    /**
+     * Set to true so that comparator uses reversed natural order.
+     * @since 2.5.0
+     */
+    boolean reversed() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/SourceURI.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/SourceURI.java b/src/main/groovy/groovy/transform/SourceURI.java
new file mode 100644
index 0000000..4104369
--- /dev/null
+++ b/src/main/groovy/groovy/transform/SourceURI.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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Variable annotation used for getting the URI of the current script.
+ * <p>
+ * The type of the variable annotated with {@code @SourceURI} must be assignment compatible with {@link java.net.URI}.
+ * It will be used to hold a URI object that references the source for the current script.
+ * </p><p>By default the URI
+ * will be made absolute (which is to say it will have an authority) in the case where a relative path was used
+ * for the source of the script.  If you want to leave relative URIs as relative, then set <code>allowRelative</code>
+ * to <code>true</code>.
+ * </p>
+ *
+ * Example usage:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.SourceURI} def sourceURI
+ *
+ * assert sourceURI instanceof java.net.URI
+ * </pre>
+ *
+ * @author Jim White
+ * @since 2.3.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.LOCAL_VARIABLE, ElementType.FIELD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.SourceURIASTTransformation")
+public @interface SourceURI {
+    boolean allowRelative() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Synchronized.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Synchronized.java b/src/main/groovy/groovy/transform/Synchronized.java
new file mode 100644
index 0000000..8282270
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Synchronized.java
@@ -0,0 +1,170 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Method annotation to make a method call synchronized for concurrency handling
+ * with some useful baked-in conventions.
+ * <p>
+ * {@code @Synchronized} is a safer variant of the <code>synchronized</code> method modifier.
+ * The annotation can only be used on static and instance methods. It operates similarly to
+ * the <code>synchronized</code> keyword, but it locks on different objects. When used with
+ * an instance method, the <code>synchronized</code> keyword locks on <code>this</code>, but the annotation
+ * locks on a (by default automatically generated) field named <code>$lock</code>.
+ * If the field does not exist, it is created for you. If you annotate a static method,
+ * the annotation locks on a static field named <code>$LOCK</code> instead.
+ * <p>
+ * If you want, you can create these locks yourself.
+ * The <code>$lock</code> and <code>$LOCK</code> fields will not be generated if you create
+ * them yourself. You can also choose to lock on another field, by specifying its name as
+ * parameter to the {@code @Synchronized} annotation. In this usage variant, the lock field
+ * will not be created automatically, and you must explicitly create it yourself.
+ * <p>
+ * <em>Rationale:</em> Locking on <code>this</code> or your own class object can have unfortunate side-effects,
+ * as other code not under your control can lock on these objects as well, which can
+ * cause race conditions and other nasty threading-related bugs.
+ * <p>
+ * <em>Example usage:</em>
+ * <pre>
+ * class SynchronizedExample {
+ *   private final myLock = new Object()
+ *
+ *   {@code @}Synchronized
+ *   static void greet() {
+ *     println "world"
+ *   }
+ *
+ *   {@code @}Synchronized
+ *   int answerToEverything() {
+ *     return 42
+ *   }
+ *
+ *   {@code @}Synchronized("myLock")
+ *   void foo() {
+ *     println "bar"
+ *   }
+ * }
+ * </pre>
+ * which becomes:
+ * <pre>
+ * class SynchronizedExample {
+ *   private static final $LOCK = new Object[0]
+ *   private final $lock = new Object[0]
+ *   private final myLock = new Object()
+ *
+ *   static void greet() {
+ *     synchronized($LOCK) {
+ *       println "world"
+ *     }
+ *   }
+ *
+ *   int answerToEverything() {
+ *     synchronized($lock) {
+ *       return 42
+ *     }
+ *   }
+ *
+ *   void foo() {
+ *     synchronized(myLock) {
+ *       println "bar"
+ *     }
+ *   }
+ * }
+ * </pre>
+ *
+ * <em>Credits:</em> this annotation is inspired by the Project Lombok annotation of the
+ * same name. The functionality has been kept similar to ease the learning
+ * curve when swapping between these two tools.
+ * <p>
+ * <em>Details:</em> If <code>$lock</code> and/or <code>$LOCK</code> are auto-generated, the fields are initialized
+ * with an empty <code>Object[]</code> array, and not just a new <code>Object()</code> as many snippets using
+ * this pattern tend to use. This is because a new <code>Object</code> is NOT serializable, but
+ * a 0-size array is. Therefore, using {@code @Synchronized} will not prevent your
+ * object from being serialized.
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.Synchronized
+ *
+ * class Util {
+ *     private counter = 0
+ *
+ *     private def list = ['Groovy']
+ *
+ *     private Object listLock = new Object[0]
+ *
+ *     &#64;Synchronized
+ *     void workOnCounter() {
+ *         assert 0 == counter
+ *         counter++
+ *         assert 1 == counter
+ *         counter --
+ *         assert 0 == counter
+ *     }
+ *
+ *     &#64;Synchronized('listLock')
+ *     void workOnList() {
+ *         assert 'Groovy' == list[0]
+ *         list &lt;&lt; 'Grails'
+ *         assert 2 == list.size()
+ *         list = list - 'Grails'
+ *         assert 'Groovy' == list[0]
+ *     }
+ * }
+ *
+ * def util = new Util()
+ * def tc1 = Thread.start {
+ *     100.times {
+ *         util.workOnCounter()
+ *         sleep 20 
+ *         util.workOnList()
+ *         sleep 10
+ *     }
+ * }
+ * def tc2 = Thread.start {
+ *     100.times {
+ *         util.workOnCounter()
+ *         sleep 10 
+ *         util.workOnList()
+ *         sleep 15
+ *     }
+ * }
+ * tc1.join()
+ * tc2.join()
+ * </pre>
+ *
+ * @author Paul King
+ * @since 1.7.3
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.SynchronizedASTTransformation")
+public @interface Synchronized {
+    /**
+     * @return if a user specified lock object with the given name should be used
+     */
+    String value () default "";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/TailRecursive.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TailRecursive.groovy b/src/main/groovy/groovy/transform/TailRecursive.groovy
new file mode 100644
index 0000000..afbee50
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TailRecursive.groovy
@@ -0,0 +1,87 @@
+/*
+ *  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 groovy.transform
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.ElementType
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+import java.lang.annotation.Target
+
+/**
+ * Method annotation used to transform methods with tail recursive calls into iterative methods automagically
+ * since the JVM cannot do this itself. This works for both static and non-static methods.
+ * <p/>
+ * It allows you to write a method like this:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.TailRecursive
+ * class Target {
+ *      {@code @TailRecursive}
+ *      long sumUp(long number, long sum = 0) {
+ *          if (number == 0)
+ *              return sum;
+ *          sumUp(number - 1, sum + number)
+ *      }
+ * }
+ * def target = new Target()
+ * assert target.sumUp(100) == 5050
+ * assert target.sumUp(1000000) == 500000500000 //will blow the stack on most machines when used without {@code @TailRecursive}
+ * </pre>
+ *
+ * {@code @TailRecursive} is supposed to work in combination with {@code @CompileStatic}
+ *
+ * Known shortcomings:
+ * <ul>
+ * <li>Only non-void methods are currently being handled. Void methods will fail compilation.
+ * <li>Only direct recursion (calling the exact same method again) is supported.
+ * <li>Mixing of tail calls and non-tail calls is not possible. The compiler will complain if some recursive calls cannot be handled.
+ * <li>Checking if a recursive call is really tail-recursive is not very strict. You might run into cases where non-tail calls will be considered tail calls.
+ * <li>In the presence of method overloading and method overriding you might run into situations where a call is considered recursive although it really is not.
+ * <li>Catching {@code Throwable} around a recursive might lead to problems
+ * <li>Non trivial continuation passing style examples do not work.
+ * <li>Probably many unrecognized edge cases.
+ * </ul>
+ * 
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * import groovy.transform.TailRecursive
+ *
+ * &#64;TailRecursive
+ * long sizeOfList(list, counter = 0) {
+ *     if (list.size() == 0) {
+ *         counter
+ *     } else {
+ *        sizeOfList(list.tail(), counter + 1) 
+ *     }
+ * }
+ *
+ * // Without &#64;TailRecursive a StackOverFlowError
+ * // is thrown.
+ * assert sizeOfList(1..10000) == 10000
+ * </pre>
+ *
+ * @author Johannes Link
+ * @since 2.3
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target([ElementType.METHOD])
+@GroovyASTTransformationClass(["org.codehaus.groovy.transform.tailrec.TailRecursiveASTTransformation"])
+public @interface TailRecursive {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ThreadInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ThreadInterrupt.groovy b/src/main/groovy/groovy/transform/ThreadInterrupt.groovy
new file mode 100644
index 0000000..817507a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ThreadInterrupt.groovy
@@ -0,0 +1,148 @@
+/*
+ *  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 groovy.transform
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.Documented
+import java.lang.annotation.ElementType
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+import java.lang.annotation.Target
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding Thread.currentThread().isInterrupted()
+ * checks into loops (for, while) and at the start of closures and methods.
+ * <p>
+ * This is especially useful when executing foreign scripts that you do not have control over. Inject this
+ * transformation into a script that you need to interrupt.
+ * <p>
+ * Annotating anything in a script will cause for loops, while loops, methods, and closures to make an
+ * isInterruptedCheck and throw a InterruptedException if the check yields true. The annotation by default
+ * will apply to any classes defined in the script as well. Annotated a class will cause (by default) all classes
+ * in the entire file ('Compilation Unit') to be enhanced. You can fine tune what is enhanced using the annotation
+ * parameters. 
+ * <p>
+ * The following is sample usage of the annotation:
+ *
+ * <pre>
+ * <code>@groovy.transform.ThreadInterrupt</code>
+ * def scriptMethod() {
+ *   4.times {
+ *     println 'executing script method...'
+ *   }
+ * }
+ *
+ * class MyClass {
+ *   def myMethod() {
+ *     for (i in (1..10)) {
+ *       println 'executing method...'
+ *     }
+ *   }
+ * }
+ *
+ * scriptMethod()
+ * new MyClass().myMethod()
+ * </pre>
+ *
+ * Which results in the following code being generated. Notice the checks and exceptions:
+ *
+ * <pre>
+ * public class script1290627909406 extends groovy.lang.Script {
+ *
+ *     public java.lang.Object scriptMethod() {
+ *         if (java.lang.Thread.currentThread().isInterrupted()) {
+ *             throw new java.lang.InterruptedException('Execution Interrupted')
+ *         }
+ *         4.times({
+ *             if (java.lang.Thread.currentThread().isInterrupted()) {
+ *                 throw new java.lang.InterruptedException('Execution Interrupted')
+ *             }
+ *             this.println('executing script method...')
+ *         })
+ *     }
+ * }
+ * public class MyClass extends java.lang.Object {
+ *
+ *   public java.lang.Object myMethod() {
+ *     if (java.lang.Thread.currentThread().isInterrupted()) {
+ *       throw new java.lang.InterruptedException('Execution Interrupted')
+ *     }
+ *     for (java.lang.Object i : (1..10)) {
+ *       if (java.lang.Thread.currentThread().isInterrupted()) {
+ *         throw new java.lang.InterruptedException('Execution Interrupted')
+ *       }
+ *       this.println('executing method...')
+ *     }
+ *   }
+ * }
+ *
+ * this.scriptMethod()
+ * new MyClass().myMethod()
+ * </pre>
+ * Additional usage examples can be found in the unit test for this class.
+ *
+ * @see TimedInterrupt
+ * @see ConditionalInterrupt
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ * @author Paul King
+ * @since 1.8.0
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target([ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
+@GroovyASTTransformationClass(["org.codehaus.groovy.transform.ThreadInterruptibleASTTransformation"])
+@interface ThreadInterrupt {
+  /**
+   * Set this to false if you have multiple classes within one source file and only
+   * want isInterrupted checks on some of the classes. Place annotations on the classes
+   * you want enhanced. Set to true (the default) for blanket coverage of isInterrupted
+   * checks on all methods, loops and closures within all classes/script code.
+   *
+   * For even finer-grained control see {@code applyToAllMembers}.
+   *
+   * @see #applyToAllMembers()
+   */
+  boolean applyToAllClasses() default true
+
+  /**
+   * Set this to false if you have multiple methods/closures within a class or script and only
+   * want isInterrupted checks on some of them. Place annotations on the methods/closures that
+   * you want enhanced. When false, {@code applyToAllClasses} is automatically set to false.
+   *
+   * Set to true (the default) for blanket coverage of isInterrupted checks on all methods, loops
+   * and closures within the class/script.
+   *
+   * @since 2.2.0
+   * @see #applyToAllClasses()
+   */
+  boolean applyToAllMembers() default true
+
+  /**
+   * By default an isInterrupted check is added to the start of all user-defined methods. To turn this off simply
+   * set this parameter to false.
+   */
+  boolean checkOnMethodStart() default true
+
+  /**
+   * Sets the type of exception which is thrown.
+   */
+  Class thrown() default InterruptedException
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/TimedInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TimedInterrupt.groovy b/src/main/groovy/groovy/transform/TimedInterrupt.groovy
new file mode 100644
index 0000000..0a0c193
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TimedInterrupt.groovy
@@ -0,0 +1,142 @@
+/*
+ *  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 groovy.transform
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.Documented
+import java.lang.annotation.ElementType
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+import java.lang.annotation.Target
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+/**
+ * Allows safe timed executions of scripts by adding elapsed time checks into loops (for, while)
+ * and at the start of closures and methods and throwing an exception if a timeout occurs.
+ * <p>
+ * This is especially useful when executing foreign scripts that you do not have control over.
+ * Inject this transformation into a script that you want to timeout after a specified amount of time.
+ * <p>
+ * Annotating anything in a script will cause for loops, while loops, methods, and closures to make an
+ * elapsed time check and throw a TimeoutException if the check yields true. The annotation by default
+ * will apply to any classes defined in the script as well. Annotating a class will cause (by default)
+ * all classes in the entire file ('Compilation Unit') to be enhanced. You can fine tune what is
+ * enhanced using the annotation parameters. Static methods and static fields are ignored.
+ * <p>
+ * The following is sample usage of the annotation forcing the script to timeout after 5 minutes (300 seconds):
+ *
+ * <pre>
+ * import groovy.transform.TimedInterrupt
+ * import java.util.concurrent.TimeUnit
+ *
+ * {@code @TimedInterrupt}(value = 300L, unit = TimeUnit.SECONDS)
+ * class MyClass {
+ *      def method() {
+ *          println '...'
+ *      }
+ * }
+ * </pre>
+ * This sample script will be transformed at compile time to something that resembles this:
+ * <pre>
+ * import java.util.concurrent.TimeUnit
+ * import java.util.concurrent.TimeoutException
+ *
+ * public class MyClass {
+ *     // XXXXXX below is a placeholder for a hashCode value at runtime
+ *     final private long timedInterruptXXXXXX$expireTime
+ *     final private java.util.Date timedInterruptXXXXXX$startTime
+ *
+ *     public MyClass() {
+ *         timedInterruptXXXXXX$expireTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(300, TimeUnit.SECONDS)
+ *         timedInterruptXXXXXX$startTime = new java.util.Date()
+ *     }
+ *
+ *     public java.lang.Object method() {
+ *         if (timedInterruptXXXXXX$expireTime < System.nanoTime()) {
+ *             throw new TimeoutException('Execution timed out after 300 units. Start time: ' + timedInterruptXXXXXX$startTime)
+ *         }
+ *         return this.println('...')
+ *     }
+ * }
+ * </pre>
+ * See the unit test for this class for additional examples.
+ *
+ * @author Hamlet D'Arcy
+ * @author Cedric Champeau
+ * @author Paul King
+ * @see ThreadInterrupt
+ * @see ConditionalInterrupt
+ * @since 1.8.0
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target([ ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
+@GroovyASTTransformationClass(["org.codehaus.groovy.transform.TimedInterruptibleASTTransformation"])
+@interface TimedInterrupt {
+    /**
+     * Set this to false if you have multiple classes within one source file and only want
+     * timeout checks on some of the classes (or you want different time constraints on different classes).
+     * Place an annotation with appropriate parameters on each class you want enhanced.
+     * Set to true (the default) for blanket coverage of timeout checks on all methods, loops
+     * and closures within all classes/script code.
+     *
+     * For even finer-grained control see {@code applyToAllMembers}.
+     *
+     * @see #applyToAllMembers()
+     */
+    boolean applyToAllClasses() default true
+
+    /**
+     * Set this to false if you have multiple methods/closures within a class or script and only
+     * want timeout checks on some of them (or you want different time constraints on different methods/closures).
+     * Place annotations with appropriate parameters on the methods/closures that you want enhanced.
+     * When false, {@code applyToAllClasses} is automatically set to false.
+     *
+     * Set to true (the default) for blanket coverage of timeout checks on all methods, loops
+     * and closures within the class/script.
+     *
+     * @since 2.2.0
+     * @see #applyToAllClasses()
+     */
+    boolean applyToAllMembers() default true
+
+    /**
+     * By default a time check is added to the start of all user-defined methods. To turn this off
+     * simply set this parameter to false.
+     */
+    boolean checkOnMethodStart() default true
+
+    /**
+     * The maximum elapsed time the script will be allowed to run for. By default it is measure in seconds
+     */
+    long value()
+
+    /**
+     * The TimeUnit of the value parameter. By default it is TimeUnit.SECONDS.
+     */
+    TimeUnit unit() default TimeUnit.SECONDS
+
+    /**
+     * The type of exception thrown when timeout is reached.
+     */
+    Class thrown() default TimeoutException
+}
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/ToString.java b/src/main/groovy/groovy/transform/ToString.java
new file mode 100644
index 0000000..968e7f0
--- /dev/null
+++ b/src/main/groovy/groovy/transform/ToString.java
@@ -0,0 +1,339 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of {@code toString()} methods in classes.
+ * The {@code @ToString} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary toString() method.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre>
+ * {@code @ToString}
+ * class Customer {
+ *     String first, last
+ *     int age
+ *     Date since = new Date()
+ *     Collection favItems
+ *     private answer = 42
+ * }
+ * println new Customer(first:'Tom', last:'Jones', age:21, favItems:['Books', 'Games'])
+ * </pre>
+ * Which will have this output:
+ * <pre>
+ * Customer(Tom, Jones, 21, Wed Jul 14 23:57:14 EST 2010, [Books, Games])
+ * </pre>
+ * There are numerous options to customize the format of the generated output.
+ * E.g. if you change the first annotation to:
+ * <pre>
+ * {@code @ToString(includeNames=true)}
+ * </pre>
+ * Then the output will be:
+ * <pre>
+ * Customer(first:Tom, last:Jones, age:21, since:Wed Jul 14 23:57:50 EST 2010, favItems:[Books, Games])
+ * </pre>
+ * Or if you change the first annotation to:
+ * <pre>
+ * {@code @ToString(includeNames=true,includeFields=true,excludes="since,favItems")}
+ * </pre>
+ * Then the output will be:
+ * <pre>
+ * Customer(first:Tom, last:Jones, age:21, answer:42)
+ * </pre>
+ * If you have this example:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * {@code @ToString} class NamedThing {
+ *     String name
+ * }
+ * {@code @ToString}(includeNames=true,includeSuper=true)
+ * class AgedThing extends NamedThing {
+ *     int age
+ * }
+ * String agedThingAsString = new AgedThing(name:'Lassie', age:5).toString()
+ * assert agedThingAsString == 'AgedThing(age:5, super:NamedThing(Lassie))'
+ * </pre>
+ * {@code @ToString} can also be used in conjunction with {@code @Canonical} and {@code @Immutable}.
+ * <p>
+ * If you want to omit fields or properties referring to <tt>null</tt>, you can use the <tt>ignoreNulls</tt> flag:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * {@code @ToString(ignoreNulls = true)} class NamedThing {
+ *     String name
+ * }
+ * assert new NamedThing(name: null).toString() == 'NamedThing()'
+ * </pre>
+ * <p>
+ * By default the fully-qualified class name is used as part of the generated toString.
+ * If you want to exclude the package, you can set the includePackage flag to false, e.g.:
+ * <pre>
+ * package my.company
+ * import groovy.transform.ToString
+ * {@code @ToString(includePackage = false)} class NamedThing {
+ *     String name
+ * }
+ * println new NamedThing(name: "Lassie")
+ * </pre>
+ * Which results in:
+ * <pre>
+ * NamedThing(name: Lassie)
+ * </pre>
+ * If the includePackage flag is {@code true} (the default), then the output will be:
+ * <pre>
+ * my.company.NamedThing(name: Lassie)
+ * </pre>
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------    
+ * // Most simple implementation of toString.
+ * import groovy.transform.ToString
+ *
+ * {@code @ToString}
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(mrhaki, [Groovy, Java])'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------    
+ * // includeNames to output the names of the properties.
+ * import groovy.transform.ToString
+ *
+ * &#64;ToString(includeNames=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java])'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // includeFields to not only output properties, but also field values.
+ * import groovy.transform.ToString
+ *
+ * &#64;ToString(includeNames=true, includeFields=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java], active:false)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------    
+ * // Use includeSuper to include properties from super class in output.
+ * import groovy.transform.ToString
+ *
+ * &#64;ToString(includeNames=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * &#64;ToString(includeSuper=true, includeNames=true)
+ * class Student extends Person {
+ *     List courses
+ * }
+ *
+ * def student = new Student(name: 'mrhaki', likes: ['Groovy', 'Java'], courses: ['IT', 'Business'])
+ *
+ * assert student.toString() == 'Student(courses:[IT, Business], super:Person(name:mrhaki, likes:[Groovy, Java]))'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------    
+ * // excludes active field and likes property from output
+ * import groovy.transform.ToString
+ *
+ * &#64;ToString(includeNames=true, includeFields=true, excludes='active,likes')
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ *
+ * assert person.toString() == 'Person(name:mrhaki)'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Don't include the package name in the output
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;ToString(includePackage=false)
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * final Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
+ *
+ * assert course.toString() == 'Course(Groovy 101, 200)'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Don't use properties with null value.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;ToString(ignoreNulls=true)
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * final Course course = new Course(title: 'Groovy 101')
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101)'
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // Cache toString() result.
+ * package com.mrhaki.blog.groovy
+ *
+ * import groovy.transform.*
+ *
+ * &#64;ToString(cache=true)
+ * class Course {
+ *     String title
+ *     Integer maxAttendees
+ * }
+ *
+ * Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
+ *
+ * // Value change will not be reflected in toString().
+ * course.title = 'Grails with REST'
+ *
+ * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
+ * assert course.title == 'Grails with REST'
+ * </pre> 
+ *
+ * @author Paul King
+ * @author Andre Steingress
+ * @see groovy.transform.Immutable
+ * @see groovy.transform.Canonical
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ToStringASTTransformation")
+public @interface ToString {
+    /**
+     * List of field and/or property names to exclude from generated toString.
+     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the generated toString.
+     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields and/or properties
+     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
+     * The special name 'super' can be used instead of using the 'includeSuper' flag.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Whether to include the toString() of super in the generated toString.
+     */
+    boolean includeSuper() default false;
+
+    /**
+     * Whether to include super properties in the generated toString.
+     * @since 2.4.0
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Whether to include names of properties/fields in the generated toString.
+     */
+    boolean includeNames() default false;
+
+    /**
+     * Include fields as well as properties in the generated toString.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Don't display any fields or properties with value <tt>null</tt>.
+     */
+    boolean ignoreNulls() default false;
+
+    /**
+     * Whether to include the fully-qualified class name (i.e. including
+     * the package) or just the simple class name in the generated toString.
+     * @since 2.0.6
+     */
+    boolean includePackage() default true;
+
+    /**
+     * Whether to include all properties (as per the JavaBean spec) in the generated toString.
+     * Groovy recognizes any field-like definitions with no explicit visibility as property definitions
+     * and always includes them in the {@code @ToString} generated toString (as well as auto-generating the
+     * appropriate getters and setters). Groovy also treats any explicitly created getXxx() or isYyy()
+     * methods as property getters as per the JavaBean specification. Old versions of Groovy did not.
+     * So set this flag to false for the old behavior or if you want to explicitly exclude such properties.
+     *
+     * @since 2.5
+     */
+    boolean allProperties() default true;
+
+    /**
+     * Whether to cache toString() calculations. You should only set this to true if
+     * you know the object is immutable (or technically mutable but never changed).
+     * @since 2.1.0
+     */
+    boolean cache() default false;
+
+    /**
+     * Whether to include all fields and/or properties in the generated toString, including those with names that
+     * are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+}


[29/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Trait.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Trait.java b/src/main/groovy/groovy/transform/Trait.java
new file mode 100644
index 0000000..de88180
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Trait.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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to mark a class as being a trait.
+ *
+ * @since 2.3.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.trait.TraitASTTransformation")
+public @interface Trait {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TupleConstructor.java b/src/main/groovy/groovy/transform/TupleConstructor.java
new file mode 100644
index 0000000..2cd2be7
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TupleConstructor.java
@@ -0,0 +1,278 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Class annotation used to assist in the creation of tuple constructors in classes.
+ * Should be used with care with other annotations which create constructors - see "Known
+ * Limitations" for more details.
+ * <p>
+ * It allows you to write classes in this shortened form:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.TupleConstructor} class Customer {
+ *     String first, last
+ *     int age
+ *     Date since
+ *     Collection favItems
+ * }
+ * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:new Date(), favItems:['Books', 'Games'])
+ * def c2 = new Customer('Tom', 'Jones', 21, new Date(), ['Books', 'Games'])
+ * def c3 = new Customer('Tom', 'Jones')
+ * </pre>
+ * The {@code @TupleConstructor} annotation instructs the compiler to execute an
+ * AST transformation which adds the necessary constructor method to your class.
+ * <p>
+ * A tuple constructor is created with a parameter for each property (and optionally field and
+ * super properties).
+ * A default value is provided (using Java's default values) for all parameters in the constructor.
+ * Groovy's normal conventions then allows any number of parameters to be left off the end of the parameter list
+ * including all of the parameters - giving a no-arg constructor which can be used with the map-style naming conventions.
+ * <p>
+ * The order of parameters is given by the properties of any super classes with most super first
+ * (if {@code includeSuperProperties} is set) followed by the properties of the class followed
+ * by the fields of the class (if {@code includeFields} is set). Within each grouping the order
+ * is as attributes appear within the respective class.
+ * <p>More examples:</p>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;TupleConstructor()
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'])
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ *
+ * person = new Person('mrhaki')
+ *
+ * assert person.name == 'mrhaki'
+ * assert !person.likes
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // includeFields in the constructor creation.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;TupleConstructor(includeFields=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'], true)
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ * assert person.activated
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // use force attribute to force creation of constructor
+ * // even if we define our own constructors.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;TupleConstructor(force=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     Person(boolean active) {
+ *         this.active = active
+ *     }
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * def person = new Person('mrhaki', ['Groovy', 'Java'])
+ *
+ * assert person.name == 'mrhaki'
+ * assert person.likes == ['Groovy', 'Java']
+ * assert !person.activated
+ *
+ * person = new Person(true)
+ *
+ * assert person.activated
+ * </pre>
+ * <pre class="groovyTestCase">
+ * //--------------------------------------------------------------------------
+ * // include properties and fields from super class.
+ * import groovy.transform.TupleConstructor
+ *
+ * &#64;TupleConstructor(includeFields=true)
+ * class Person {
+ *     String name
+ *     List likes
+ *     private boolean active = false
+ *
+ *     boolean isActivated() { active }
+ * }
+ *
+ * &#64;TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)
+ * class Student extends Person {
+ *     List courses
+ * }
+ *
+ * def student = new Student('mrhaki', ['Groovy', 'Java'], true, ['IT'])
+ *
+ * assert student.name == 'mrhaki'
+ * assert student.likes == ['Groovy', 'Java']
+ * assert student.activated
+ * assert student.courses == ['IT']
+ * </pre>
+ * <p>
+ * Known Limitations:
+ * <ul>
+ * <li>This AST transform might become a no-op if you are defining your own constructors or
+ * combining with other AST transforms which create constructors (e.g. {@code @InheritConstructors});
+ * the order in which the particular transforms are processed becomes important in that case.
+ * See the {@code force} attribute for further details about customizing this behavior.</li>
+ * <li>This AST transform normally uses default parameter values which creates multiple constructors under
+ * the covers. You should use with care if you are defining your own constructors or
+ * combining with other AST transforms which create constructors (e.g. {@code @InheritConstructors});
+ * the order in which the particular transforms are processed becomes important in that case.
+ * See the {@code defaults} attribute for further details about customizing this behavior.</li>
+ * <li>Groovy's normal map-style naming conventions will not be available if the first property (or field)
+ * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property (or field)</li>
+ * </ul>
+ *
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.TupleConstructorASTTransformation")
+public @interface TupleConstructor {
+    /**
+     * List of field and/or property names to exclude from the constructor.
+     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the constructor.
+     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined;
+     * all fields are included if includes remains undefined and excludes is explicitly or implicitly
+     * an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * Include fields in the constructor.
+     */
+    boolean includeFields() default false;
+
+    /**
+     * Include properties in the constructor.
+     */
+    boolean includeProperties() default true;
+
+    /**
+     * Include fields from super classes in the constructor.
+     */
+    boolean includeSuperFields() default false;
+
+    /**
+     * Include properties from super classes in the constructor.
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Should super properties be called within a call to the parent constructor
+     * rather than set as properties. Typically used in combination with {@code includeSuperProperties}.
+     * Can't be true if using {@code pre} with a {@code super} first statement.
+     */
+    boolean callSuper() default false;
+
+    /**
+     * By default, this annotation becomes a no-op if you provide your own constructor.
+     * By setting {@code force=true} then the tuple constructor(s) will be added regardless of
+     * whether existing constructors exist. It is up to you to avoid creating duplicate constructors.
+     */
+    boolean force() default false;
+
+    /**
+     * Used to set whether default value processing is enabled (the default) or disabled.
+     *
+     * By default, every constructor parameter is given a default value. This value will
+     * be Java's default for primitive types (zero or false) and null for Objects, unless
+     * an initial value is given when declaring the property or field. A consequence of
+     * this design is that you can leave off parameters from the right if the default
+     * value will suffice. As far as Java interoperability is concerned, Groovy will
+     * create additional constructors under the covers representing the constructors
+     * with parameters left off, all the way from the constructor with all arguments
+     * to the no-arg constructor.
+     *
+     * However, when set to false, default values are not allowed for properties and fields.
+     * Only the constructor containing all arguments will be provided.
+     * In particular, a no-arg constructor won't be provided and since this is currently
+     * used by Groovy when using named-arguments, the named-argument style won't be available.
+     */
+    boolean defaults() default true;
+
+    /**
+     * By default, properties are set directly using their respective field.
+     * By setting {@code useSetters=true} then a writable property will be set using its setter.
+     * If turning on this flag we recommend that setters that might be called are
+     * made null-safe wrt the parameter.
+     */
+    boolean useSetters() default false;
+
+    /**
+     * Whether to include all fields and/or properties within the constructor, including those with names that are
+     * considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+
+    /**
+     * A Closure containing statements which will be prepended to the generated constructor. The first statement
+     * within the Closure may be {@code super(someArgs)} in which case the no-arg super constructor won't be called.
+     *
+     * @since 2.5.0
+     */
+    Class pre() default Undefined.CLASS.class;
+
+    /**
+     * A Closure containing statements which will be appended to the end of the generated constructor. Useful for validation steps or tweaking the populated fields/properties.
+     *
+     * @since 2.5.0
+     */
+    Class post() default Undefined.CLASS.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/TypeChecked.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TypeChecked.java b/src/main/groovy/groovy/transform/TypeChecked.java
new file mode 100644
index 0000000..b902f3f
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TypeChecked.java
@@ -0,0 +1,70 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This will let the Groovy compiler use compile time checks in the style of Java.
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({   ElementType.METHOD,         ElementType.TYPE,
+            ElementType.CONSTRUCTOR
+})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.StaticTypesTransformation")
+public @interface TypeChecked {
+    TypeCheckingMode value() default TypeCheckingMode.PASS;
+
+    /**
+     * The list of (classpath resources) paths to type checking DSL scripts, also known
+     * as type checking extensions.
+     * @return an array of paths to groovy scripts that must be on compile classpath
+     */
+    String[] extensions() default {};
+
+    /**
+     * This annotation is added by @TypeChecked on methods which have type checking turned on.
+     * It is used to embed type information into binary, so that the type checker can use this information,
+     * if available, for precompiled classes.
+     */
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface TypeCheckingInfo {
+        /**
+         * Returns the type checker information protocol number. This is used if the format of the
+         * string used in {@link #inferredType()} changes.
+         * @return the protocol version
+         */
+        int version() default 0;
+
+        /**
+         * An encoded type information.
+         * @return the inferred type
+         */
+        String inferredType();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/TypeCheckingMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/TypeCheckingMode.java b/src/main/groovy/groovy/transform/TypeCheckingMode.java
new file mode 100644
index 0000000..075bd71
--- /dev/null
+++ b/src/main/groovy/groovy/transform/TypeCheckingMode.java
@@ -0,0 +1,31 @@
+/*
+ *  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 groovy.transform;
+
+/**
+ * This enumeration can be used whenever it is preferred to annotate a class as
+ * {@link TypeChecked} in general, but where only one or more methods are "dynamic". This allows the user
+ * to annotate the class itself then annotate only the methods which require exclusion.
+ *
+ * @author Cedric Champeau
+ */
+public enum TypeCheckingMode {
+    PASS,
+    SKIP
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/Undefined.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/Undefined.java b/src/main/groovy/groovy/transform/Undefined.java
new file mode 100644
index 0000000..35b360d
--- /dev/null
+++ b/src/main/groovy/groovy/transform/Undefined.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 groovy.transform;
+
+import org.codehaus.groovy.ast.ClassNode;
+
+/**
+ * Java doesn't allow you to have null as an attribute value. It wants you to indicate what you really
+ * mean by null, so that is what we do here - as ugly as it is.
+ */
+public final class Undefined {
+    private Undefined() {}
+    public static final String STRING = "<DummyUndefinedMarkerString-DoNotUse>";
+    public static final class CLASS {}
+    public static final class EXCEPTION extends RuntimeException {
+        private static final long serialVersionUID = -3960500360386581172L;
+    }
+    public static boolean isUndefined(String other) { return STRING.equals(other); }
+    public static boolean isUndefined(ClassNode other) { return CLASS.class.getName().equals(other.getName()); }
+    public static boolean isUndefinedException(ClassNode other) { return EXCEPTION.class.getName().equals(other.getName()); }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/WithReadLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/WithReadLock.java b/src/main/groovy/groovy/transform/WithReadLock.java
new file mode 100644
index 0000000..475786a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/WithReadLock.java
@@ -0,0 +1,107 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in conjunction with {@link WithWriteLock} to support read and write synchronization on a method.
+ * <p>
+ * To use this annotation, declare {@code @WithReadLock} on your method. The method may be either an instance method or
+ * a static method. The resulting method will allow multiple threads to read the information at the same time.
+ * However, if some other method obtains a write lock, then this method will force callers to wait until the write is complete.
+ * <p>
+ * This annotation is a declarative wrapper around the JDK's <code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
+ * Objects containing this annotation will have a ReentrantReadWriteLock field named <code>$reentrantLock</code> added to the class,
+ * and method access is protected by the lock. If the method is static then the field is static and named <code>$REENTRANTLOCK</code>.
+ * <p>
+ * The annotation takes an optional parameter for the name of the field. This field must exist on the class and must be
+ * of type ReentrantReadWriteLock.
+ * <p>
+ * To understand how this annotation works, it is convenient to think in terms of the source code it replaces. The following
+ * is a typical usage of this annotation from Groovy:
+ * <pre>
+ * import groovy.transform.*;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
+ *
+ *    {@code @WithReadLock}
+ *     public String getResource(String key) throws Exception {
+ *             return data.get(key);
+ *     }
+ *
+ *    {@code @WithWriteLock}
+ *     public void refresh() throws Exception {
+ *             //reload the resources into memory
+ *     }
+ * }
+ * </pre>
+ * As part of the Groovy compiler, code resembling this is produced:
+ * <pre>
+ * import java.util.concurrent.locks.ReentrantReadWriteLock;
+ * import java.util.concurrent.locks.ReadWriteLock;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final ReadWriteLock $reentrantlock = new ReentrantReadWriteLock();
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
+ *
+ *     public String getResource(String key) throws Exception {
+ *         $reentrantlock.readLock().lock();
+ *         try {
+ *             return data.get(key);
+ *         } finally {
+ *             $reentrantlock.readLock().unlock();
+ *         }
+ *     }
+ *
+ *     public void refresh() throws Exception {
+ *         $reentrantlock.writeLock().lock();
+ *         try {
+ *             //reload the resources into memory
+ *         } finally {
+ *             $reentrantlock.writeLock().unlock();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * @author Hamlet D'Arcy
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
+public @interface WithReadLock {
+    /**
+     * @return if a user specified lock object with the given name should be used
+     *      the lock object must exist. If the annotated method is static then the 
+     *      lock object must be static. If the annotated method is not static then 
+     *      the lock object must not be static. 
+     */
+    String value () default "";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/WithWriteLock.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/WithWriteLock.java b/src/main/groovy/groovy/transform/WithWriteLock.java
new file mode 100644
index 0000000..1eeb7f0
--- /dev/null
+++ b/src/main/groovy/groovy/transform/WithWriteLock.java
@@ -0,0 +1,107 @@
+/*
+ *  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 groovy.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in conjunction with {@link WithReadLock} to support read and write synchronization on a method.
+ * <p>
+ * To use this annotation, declare {@code @WithWriteLock} on your method. The method may be either an instance method or
+ * a static method. The resulting method will allow only one thread access to the method at a time, and will wait to access
+ * the method until any other read locks have been released.
+ * <p>
+ * This annotation is a declarative wrapper around the JDK's <code>java.util.concurrent.locks.ReentrantReadWriteLock</code>.
+ * Objects containing this annotation will have a ReentrantReadWriteLock field named <code>$reentrantLock</code> added to the class,
+ * and method access is protected by the lock. If the method is static then the field is static and named <code>$REENTRANTLOCK</code>.
+ * <p>
+ * The annotation takes an optional parameter for the name of the field. This field must exist on the class and must be
+ * of type ReentrantReadWriteLock.
+ * <p>
+ * To understand how this annotation works, it is convenient to think in terms of the source code it replaces. The following
+ * is a typical usage of this annotation from Groovy:
+ * <pre>
+ * import groovy.transform.*;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
+ *
+ *    {@code @WithReadLock}
+ *     public String getResource(String key) throws Exception {
+ *             return data.get(key);
+ *     }
+ *
+ *    {@code @WithWriteLock}
+ *     public void refresh() throws Exception {
+ *             //reload the resources into memory
+ *     }
+ * }
+ * </pre>
+ * As part of the Groovy compiler, code resembling this is produced:
+ * <pre>
+ * import java.util.concurrent.locks.ReentrantReadWriteLock;
+ * import java.util.concurrent.locks.ReadWriteLock;
+ *
+ * public class ResourceProvider {
+ *
+ *     private final ReadWriteLock $reentrantlock = new ReentrantReadWriteLock();
+ *     private final Map&lt;String, String&gt; data = new HashMap&lt;String, String&gt;();
+ *
+ *     public String getResource(String key) throws Exception {
+ *         $reentrantlock.readLock().lock();
+ *         try {
+ *             return data.get(key);
+ *         } finally {
+ *             $reentrantlock.readLock().unlock();
+ *         }
+ *     }
+ *
+ *     public void refresh() throws Exception {
+ *         $reentrantlock.writeLock().lock();
+ *         try {
+ *             //reload the resources into memory
+ *         } finally {
+ *             $reentrantlock.writeLock().unlock();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * @author Hamlet D'Arcy
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.ReadWriteLockASTTransformation")
+public @interface WithWriteLock {
+    /**
+     * @return if a user specified lock object with the given name should be used
+     *      the lock object must exist. If the annotated method is static then the 
+     *      lock object must be static. If the annotated method is not static then 
+     *      the lock object must not be static. 
+     */
+    String value () default "";
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/builder/Builder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/Builder.java b/src/main/groovy/groovy/transform/builder/Builder.java
new file mode 100644
index 0000000..93b6090
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/Builder.java
@@ -0,0 +1,160 @@
+/*
+ *  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 groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static org.codehaus.groovy.transform.BuilderASTTransformation.BuilderStrategy;
+
+/**
+ * The {@code @Builder} AST transformation is used to help write classes that can be created using <em>fluent</em> api calls.<!-- -->
+ * The transform supports multiple building strategies to cover a range of cases and there are a number
+ * of configuration options to customize the building process.
+ *
+ * In addition, a number of annotation attributes let you customise the building process. Not all annotation attributes
+ * are supported by all strategies. See the individual strategy documentation for more details.
+ * If you're an AST hacker, you can also define your own strategy class.
+ *
+ * The following strategies are bundled with Groovy:
+ * <ul>
+ *     <li>{@link SimpleStrategy} for creating chained setters</li>
+ *     <li>{@link ExternalStrategy} where you annotate an explicit builder class while leaving some buildee class being built untouched</li>
+ *     <li>{@link DefaultStrategy} which creates a nested helper class for instance creation</li>
+ *     <li>{@link InitializerStrategy} which creates a nested helper class for instance creation which when used with {@code @CompileStatic} allows type-safe object creation</li>
+ * </ul>
+ *
+ * Note that Groovy provides other built-in mechanisms for easy creation of objects, e.g. the named-args constructor:
+ * <pre>
+ * new Person(firstName: "Robert", lastName: "Lewandowski", age: 21)
+ * </pre>
+ * or the with statement:
+ * <pre>
+ * new Person().with {
+ *     firstName = "Robert"
+ *     lastName = "Lewandowski"
+ *     age = 21
+ * }
+ * </pre>
+ * so you might not find value in using the builder transform at all. But if you need Java integration or in some cases improved type safety, the {@code @Builder} transform might prove very useful.
+ *
+ * @see groovy.transform.builder.SimpleStrategy
+ * @see groovy.transform.builder.ExternalStrategy
+ * @see groovy.transform.builder.DefaultStrategy
+ * @see groovy.transform.builder.InitializerStrategy
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.BuilderASTTransformation")
+public @interface Builder {
+
+    /**
+     * A class for which builder methods should be created. It will be an error to leave
+     * this attribute with its default value for some strategies.
+     */
+    Class forClass() default Undefined.CLASS.class;
+
+    /**
+     * A class capturing the builder strategy
+     */
+    Class<? extends BuilderStrategy> builderStrategy() default DefaultStrategy.class;
+
+    /**
+     * The prefix to use when creating the setter methods.
+     * Default is determined by the strategy which might use "" or "set" but you can choose your own, e.g. "with".
+     * If non-empty the first letter of the property will be capitalized before being appended to the prefix.
+     */
+    String prefix() default Undefined.STRING;
+
+    /**
+     * For strategies which create a builder helper class, the class name to use for the helper class.
+     * Not used if using {@code forClass} since in such cases the builder class is explicitly supplied.
+     * Default is determined by the strategy, e.g. <em>TargetClass</em> + "Builder" or <em>TargetClass</em> + "Initializer".
+     */
+    String builderClassName() default Undefined.STRING;
+
+    /**
+     * For strategies which create a builder helper class that creates the instance, the method name to call to create the instance.
+     * Default is determined by the strategy, e.g. <em>build</em> or <em>create</em>.
+     */
+    String buildMethodName() default Undefined.STRING;
+
+    /**
+     * The method name to use for a builder factory method in the source class for easy access of the
+     * builder helper class for strategies which create such a helper class.
+     * Must not be used if using {@code forClass}.
+     * Default is determined by the strategy, e.g. <em>builder</em> or <em>createInitializer</em>.
+     */
+    String builderMethodName() default Undefined.STRING;
+
+    /**
+     * List of field and/or property names to exclude from generated builder methods.
+     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     */
+    String[] excludes() default {};
+
+    /**
+     * List of field and/or property names to include within the generated builder methods.
+     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields
+     * are included if includes remains undefined and excludes is explicitly or implicitly an empty list.
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * By default, properties are set directly using their respective field.
+     * By setting {@code useSetters=true} then a writable property will be set using its setter.
+     * If turning on this flag we recommend that setters that might be called are
+     * made null-safe wrt the parameter.
+     */
+    boolean useSetters() default false;
+
+    /**
+     * Generate builder methods for properties from super classes.
+     */
+    boolean includeSuperProperties() default false;
+
+    /**
+     * Whether the generated builder should support all properties, including those with names that are considered internal.
+     *
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+
+    /**
+     * Whether to include all properties (as per the JavaBean spec) in the generated builder.
+     * Groovy recognizes any field-like definitions with no explicit visibility as property definitions
+     * and always includes them in the {@code @Builder} generated classes. Groovy also treats any explicitly created getXxx() or isYyy()
+     * methods as property getters as per the JavaBean specification. Old versions of Groovy did not.
+     * So set this flag to false for the old behavior or if you want to explicitly exclude such properties.
+     * Currently only supported by DefaultStrategy and ExternalStrategy.
+     *
+     * @since 2.5.0
+     */
+    boolean allProperties() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/DefaultStrategy.java b/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
new file mode 100644
index 0000000..65d90e3
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/DefaultStrategy.java
@@ -0,0 +1,293 @@
+/*
+ *  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 groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
+import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to create a builder helper class
+ * for the fluent creation of instances of a specified class.&nbsp;It can be used at the class,
+ * static method or constructor levels.
+ *
+ * You use it as follows:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ *
+ * {@code @Builder}
+ * class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * def person = Person.builder().firstName("Robert").lastName("Lewandowski").age(21).build()
+ * assert person.firstName == "Robert"
+ * assert person.lastName == "Lewandowski"
+ * assert person.age == 21
+ * </pre>
+ * The {@code prefix} annotation attribute can be used to create setters with a different naming convention. The default is the
+ * empty string but you could change that to "set" as follows:
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.builder.Builder}(prefix='set')
+ * class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * def p2 = Person.builder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
+ * </pre>
+ * or using a prefix of 'with' would result in usage like this:
+ * <pre>
+ * def p3 = Person.builder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
+ * </pre>
+ *
+ * You can also use the {@code @Builder} annotation in combination with this strategy on one or more constructor or
+ * static method instead of or in addition to using it at the class level. An example with a constructor follows:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.ToString
+ * import groovy.transform.builder.Builder
+ *
+ * {@code @ToString}
+ * class Person {
+ *     String first, last
+ *     int born
+ *
+ *     {@code @Builder}
+ *     Person(String roleName) {
+ *         if (roleName == 'Jack Sparrow') {
+ *             first = 'Johnny'; last = 'Depp'; born = 1963
+ *         }
+ *     }
+ * }
+ * assert Person.builder().roleName("Jack Sparrow").build().toString() == 'Person(Johnny, Depp, 1963)'
+ * </pre>
+ * In this case, the parameter(s) for the constructor or static method become the properties available
+ * in the builder. For the case of a static method, the return type of the static method becomes the
+ * class of the instance being created. For static factory methods, this is normally the class containing the
+ * static method but in general it can be any class.
+ *
+ * Note: if using more than one {@code @Builder} annotation, which is only possible when using static method
+ * or constructor variants, it is up to you to ensure that any generated helper classes or builder methods
+ * have unique names. E.g.&nbsp;we can modify the previous example to have three builders. At least two of the builders
+ * in our case will need to set the 'builderClassName' and 'builderMethodName' annotation attributes to ensure
+ * we have unique names. This is shown in the following example:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ * import groovy.transform.*
+ *
+ * {@code @ToString}
+ * {@code @Builder}
+ * class Person {
+ *     String first, last
+ *     int born
+ *
+ *     Person(){} // required to retain no-arg constructor
+ *
+ *     {@code @Builder}(builderClassName='MovieBuilder', builderMethodName='byRoleBuilder')
+ *     Person(String roleName) {
+ *         if (roleName == 'Jack Sparrow') {
+ *             this.first = 'Johnny'; this.last = 'Depp'; this.born = 1963
+ *         }
+ *     }
+ *
+ *     {@code @Builder}(builderClassName='SplitBuilder', builderMethodName='splitBuilder')
+ *     static Person split(String name, int year) {
+ *         def parts = name.split(' ')
+ *         new Person(first: parts[0], last: parts[1], born: year)
+ *     }
+ * }
+ *
+ * assert Person.splitBuilder().name("Johnny Depp").year(1963).build().toString() == 'Person(Johnny, Depp, 1963)'
+ * assert Person.byRoleBuilder().roleName("Jack Sparrow").build().toString() == 'Person(Johnny, Depp, 1963)'
+ * assert Person.builder().first("Johnny").last('Depp').born(1963).build().toString() == 'Person(Johnny, Depp, 1963)'
+ * </pre>
+ *
+ * The 'forClass' annotation attribute for the {@code @Builder} transform isn't applicable for this strategy.
+ * The 'useSetters' annotation attribute for the {@code @Builder} transform is ignored by this strategy which always uses setters.
+ */
+public class DefaultStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
+    private static final Expression DEFAULT_INITIAL_VALUE = null;
+    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
+
+    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
+        if (unsupportedAttribute(transform, anno, "forClass")) return;
+        if (annotatedNode instanceof ClassNode) {
+            buildClass(transform, (ClassNode) annotatedNode, anno);
+        } else if (annotatedNode instanceof MethodNode) {
+            buildMethod(transform, (MethodNode) annotatedNode, anno);
+        }
+    }
+
+    public void buildMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
+        if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "excludes") != null) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
+                    " processing: includes/excludes only allowed on classes", anno);
+        }
+        ClassNode buildee = mNode.getDeclaringClass();
+        ClassNode builder = createBuilder(anno, buildee);
+        createBuilderFactoryMethod(anno, buildee, builder);
+        for (Parameter parameter : mNode.getParameters()) {
+            builder.addField(createFieldCopy(buildee, parameter));
+            builder.addMethod(createBuilderMethodForProp(builder, new PropertyInfo(parameter.getName(), parameter.getType()), getPrefix(anno)));
+        }
+        builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, mNode.getParameters()));
+    }
+
+    public void buildClass(BuilderASTTransformation transform, ClassNode buildee, AnnotationNode anno) {
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
+        ClassNode builder = createBuilder(anno, buildee);
+        createBuilderFactoryMethod(anno, buildee, builder);
+//        List<FieldNode> fields = getFields(transform, anno, buildee);
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+        boolean allProperties = !transform.memberHasValue(anno, "allProperties", false);
+        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, excludes, includes, allNames, allProperties);
+        for (PropertyInfo pi : props) {
+            ClassNode correctedType = getCorrectedType(buildee, pi.getType(), builder);
+            String fieldName = pi.getName();
+            builder.addField(createFieldCopy(buildee, fieldName, correctedType));
+            builder.addMethod(createBuilderMethodForProp(builder, new PropertyInfo(fieldName, correctedType), getPrefix(anno)));
+        }
+        builder.addMethod(createBuildMethod(anno, buildee, props));
+    }
+
+    private static ClassNode getCorrectedType(ClassNode buildee, ClassNode fieldType, ClassNode declaringClass) {
+        Map<String,ClassNode> genericsSpec = createGenericsSpec(declaringClass);
+        extractSuperClassGenerics(fieldType, buildee, genericsSpec);
+        return correctToGenericsSpecRecurse(genericsSpec, fieldType);
+    }
+
+    private static void createBuilderFactoryMethod(AnnotationNode anno, ClassNode buildee, ClassNode builder) {
+        buildee.getModule().addClass(builder);
+        buildee.addMethod(createBuilderMethod(anno, builder));
+    }
+
+    private static ClassNode createBuilder(AnnotationNode anno, ClassNode buildee) {
+        return new InnerClassNode(buildee, getFullName(anno, buildee), PUBLIC_STATIC, OBJECT_TYPE);
+    }
+
+    private static String getFullName(AnnotationNode anno, ClassNode buildee) {
+        String builderClassName = getMemberStringValue(anno, "builderClassName", buildee.getNameWithoutPackage() + "Builder");
+        return buildee.getName() + "$" + builderClassName;
+    }
+
+    private static String getPrefix(AnnotationNode anno) {
+        return getMemberStringValue(anno, "prefix", "");
+    }
+
+    private static MethodNode createBuildMethodForMethod(AnnotationNode anno, ClassNode buildee, MethodNode mNode, Parameter[] params) {
+        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
+        final BlockStatement body = new BlockStatement();
+        ClassNode returnType;
+        if (mNode instanceof ConstructorNode) {
+            returnType = newClass(buildee);
+            body.addStatement(returnS(ctorX(newClass(mNode.getDeclaringClass()), args(params))));
+        } else {
+            body.addStatement(returnS(callX(newClass(mNode.getDeclaringClass()), mNode.getName(), args(params))));
+            returnType = newClass(mNode.getReturnType());
+        }
+        return new MethodNode(buildMethodName, ACC_PUBLIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private static MethodNode createBuilderMethod(AnnotationNode anno, ClassNode builder) {
+        String builderMethodName = getMemberStringValue(anno, "builderMethodName", "builder");
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(returnS(ctorX(builder)));
+        return new MethodNode(builderMethodName, PUBLIC_STATIC, builder, NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private static MethodNode createBuildMethod(AnnotationNode anno, ClassNode buildee, List<PropertyInfo> props) {
+        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(returnS(initializeInstance(buildee, props, body)));
+        return new MethodNode(buildMethodName, ACC_PUBLIC, newClass(buildee), NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private MethodNode createBuilderMethodForProp(ClassNode builder, PropertyInfo pinfo, String prefix) {
+        ClassNode fieldType = pinfo.getType();
+        String fieldName = pinfo.getName();
+        String setterName = getSetterName(prefix, fieldName);
+        return new MethodNode(setterName, ACC_PUBLIC, newClass(builder), params(param(fieldType, fieldName)), NO_EXCEPTIONS, block(
+                stmt(assignX(propX(varX("this"), constX(fieldName)), varX(fieldName, fieldType))),
+                returnS(varX("this", builder))
+        ));
+    }
+
+    private static FieldNode createFieldCopy(ClassNode buildee, Parameter param) {
+        Map<String,ClassNode> genericsSpec = createGenericsSpec(buildee);
+        extractSuperClassGenerics(param.getType(), buildee, genericsSpec);
+        ClassNode correctedParamType = correctToGenericsSpecRecurse(genericsSpec, param.getType());
+        return new FieldNode(param.getName(), ACC_PRIVATE, correctedParamType, buildee, param.getInitialExpression());
+    }
+
+    private static FieldNode createFieldCopy(ClassNode buildee, String fieldName, ClassNode fieldType) {
+        return new FieldNode(fieldName, ACC_PRIVATE, fieldType, buildee, DEFAULT_INITIAL_VALUE);
+    }
+
+    private static Expression initializeInstance(ClassNode buildee, List<PropertyInfo> props, BlockStatement body) {
+        Expression instance = varX("_the" + buildee.getNameWithoutPackage(), buildee);
+        body.addStatement(declS(instance, ctorX(buildee)));
+        for (PropertyInfo pi : props) {
+            body.addStatement(stmt(assignX(propX(instance, pi.getName()), varX(pi.getName(), pi.getType()))));
+        }
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/ExternalStrategy.java b/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
new file mode 100644
index 0000000..c482bef
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/ExternalStrategy.java
@@ -0,0 +1,158 @@
+/*
+ *  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 groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.MY_TYPE_NAME;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to populate a builder helper class
+ * so that it can be used for the fluent creation of instances of a specified class.&nbsp;The specified class is not modified in any way and may be a Java class.
+ *
+ * You use it by creating and annotating an explicit builder class which will be filled in by during
+ * annotation processing with the appropriate build method and setters. An example is shown here:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ *
+ * class Person {
+ *     String firstName
+ *     String lastName
+ * }
+ *
+ * {@code @Builder}(builderStrategy=ExternalStrategy, forClass=Person)
+ * class PersonBuilder { }
+ *
+ * def person = new PersonBuilder().firstName("Robert").lastName("Lewandowski").build()
+ * assert person.firstName == "Robert"
+ * assert person.lastName == "Lewandowski"
+ * </pre>
+ * The {@code prefix} annotation attribute, which defaults to the empty String for this strategy, can be used to create setters with a different naming convention, e.g. with
+ * the {@code prefix} changed to 'set', you would use your setters as follows:
+ * <pre>
+ * def p1 = new PersonBuilder().setFirstName("Robert").setLastName("Lewandowski").setAge(21).build()
+ * </pre>
+ * or using a prefix of 'with':
+ * <pre>
+ * def p2 = new PersonBuilder().withFirstName("Robert").withLastName("Lewandowski").withAge(21).build()
+ * </pre>
+ *
+ * The properties to use can be filtered using either the 'includes' or 'excludes' annotation attributes for {@code @Builder}.
+ * The {@code @Builder} 'buildMethodName' annotation attribute can be used for configuring the build method's name, default "build".
+ *
+ * The {@code @Builder} 'builderMethodName' and 'builderClassName' annotation attributes aren't applicable for this strategy.
+ * The {@code @Builder} 'useSetters' annotation attribute is ignored by this strategy which always uses setters.
+ */
+public class ExternalStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
+    private static final Expression DEFAULT_INITIAL_VALUE = null;
+
+    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
+        if (!(annotatedNode instanceof ClassNode)) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: building for " +
+                    annotatedNode.getClass().getSimpleName() + " not supported by " + getClass().getSimpleName(), annotatedNode);
+            return;
+        }
+        ClassNode builder = (ClassNode) annotatedNode;
+        String prefix = transform.getMemberStringValue(anno, "prefix", "");
+        ClassNode buildee = transform.getMemberClassValue(anno, "forClass");
+        if (buildee == null) {
+            transform.addError("Error during " + MY_TYPE_NAME + " processing: 'forClass' must be specified for " + getClass().getName(), anno);
+            return;
+        }
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
+        if (unsupportedAttribute(transform, anno, "builderClassName")) return;
+        if (unsupportedAttribute(transform, anno, "builderMethodName")) return;
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+        boolean allProperties = !transform.memberHasValue(anno, "allProperties", false);
+        List<PropertyInfo> props = getPropertyInfos(transform, anno, buildee, excludes, includes, allNames, allProperties);
+        if (includes != null) {
+            for (String name : includes) {
+                checkKnownProperty(transform, anno, name, props);
+            }
+        }
+        for (PropertyInfo prop : props) {
+            builder.addField(createFieldCopy(builder, prop));
+            builder.addMethod(createBuilderMethodForField(builder, prop, prefix));
+        }
+        builder.addMethod(createBuildMethod(transform, anno, buildee, props));
+    }
+
+    private static MethodNode createBuildMethod(BuilderASTTransformation transform, AnnotationNode anno, ClassNode sourceClass, List<PropertyInfo> fields) {
+        String buildMethodName = transform.getMemberStringValue(anno, "buildMethodName", "build");
+        final BlockStatement body = new BlockStatement();
+        Expression sourceClassInstance = initializeInstance(sourceClass, fields, body);
+        body.addStatement(returnS(sourceClassInstance));
+        return new MethodNode(buildMethodName, ACC_PUBLIC, sourceClass, NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private MethodNode createBuilderMethodForField(ClassNode builderClass, PropertyInfo prop, String prefix) {
+        String propName = prop.getName().equals("class") ? "clazz" : prop.getName();
+        String setterName = getSetterName(prefix, prop.getName());
+        return new MethodNode(setterName, ACC_PUBLIC, newClass(builderClass), params(param(newClass(prop.getType()), propName)), NO_EXCEPTIONS, block(
+                stmt(assignX(propX(varX("this"), constX(propName)), varX(propName))),
+                returnS(varX("this", newClass(builderClass)))
+        ));
+    }
+
+    private static FieldNode createFieldCopy(ClassNode builderClass, PropertyInfo prop) {
+        String propName = prop.getName();
+        return new FieldNode(propName.equals("class") ? "clazz" : propName, ACC_PRIVATE, newClass(prop.getType()), builderClass, DEFAULT_INITIAL_VALUE);
+    }
+
+    private static Expression initializeInstance(ClassNode sourceClass, List<PropertyInfo> props, BlockStatement body) {
+        Expression instance = varX("_the" + sourceClass.getNameWithoutPackage(), sourceClass);
+        body.addStatement(declS(instance, ctorX(sourceClass)));
+        for (PropertyInfo prop : props) {
+            body.addStatement(stmt(assignX(propX(instance, prop.getName()), varX(prop.getName().equals("class") ? "clazz" : prop.getName(), newClass(prop.getType())))));
+        }
+        return instance;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/builder/InitializerStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/InitializerStrategy.java b/src/main/groovy/groovy/transform/builder/InitializerStrategy.java
new file mode 100644
index 0000000..c678c38
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/InitializerStrategy.java
@@ -0,0 +1,388 @@
+/*
+ *  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 groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.classgen.Verifier;
+import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+import org.codehaus.groovy.transform.ImmutableASTTransformation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorThisS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafeWithGenerics;
+import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_PARAMS;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to create a builder helper class
+ * for the fluent and type-safe creation of instances of a specified class.
+ *
+ * It is modelled roughly on the design outlined here:
+ * http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/
+ *
+ * You define classes which use the type-safe initializer pattern as follows:
+ * <pre>
+ * import groovy.transform.builder.*
+ * import groovy.transform.*
+ *
+ * {@code @ToString}
+ * {@code @Builder}(builderStrategy=InitializerStrategy) class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * </pre>
+ * While it isn't required to do so, the benefit of this builder strategy comes in conjunction with static type-checking or static compilation. Typical usage is as follows:
+ * <pre>
+ * {@code @CompileStatic}
+ * def main() {
+ *     println new Person(Person.createInitializer().firstName("John").lastName("Smith").age(21))
+ * }
+ * </pre>
+ * which prints:
+ * <pre>
+ * Person(John, Smith, 21)
+ * </pre>
+ * If you don't initialise some of the properties, your code won't compile, e.g. if the method body above was changed to this:
+ * <pre>
+ * println new Person(Person.createInitializer().firstName("John").lastName("Smith"))
+ * </pre>
+ * then the following compile-time error would result:
+ * <pre>
+ * [Static type checking] - Cannot find matching method Person#<init>(Person$PersonInitializer <groovy.transform.builder.InitializerStrategy$SET, groovy.transform.builder.InitializerStrategy$SET, groovy.transform.builder.InitializerStrategy$UNSET>). Please check if the declared type is right and if the method exists.
+ * </pre>
+ * The message is a little cryptic, but it is basically the static compiler telling us that the third parameter, {@code age} in our case, is unset.
+ *
+ * You can also add this annotation to your predefined constructors. These will be made private and an initializer will be set up
+ * to call your constructor. Any parameters to your constructor become the properties expected by the initializer.
+ * If you use such a builder on a constructor as well as on the class or on more than one constructor, then it is up to you
+ * to define unique values for 'builderClassName' and 'builderMethodName' for each annotation.
+ */
+public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
+
+    /**
+     * Internal phantom type used by the {@code InitializerStrategy} to indicate that a property has been set. It is used in conjunction with the generated parameterized type helper class.
+     */
+    public abstract static class SET {
+    }
+
+    /**
+     * Internal phantom type used by the {@code InitializerStrategy} to indicate that a property remains unset. It is used in conjunction with the generated parameterized type helper class.
+     */
+    public abstract static class UNSET {
+    }
+
+    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
+    private static final Expression DEFAULT_INITIAL_VALUE = null;
+
+    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
+        if (unsupportedAttribute(transform, anno, "forClass")) return;
+        if (unsupportedAttribute(transform, anno, "allProperties")) return;
+        boolean useSetters = transform.memberHasValue(anno, "useSetters", true);
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+        if (annotatedNode instanceof ClassNode) {
+            createBuilderForAnnotatedClass(transform, (ClassNode) annotatedNode, anno, useSetters, allNames);
+        } else if (annotatedNode instanceof MethodNode) {
+            createBuilderForAnnotatedMethod(transform, (MethodNode) annotatedNode, anno, useSetters);
+        }
+    }
+
+    private void createBuilderForAnnotatedClass(BuilderASTTransformation transform, ClassNode buildee, AnnotationNode anno, boolean useSetters, boolean allNames) {
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
+        List<FieldNode> fields = getFields(transform, anno, buildee);
+        List<FieldNode> filteredFields = filterFields(fields, includes, excludes, allNames);
+        if (filteredFields.isEmpty()) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
+                    " processing: at least one property is required for this strategy", anno);
+        }
+        ClassNode builder = createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), filteredFields.size());
+        addFields(buildee, filteredFields, builder);
+
+        buildCommon(buildee, anno, filteredFields, builder);
+        createBuildeeConstructors(transform, buildee, builder, filteredFields, true, useSetters);
+    }
+
+    private void createBuilderForAnnotatedMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno, boolean useSetters) {
+        if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "excludes") != null) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
+                    " processing: includes/excludes only allowed on classes", anno);
+        }
+        if (mNode instanceof ConstructorNode) {
+            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC);
+        } else {
+            if ((mNode.getModifiers() & ACC_STATIC) == 0) {
+                transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
+                        " processing: method builders only allowed on static methods", anno);
+            }
+            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC);
+        }
+        ClassNode buildee = mNode.getDeclaringClass();
+        Parameter[] parameters = mNode.getParameters();
+        if (parameters.length == 0) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
+                    " processing: at least one parameter is required for this strategy", anno);
+        }
+        ClassNode builder = createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), parameters.length);
+        List<FieldNode> convertedFields = convertParamsToFields(builder, parameters);
+
+        buildCommon(buildee, anno, convertedFields, builder);
+        if (mNode instanceof ConstructorNode) {
+            createBuildeeConstructors(transform, buildee, builder, convertedFields, false, useSetters);
+        } else {
+            createBuildeeMethods(buildee, mNode, builder, convertedFields);
+        }
+    }
+
+    private static String getBuilderClassName(ClassNode buildee, AnnotationNode anno) {
+        return getMemberStringValue(anno, "builderClassName", buildee.getNameWithoutPackage() + "Initializer");
+    }
+
+    private static void addFields(ClassNode buildee, List<FieldNode> filteredFields, ClassNode builder) {
+        for (FieldNode filteredField : filteredFields) {
+            builder.addField(createFieldCopy(buildee, filteredField));
+        }
+    }
+
+    private void buildCommon(ClassNode buildee, AnnotationNode anno, List<FieldNode> fieldNodes, ClassNode builder) {
+        String prefix = getMemberStringValue(anno, "prefix", "");
+        String buildMethodName = getMemberStringValue(anno, "buildMethodName", "create");
+        createBuilderConstructors(builder, buildee, fieldNodes);
+        buildee.getModule().addClass(builder);
+        String builderMethodName = getMemberStringValue(anno, "builderMethodName", "createInitializer");
+        buildee.addMethod(createBuilderMethod(buildMethodName, builder, fieldNodes.size(), builderMethodName));
+        for (int i = 0; i < fieldNodes.size(); i++) {
+            builder.addMethod(createBuilderMethodForField(builder, fieldNodes, prefix, i));
+        }
+        builder.addMethod(createBuildMethod(builder, buildMethodName, fieldNodes));
+    }
+
+    private static List<FieldNode> convertParamsToFields(ClassNode builder, Parameter[] parameters) {
+        List<FieldNode> fieldNodes = new ArrayList<FieldNode>();
+        for(Parameter parameter: parameters) {
+            Map<String,ClassNode> genericsSpec = createGenericsSpec(builder);
+            ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, parameter.getType());
+            FieldNode fieldNode = new FieldNode(parameter.getName(), parameter.getModifiers(), correctedType, builder, DEFAULT_INITIAL_VALUE);
+            fieldNodes.add(fieldNode);
+            builder.addField(fieldNode);
+        }
+        return fieldNodes;
+    }
+
+    private static ClassNode createInnerHelperClass(ClassNode buildee, String builderClassName, int fieldsSize) {
+        final String fullName = buildee.getName() + "$" + builderClassName;
+        ClassNode builder = new InnerClassNode(buildee, fullName, PUBLIC_STATIC, OBJECT_TYPE);
+        GenericsType[] gtypes = new GenericsType[fieldsSize];
+        for (int i = 0; i < gtypes.length; i++) {
+            gtypes[i] = makePlaceholder(i);
+        }
+        builder.setGenericsTypes(gtypes);
+        return builder;
+    }
+
+    private static MethodNode createBuilderMethod(String buildMethodName, ClassNode builder, int numFields, String builderMethodName) {
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(returnS(callX(builder, buildMethodName)));
+        ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(numFields));
+        return new MethodNode(builderMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
+    }
+
+    private static GenericsType[] unsetGenTypes(int numFields) {
+        GenericsType[] gtypes = new GenericsType[numFields];
+        for (int i = 0; i < gtypes.length; i++) {
+            gtypes[i] = new GenericsType(ClassHelper.make(UNSET.class));
+        }
+        return gtypes;
+    }
+
+    private static GenericsType[] setGenTypes(int numFields) {
+        GenericsType[] gtypes = new GenericsType[numFields];
+        for (int i = 0; i < gtypes.length; i++) {
+            gtypes[i] = new GenericsType(ClassHelper.make(SET.class));
+        }
+        return gtypes;
+    }
+
+    private static void createBuilderConstructors(ClassNode builder, ClassNode buildee, List<FieldNode> fields) {
+        builder.addConstructor(ACC_PRIVATE, NO_PARAMS, NO_EXCEPTIONS, block(ctorSuperS()));
+        final BlockStatement body = new BlockStatement();
+        body.addStatement(ctorSuperS());
+        initializeFields(fields, body, false);
+        builder.addConstructor(ACC_PRIVATE, getParams(fields, buildee), NO_EXCEPTIONS, body);
+    }
+
+    private static void createBuildeeConstructors(BuilderASTTransformation transform, ClassNode buildee, ClassNode builder, List<FieldNode> fields, boolean needsConstructor, boolean useSetters) {
+        ConstructorNode initializer = createInitializerConstructor(buildee, builder, fields);
+        if (transform.hasAnnotation(buildee, ImmutableASTTransformation.MY_TYPE)) {
+            initializer.putNodeMetaData(ImmutableASTTransformation.IMMUTABLE_SAFE_FLAG, Boolean.TRUE);
+        } else if (needsConstructor) {
+            final BlockStatement body = new BlockStatement();
+            body.addStatement(ctorSuperS());
+            initializeFields(fields, body, useSetters);
+            buildee.addConstructor(ACC_PRIVATE | ACC_SYNTHETIC, getParams(fields, buildee), NO_EXCEPTIONS, body);
+        }
+    }
+
+    private static void createBuildeeMethods(ClassNode buildee, MethodNode mNode, ClassNode builder, List<FieldNode> fields) {
+        ClassNode paramType = makeClassSafeWithGenerics(builder, setGenTypes(fields.size()));
+        List<Expression> argsList = new ArrayList<Expression>();
+        Parameter initParam = param(paramType, "initializer");
+        for (FieldNode fieldNode : fields) {
+            argsList.add(propX(varX(initParam), fieldNode.getName()));
+        }
+        String newName = "$" + mNode.getName(); // can't have private and public methods of the same name, so rename original
+        buildee.addMethod(mNode.getName(), PUBLIC_STATIC, mNode.getReturnType(), params(param(paramType, "initializer")), NO_EXCEPTIONS,
+                block(stmt(callX(buildee, newName, args(argsList)))));
+        renameMethod(buildee, mNode, newName);
+    }
+
+    // no rename so delete and add
+    private static void renameMethod(ClassNode buildee, MethodNode mNode, String newName) {
+        buildee.addMethod(newName, mNode.getModifiers(), mNode.getReturnType(), mNode.getParameters(), mNode.getExceptions(), mNode.getCode());
+        buildee.removeMethod(mNode);
+    }
+
+    private static Parameter[] getParams(List<FieldNode> fields, ClassNode cNode) {
+        Parameter[] parameters = new Parameter[fields.size()];
+        for (int i = 0; i < parameters.length; i++) {
+            FieldNode fNode = fields.get(i);
+            Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
+            extractSuperClassGenerics(fNode.getType(), cNode, genericsSpec);
+            ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
+            parameters[i] = new Parameter(correctedType, fNode.getName());
+        }
+        return parameters;
+    }
+
+    private static ConstructorNode createInitializerConstructor(ClassNode buildee, ClassNode builder, List<FieldNode> fields) {
+        ClassNode paramType = makeClassSafeWithGenerics(builder, setGenTypes(fields.size()));
+        List<Expression> argsList = new ArrayList<Expression>();
+        Parameter initParam = param(paramType, "initializer");
+        for (FieldNode fieldNode : fields) {
+            argsList.add(propX(varX(initParam), fieldNode.getName()));
+        }
+        return buildee.addConstructor(ACC_PUBLIC, params(param(paramType, "initializer")), NO_EXCEPTIONS, block(ctorThisS(args(argsList))));
+    }
+
+    private static MethodNode createBuildMethod(ClassNode builder, String buildMethodName, List<FieldNode> fields) {
+        ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(fields.size()));
+        return new MethodNode(buildMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, block(returnS(ctorX(returnType))));
+    }
+
+    private MethodNode createBuilderMethodForField(ClassNode builder, List<FieldNode> fields, String prefix, int fieldPos) {
+        String fieldName = fields.get(fieldPos).getName();
+        String setterName = getSetterName(prefix, fieldName);
+        GenericsType[] gtypes = new GenericsType[fields.size()];
+        List<Expression> argList = new ArrayList<Expression>();
+        for (int i = 0; i < fields.size(); i++) {
+            gtypes[i] = i == fieldPos ? new GenericsType(ClassHelper.make(SET.class)) : makePlaceholder(i);
+            argList.add(i == fieldPos ? propX(varX("this"), constX(fieldName)) : varX(fields.get(i).getName()));
+        }
+        ClassNode returnType = makeClassSafeWithGenerics(builder, gtypes);
+        FieldNode fNode = fields.get(fieldPos);
+        Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
+        extractSuperClassGenerics(fNode.getType(), builder, genericsSpec);
+        ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
+        return new MethodNode(setterName, ACC_PUBLIC, returnType, params(param(correctedType, fieldName)), NO_EXCEPTIONS, block(
+                stmt(assignX(propX(varX("this"), constX(fieldName)), varX(fieldName, correctedType))),
+                returnS(ctorX(returnType, args(argList)))
+        ));
+    }
+
+    private static GenericsType makePlaceholder(int i) {
+        ClassNode type = ClassHelper.makeWithoutCaching("T" + i);
+        type.setRedirect(OBJECT_TYPE);
+        type.setGenericsPlaceHolder(true);
+        return new GenericsType(type);
+    }
+
+    private static FieldNode createFieldCopy(ClassNode buildee, FieldNode fNode) {
+        Map<String,ClassNode> genericsSpec = createGenericsSpec(fNode.getDeclaringClass());
+        extractSuperClassGenerics(fNode.getType(), buildee, genericsSpec);
+        ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, fNode.getType());
+        return new FieldNode(fNode.getName(), fNode.getModifiers(), correctedType, buildee, DEFAULT_INITIAL_VALUE);
+    }
+
+    private static List<FieldNode> filterFields(List<FieldNode> fieldNodes, List<String> includes, List<String> excludes, boolean allNames) {
+        List<FieldNode> fields = new ArrayList<FieldNode>();
+        for (FieldNode fNode : fieldNodes) {
+            if (AbstractASTTransformation.shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames)) continue;
+            fields.add(fNode);
+        }
+        return fields;
+    }
+
+    private static void initializeFields(List<FieldNode> fields, BlockStatement body, boolean useSetters) {
+        for (FieldNode field : fields) {
+            String name = field.getName();
+            body.addStatement(
+                    stmt(useSetters && !field.isFinal()
+                                    ? callThisX(getSetterName(name), varX(param(field.getType(), name)))
+                                    : assignX(propX(varX("this"), field.getName()), varX(param(field.getType(), name)))
+                    )
+            );
+        }
+    }
+
+    private static String getSetterName(String name) {
+        return "set" + Verifier.capitalize(name);
+    }
+}


[04/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/DelegatingScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/DelegatingScript.java b/src/main/groovy/util/DelegatingScript.java
deleted file mode 100644
index 959c8e8..0000000
--- a/src/main/groovy/util/DelegatingScript.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyObject;
-import groovy.lang.MetaClass;
-import groovy.lang.MissingMethodException;
-import groovy.lang.MissingPropertyException;
-import groovy.lang.Script;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * {@link Script} that performs method invocations and property access like {@link groovy.lang.Closure} does.
- *
- * <p>
- * {@link DelegatingScript} is a convenient basis for loading a custom-defined DSL as a {@link Script}, then execute it.
- * The following sample code illustrates how to do it:
- *
- * <pre>
- * class MyDSL {
- *     public void foo(int x, int y, Closure z) { ... }
- *     public void setBar(String a) { ... }
- * }
- *
- * CompilerConfiguration cc = new CompilerConfiguration();
- * cc.setScriptBaseClass(DelegatingScript.class.getName());
- * GroovyShell sh = new GroovyShell(cl,new Binding(),cc);
- * DelegatingScript script = (DelegatingScript)sh.parse(new File("my.dsl"))
- * script.setDelegate(new MyDSL());
- * script.run();
- * </pre>
- *
- * <p>
- * <tt>my.dsl</tt> can look like this:
- *
- * <pre>
- * foo(1,2) {
- *     ....
- * }
- * bar = ...;
- * </pre>
- *
- * <p>
- * {@link DelegatingScript} does this by delegating property access and method invocation to the <tt>delegate</tt> object.
- *
- * <p>
- * More formally speaking, given the following script:
- *
- * <pre>
- * a = 1;
- * b(2);
- * </pre>
- *
- * <p>
- * Using {@link DelegatingScript} as the base class, the code will run as:
- *
- * <pre>
- * delegate.a = 1;
- * delegate.b(2);
- * </pre>
- *
- * ... whereas in plain {@link Script}, this will be run as:
- *
- * <pre>
- * binding.setProperty("a",1);
- * ((Closure)binding.getProperty("b")).call(2);
- * </pre>
- *
- * @author Kohsuke Kawaguchi
- */
-public abstract class DelegatingScript extends Script {
-    private Object delegate;
-    private MetaClass metaClass;
-
-    protected DelegatingScript() {
-        super();
-    }
-
-    protected DelegatingScript(Binding binding) {
-        super(binding);
-    }
-
-    /**
-     * Sets the delegation target.
-     */
-    public void setDelegate(Object delegate) {
-        this.delegate = delegate;
-        this.metaClass = InvokerHelper.getMetaClass(delegate.getClass());
-    }
-
-    @Override
-    public Object invokeMethod(String name, Object args) {
-        try {
-            if (delegate instanceof GroovyObject) {
-                return ((GroovyObject) delegate).invokeMethod(name, args);
-            }
-            return metaClass.invokeMethod(delegate, name, args);
-        } catch (MissingMethodException mme) {
-            return super.invokeMethod(name, args);
-        }
-    }
-
-    @Override
-    public Object getProperty(String property) {
-        try {
-            return metaClass.getProperty(delegate,property);
-        } catch (MissingPropertyException e) {
-            return super.getProperty(property);
-        }
-    }
-
-    @Override
-    public void setProperty(String property, Object newValue) {
-        try {
-            metaClass.setProperty(delegate,property,newValue);
-        } catch (MissingPropertyException e) {
-            super.setProperty(property,newValue);
-        }
-    }
-
-    public Object getDelegate() {
-        return delegate;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Eval.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Eval.java b/src/main/groovy/util/Eval.java
deleted file mode 100644
index 87f9295..0000000
--- a/src/main/groovy/util/Eval.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyShell;
-import org.codehaus.groovy.control.CompilationFailedException;
-
-/**
- * Allow easy integration from Groovy into Java through convenience methods.
- * <p>
- * This class is a simple helper on top of GroovyShell. You can use it to evaluate small
- * Groovy scripts that don't need large Binding objects. For example, this script 
- * executes with no errors: 
- * <pre class="groovyTestCase">
- * assert Eval.me(' 2 * 4 + 2') == 10
- * assert Eval.x(2, ' x * 4 + 2') == 10
- * </pre>
- * 
- * @see GroovyShell
- * @author Dierk Koenig
- */
-
-public class Eval {
-    /**
-     * Evaluates the specified String expression and returns the result. For example: 
-     * <pre class="groovyTestCase">
-     * assert Eval.me(' 2 * 4 + 2') == 10
-     * </pre>
-     * @param expression the Groovy expression to evaluate
-     * @return the result of the expression
-     * @throws CompilationFailedException if expression is not valid Groovy
-     */
-    public static Object me(final String expression) throws CompilationFailedException {
-        return me(null, null, expression);
-    }
-
-    /**
-     * Evaluates the specified String expression and makes the parameter available inside
-     * the script, returning the result. For example, this code binds the 'x' variable: 
-     * <pre class="groovyTestCase">
-     * assert Eval.me('x', 2, ' x * 4 + 2') == 10
-     * </pre>
-     * @param expression the Groovy expression to evaluate
-     * @return the result of the expression
-     * @throws CompilationFailedException if expression is not valid Groovy
-     */
-    public static Object me(final String symbol, final Object object, final String expression) throws CompilationFailedException {
-        Binding b = new Binding();
-        b.setVariable(symbol, object);
-        GroovyShell sh = new GroovyShell(b);
-        return sh.evaluate(expression);
-    }
-
-    /**
-     * Evaluates the specified String expression and makes the parameter available inside
-     * the script bound to a variable named 'x', returning the result. For example, this 
-     * code executes without failure: 
-     * <pre class="groovyTestCase">
-     * assert Eval.x(2, ' x * 4 + 2') == 10
-     * </pre>
-     * @param expression the Groovy expression to evaluate
-     * @return the result of the expression
-     * @throws CompilationFailedException if expression is not valid Groovy
-     */
-    public static Object x(final Object x, final String expression) throws CompilationFailedException {
-        return me("x", x, expression);
-    }
-
-    /**
-     * Evaluates the specified String expression and makes the first two parameters available inside
-     * the script bound to variables named 'x' and 'y' respectively, returning the result. For example, 
-     * this code executes without failure: 
-     * <pre class="groovyTestCase">
-     * assert Eval.xy(2, 4, ' x * y + 2') == 10
-     * </pre>
-     * @param expression the Groovy expression to evaluate
-     * @return the result of the expression
-     * @throws CompilationFailedException if expression is not valid Groovy
-     */
-    public static Object xy(final Object x, final Object y, final String expression) throws CompilationFailedException {
-        Binding b = new Binding();
-        b.setVariable("x", x);
-        b.setVariable("y", y);
-        GroovyShell sh = new GroovyShell(b);
-        return sh.evaluate(expression);
-    }
-
-    /**
-     * Evaluates the specified String expression and makes the first three parameters available inside
-     * the script bound to variables named 'x', 'y', and 'z' respectively, returning the result. For 
-     * example, this code executes without failure: 
-     * <pre class="groovyTestCase">
-     * assert Eval.xyz(2, 4, 2, ' x * y + z') == 10
-     * </pre>
-     * @param expression the Groovy expression to evaluate
-     * @return the result of the expression
-     * @throws CompilationFailedException if expression is not valid Groovy
-     */
-    public static Object xyz(final Object x, final Object y, final Object z, final String expression) throws CompilationFailedException {
-        Binding b = new Binding();
-        b.setVariable("x", x);
-        b.setVariable("y", y);
-        b.setVariable("z", z);
-        GroovyShell sh = new GroovyShell(b);
-        return sh.evaluate(expression);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Expando.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Expando.java b/src/main/groovy/util/Expando.java
deleted file mode 100644
index f009551..0000000
--- a/src/main/groovy/util/Expando.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.MetaExpandoProperty;
-import groovy.lang.MissingPropertyException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-
-/**
- * Represents a dynamically expandable bean.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Hein Meling
- * @author Pilho Kim
- */
-public class Expando extends GroovyObjectSupport {
-
-    private Map expandoProperties;
-
-    public Expando() {
-    }
-
-    public Expando(Map expandoProperties) {
-        this.expandoProperties = expandoProperties;
-    }
-
-    /**
-     * @return the dynamically expanded properties
-     */
-    public Map getProperties() {
-        if (expandoProperties == null) {
-            expandoProperties = createMap();
-        }
-        return expandoProperties;
-    }
-
-    public List getMetaPropertyValues() {
-        // run through all our current properties and create MetaProperty objects
-        List ret = new ArrayList();
-        for (Object o : getProperties().entrySet()) {
-            Entry entry = (Entry) o;
-            ret.add(new MetaExpandoProperty(entry));
-        }
-
-        return ret;
-    }
-
-    public Object getProperty(String property) {
-        // always use the expando properties first
-        Object result = getProperties().get(property);
-        if (result != null) return result;
-        try {
-            return super.getProperty(property);
-        }
-        catch (MissingPropertyException e) {
-            // IGNORE
-        }
-        return null;
-    }
-
-    public void setProperty(String property, Object newValue) {
-        // always use the expando properties
-        getProperties().put(property, newValue);
-    }
-
-    public Object invokeMethod(String name, Object args) {
-        try {
-            return super.invokeMethod(name, args);
-        }
-        catch (GroovyRuntimeException e) {
-            // br should get a "native" property match first. getProperty includes such fall-back logic
-            Object value = this.getProperty(name);
-            if (value instanceof Closure) {
-                Closure closure = (Closure) value;
-                closure = (Closure) closure.clone();
-                closure.setDelegate(this);
-                return closure.call((Object[]) args);
-            } else {
-                throw e;
-            }
-        }
-
-    }
-
-    /**
-     * This allows toString to be overridden by a closure <i>field</i> method attached
-     * to the expando object.
-     *
-     * @see java.lang.Object#toString()
-     */
-    public String toString() {
-        Object method = getProperties().get("toString");
-        if (method != null && method instanceof Closure) {
-            // invoke overridden toString closure method
-            Closure closure = (Closure) method;
-            closure.setDelegate(this);
-            return closure.call().toString();
-        } else {
-            return expandoProperties.toString();
-        }
-    }
-
-    /**
-     * This allows equals to be overridden by a closure <i>field</i> method attached
-     * to the expando object.
-     *
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object obj) {
-        Object method = getProperties().get("equals");
-        if (method != null && method instanceof Closure) {
-            // invoke overridden equals closure method
-            Closure closure = (Closure) method;
-            closure.setDelegate(this);
-            Boolean ret = (Boolean) closure.call(obj);
-            return ret.booleanValue();
-        } else {
-            return super.equals(obj);
-        }
-    }
-
-    /**
-     * This allows hashCode to be overridden by a closure <i>field</i> method attached
-     * to the expando object.
-     *
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        Object method = getProperties().get("hashCode");
-        if (method != null && method instanceof Closure) {
-            // invoke overridden hashCode closure method
-            Closure closure = (Closure) method;
-            closure.setDelegate(this);
-            Integer ret = (Integer) closure.call();
-            return ret.intValue();
-        } else {
-            return super.hashCode();
-        }
-    }
-
-    /**
-     * Factory method to create a new Map used to store the expando properties map
-     *
-     * @return a newly created Map implementation
-     */
-    protected Map createMap() {
-        return new HashMap();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Factory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Factory.java b/src/main/groovy/util/Factory.java
deleted file mode 100644
index 8ab85b4..0000000
--- a/src/main/groovy/util/Factory.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- * @author Danno Ferrin
- */
-public interface Factory {
-    /**
-     *
-     * @return true if no child closures should be processed
-     */
-    boolean isLeaf();
-
-    /**
-     * Does this factory "Own" it's child closure.
-     *
-     * @return true  if the factory should have onContentClosure() called,
-     *         false if the builder should handle it
-     */
-    boolean isHandlesNodeChildren();
-
-    /**
-     * Called when a factory is registered to a builder
-     * @param builder the build the factory has been registered to
-     * @param registeredName the name the factory has been registered under
-     */
-    void onFactoryRegistration(FactoryBuilderSupport builder, String registeredName, String registeredGroupName);
-
-    /**
-     * @param builder the FactoryBuilder
-     * @param name the name of the node being built
-     * @param value the 'value' argument in the build node
-     * @param attributes the attributes of the build arg
-     * @return the object created for the builder
-     * @throws InstantiationException if attempting to instantiate an interface or abstract class
-     * @throws IllegalAccessException if the instance can't be created due to a security violation
-     */
-    Object newInstance( FactoryBuilderSupport builder, Object name, Object value, Map attributes )
-            throws InstantiationException, IllegalAccessException;
-
-    /**
-     * @param builder the FactoryBuilder
-     * @param node the node (returned from newINstance) to consider the attributes for
-     * @param attributes the attributes, a mutable set
-     * @return true if the factory builder should use standard bean property matching for the remaining attributes
-     */
-    boolean onHandleNodeAttributes( FactoryBuilderSupport builder, Object node, Map attributes );
-
-    /**
-     * Only called if it isLeaf is false and isHandlesNodeChildren is true
-     * @param builder the FactoryBuilder
-     * @param node the node (returned from newINstance) to consider the attributes for
-     * @param childContent the child content closure of the builder
-     * @return true if the factory builder should apply default node processing to the content child
-     */
-    boolean onNodeChildren( FactoryBuilderSupport builder, Object node, Closure childContent);
-
-    /**
-     * @param builder the FactoryBuilder
-     * @param parent the parent node (null if 'root')
-     * @param node the node just completed
-     */
-    void onNodeCompleted( FactoryBuilderSupport builder, Object parent, Object node );
-
-    void setParent( FactoryBuilderSupport builder, Object parent, Object child );
-
-    void setChild( FactoryBuilderSupport builder, Object parent, Object child );
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FactoryBuilderSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FactoryBuilderSupport.java b/src/main/groovy/util/FactoryBuilderSupport.java
deleted file mode 100644
index 8dbcff0..0000000
--- a/src/main/groovy/util/FactoryBuilderSupport.java
+++ /dev/null
@@ -1,1363 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.Closure;
-import groovy.lang.DelegatingMetaClass;
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.MetaClass;
-import groovy.lang.MissingMethodException;
-import groovy.lang.MissingPropertyException;
-import groovy.lang.Reference;
-import groovy.lang.Script;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Mix of BuilderSupport and SwingBuilder's factory support.
- *
- * Warning: this implementation is not thread safe and should not be used
- * across threads in a multi-threaded environment.  A locking mechanism
- * should be implemented by the subclass if use is expected across
- * multiple threads.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- * @author Danno Ferrin
- */
-public abstract class FactoryBuilderSupport extends Binding {
-    public static final String CURRENT_FACTORY = "_CURRENT_FACTORY_";
-    public static final String PARENT_FACTORY = "_PARENT_FACTORY_";
-    public static final String PARENT_NODE = "_PARENT_NODE_";
-    public static final String CURRENT_NODE = "_CURRENT_NODE_";
-    public static final String PARENT_CONTEXT = "_PARENT_CONTEXT_";
-    public static final String PARENT_NAME = "_PARENT_NAME_";
-    public static final String CURRENT_NAME = "_CURRENT_NAME_";
-    public static final String OWNER = "owner";
-    public static final String PARENT_BUILDER = "_PARENT_BUILDER_";
-    public static final String CURRENT_BUILDER = "_CURRENT_BUILDER_";
-    public static final String CHILD_BUILDER = "_CHILD_BUILDER_";
-    public static final String SCRIPT_CLASS_NAME = "_SCRIPT_CLASS_NAME_";
-    private static final Logger LOG = Logger.getLogger(FactoryBuilderSupport.class.getName());
-    private static final Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() {
-        public int compare(final Method o1, final Method o2) {
-            int cmp = o1.getName().compareTo(o2.getName());
-            if (cmp != 0) return cmp;
-            cmp = o1.getParameterTypes().length - o2.getParameterTypes().length;
-            return cmp;
-        }
-    };
-
-    /**
-     * Throws an exception if value is null.
-     *
-     * @param value the node's value
-     * @param name  the node's name
-     */
-    public static void checkValueIsNull(Object value, Object name) {
-        if (value != null) {
-            throw new RuntimeException("'" + name + "' elements do not accept a value argument.");
-        }
-    }
-
-    /**
-     * Checks type of value against builder type
-     *
-     * @param value the node's value
-     * @param name  the node's name
-     * @param type  a Class that may be assignable to the value's class
-     * @return true if type is assignable to the value's class, false if value
-     *         is null.
-     */
-    public static boolean checkValueIsType(Object value, Object name, Class type) {
-        if (value != null) {
-            if (type.isAssignableFrom(value.getClass())) {
-                return true;
-            } else {
-                throw new RuntimeException("The value argument of '" + name + "' must be of type "
-                        + type.getName() + ". Found: " + value.getClass());
-            }
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Checks values against factory's type
-     *
-     * @param value the node's value
-     * @param name  the node's name
-     * @param type  a Class that may be assignable to the value's class
-     * @return Returns true if type is assignable to the value's class, false if value is
-     *         null or a String.
-     */
-    public static boolean checkValueIsTypeNotString(Object value, Object name, Class type) {
-        if (value != null) {
-            if (type.isAssignableFrom(value.getClass())) {
-                return true;
-            } else if (value instanceof String) {
-                return false;
-            } else {
-                throw new RuntimeException("The value argument of '" + name + "' must be of type "
-                        + type.getName() + " or a String. Found: " + value.getClass());
-            }
-        } else {
-            return false;
-        }
-    }
-
-    private final ThreadLocal<LinkedList<Map<String, Object>>> contexts = new ThreadLocal<LinkedList<Map<String, Object>>>();
-    protected LinkedList<Closure> attributeDelegates = new LinkedList<Closure>(); //
-    private final List<Closure> disposalClosures = new ArrayList<Closure>(); // because of reverse iteration use ArrayList
-    private final Map<String, Factory> factories = new HashMap<String, Factory>();
-    private Closure nameMappingClosure;
-    private final ThreadLocal<FactoryBuilderSupport> localProxyBuilder = new ThreadLocal<FactoryBuilderSupport>();
-    private FactoryBuilderSupport globalProxyBuilder;
-    protected LinkedList<Closure> preInstantiateDelegates = new LinkedList<Closure>();
-    protected LinkedList<Closure> postInstantiateDelegates = new LinkedList<Closure>();
-    protected LinkedList<Closure> postNodeCompletionDelegates = new LinkedList<Closure>();
-    protected Closure methodMissingDelegate;
-    protected Closure propertyMissingDelegate;
-    protected Map<String, Closure[]> explicitProperties = new HashMap<String, Closure[]>();
-    protected Map<String, Closure> explicitMethods = new HashMap<String, Closure>();
-    protected Map<String, Set<String>> registrationGroup = new HashMap<String, Set<String>>();
-    protected String registrationGroupName = ""; // use binding to store?
-
-    protected boolean autoRegistrationRunning = false;
-    protected boolean autoRegistrationComplete = false;
-
-    public FactoryBuilderSupport() {
-        this(false);
-    }
-
-    public FactoryBuilderSupport(boolean init) {
-        globalProxyBuilder = this;
-        registrationGroup.put(registrationGroupName, new TreeSet<String>());
-        if (init) {
-            autoRegisterNodes();
-        }
-    }
-
-    private Set<String> getRegistrationGroup(String name) {
-        Set<String> group = registrationGroup.get(name);
-        if (group == null ) {
-            group = new TreeSet<String>();
-            registrationGroup.put(name, group);
-        }
-        return group;
-    }
-
-    /**
-     * Ask the nodes to be registered
-     */
-    public void autoRegisterNodes() {
-        // if java did atomic blocks, this would be one
-        synchronized (this) {
-            if (autoRegistrationRunning || autoRegistrationComplete) {
-                // registration already done or in process, abort
-                return;
-            }
-        }
-        autoRegistrationRunning = true;
-        try {
-            callAutoRegisterMethods(getClass());
-        } finally {
-            autoRegistrationComplete = true;
-            autoRegistrationRunning = false;
-        }
-    }
-
-    private void callAutoRegisterMethods(Class declaredClass) {
-        if (declaredClass == null) {
-            return;
-        }
-        callAutoRegisterMethods(declaredClass.getSuperclass());
-
-        Method[] declaredMethods = declaredClass.getDeclaredMethods();
-        Arrays.sort(declaredMethods, METHOD_COMPARATOR);
-        for (Method method : declaredMethods) {
-            if (method.getName().startsWith("register") && method.getParameterTypes().length == 0) {
-                registrationGroupName = method.getName().substring("register".length());
-                registrationGroup.put(registrationGroupName, new TreeSet<String>());
-                try {
-                    if (Modifier.isPublic(method.getModifiers())) {
-                        method.invoke(this);
-                    }
-                } catch (IllegalAccessException e) {
-                    throw new RuntimeException("Could not init " + getClass().getName() + " because of an access error in " + declaredClass.getName() + "." + method.getName(), e);
-                } catch (InvocationTargetException e) {
-                    throw new RuntimeException("Could not init " + getClass().getName() + " because of an exception in " + declaredClass.getName() + "." + method.getName(), e);
-                } finally {
-                    registrationGroupName = "";
-                }
-            }
-        }
-    }
-
-    /**
-     * @param name the name of the variable to lookup
-     * @return the variable value
-     */
-    public Object getVariable(String name) {
-        try {
-            return getProxyBuilder().doGetVariable(name);
-        } catch(MissingPropertyException mpe) {
-            if(mpe.getProperty().equals(name) && propertyMissingDelegate != null) {
-                return propertyMissingDelegate.call(new Object[]{name});
-            }
-            throw mpe;
-        }
-    }
-
-    private Object doGetVariable(String name) {
-        return super.getVariable(name);
-    }
-
-    /**
-     * Sets the value of the given variable
-     *
-     * @param name  the name of the variable to set
-     * @param value the new value for the given variable
-     */
-    public void setVariable(String name, Object value) {
-        getProxyBuilder().doSetVariable(name, value);
-    }
-
-    private void doSetVariable(String name, Object value) {
-        super.setVariable(name, value);
-    }
-
-    public Map getVariables() {
-        return getProxyBuilder().doGetVariables();
-    }
-
-    private Map doGetVariables() {
-        return super.getVariables();
-    }
-
-    /**
-     * Overloaded to make variables appear as bean properties or via the subscript operator
-     */
-    public Object getProperty(String property) {
-        try {
-            return getProxyBuilder().doGetProperty(property);
-        } catch (MissingPropertyException mpe) {
-            if ((getContext() != null) && (getContext().containsKey(property))) {
-                return getContext().get(property);
-            } else {
-                try {
-                    return getMetaClass().getProperty(this, property);
-                } catch(MissingPropertyException mpe2) {
-                    if(mpe2.getProperty().equals(property) && propertyMissingDelegate != null) {
-                        return propertyMissingDelegate.call(new Object[]{property});
-                    }
-                    throw mpe2;
-                }
-            }
-        }
-    }
-
-    private Object doGetProperty(String property) {
-        Closure[] accessors = resolveExplicitProperty(property);
-        if (accessors != null) {
-            if (accessors[0] == null) {
-                // write only property
-                throw new MissingPropertyException(property + " is declared as write only");
-            } else {
-                return accessors[0].call();
-            }
-        } else {
-            return super.getProperty(property);
-        }
-    }
-
-    /**
-     * Overloaded to make variables appear as bean properties or via the subscript operator
-     */
-    public void setProperty(String property, Object newValue) {
-        getProxyBuilder().doSetProperty(property, newValue);
-    }
-
-    private void doSetProperty(String property, Object newValue) {
-        Closure[] accessors = resolveExplicitProperty(property);
-        if (accessors != null) {
-            if (accessors[1] == null) {
-                // read only property
-                throw new MissingPropertyException(property + " is declared as read only");
-            } else {
-                accessors[1].call(newValue);
-            }
-        } else {
-            super.setProperty(property, newValue);
-        }
-    }
-
-    /**
-     * @return the factory map (Unmodifiable Map).
-     */
-    public Map<String, Factory> getFactories() {
-        return Collections.unmodifiableMap(getProxyBuilder().factories);
-    }
-
-    /**
-     * @return the explicit methods map (Unmodifiable Map).
-     */
-    public Map<String, Closure> getExplicitMethods() {
-        return Collections.unmodifiableMap(getProxyBuilder().explicitMethods);
-    }
-
-    /**
-     * @return the explicit properties map (Unmodifiable Map).
-     */
-    public Map<String, Closure[]> getExplicitProperties() {
-        return Collections.unmodifiableMap(getProxyBuilder().explicitProperties);
-    }
-
-    /**
-     * @return the factory map (Unmodifiable Map).
-     */
-    public Map<String, Factory> getLocalFactories() {
-        return Collections.unmodifiableMap(factories);
-    }
-
-    /**
-     * @return the explicit methods map (Unmodifiable Map).
-     */
-    public Map<String, Closure> getLocalExplicitMethods() {
-        return Collections.unmodifiableMap(explicitMethods);
-    }
-
-    /**
-     * @return the explicit properties map (Unmodifiable Map).
-     */
-    public Map<String, Closure[]> getLocalExplicitProperties() {
-        return Collections.unmodifiableMap(explicitProperties);
-    }
-
-    public Set<String> getRegistrationGroups() {
-        return Collections.unmodifiableSet(registrationGroup.keySet());
-    }
-
-    public Set<String> getRegistrationGroupItems(String group) {
-        Set<String> groupSet = registrationGroup.get(group);
-        if (groupSet != null) {
-            return Collections.unmodifiableSet(groupSet);
-        } else {
-            return Collections.emptySet();
-        }
-    }
-
-    public List<Closure> getAttributeDelegates() {
-        return Collections.unmodifiableList(attributeDelegates);
-    }
-
-    public List<Closure> getPreInstantiateDelegates() {
-        return Collections.unmodifiableList(preInstantiateDelegates);
-    }
-
-    public List<Closure> getPostInstantiateDelegates() {
-        return Collections.unmodifiableList(postInstantiateDelegates);
-    }
-
-    public List<Closure> getPostNodeCompletionDelegates() {
-        return Collections.unmodifiableList(postNodeCompletionDelegates);
-    }
-
-    public Closure getMethodMissingDelegate() {
-        return methodMissingDelegate;
-    }
-
-    public void setMethodMissingDelegate(Closure delegate) {
-        methodMissingDelegate = delegate;
-    }
-
-    public Closure getPropertyMissingDelegate() {
-        return propertyMissingDelegate;
-    }
-
-    public void setPropertyMissingDelegate(Closure delegate) {
-        propertyMissingDelegate = delegate;
-    }
-
-    /**
-     * @return the context of the current node.
-     */
-    public Map<String, Object> getContext() {
-        LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
-        if (contexts != null && !contexts.isEmpty()) {
-            return contexts.getFirst();
-        }
-        return null;
-    }
-
-    /**
-     * @return the current node being built.
-     */
-    public Object getCurrent() {
-        return getContextAttribute(CURRENT_NODE);
-    }
-
-    /**
-     * @return the factory that built the current node.
-     */
-    public Factory getCurrentFactory() {
-        return (Factory) getContextAttribute(CURRENT_FACTORY);
-    }
-
-    /**
-     * @return the factory of the parent of the current node.
-     */
-    public String getCurrentName() {
-        return (String) getContextAttribute(CURRENT_NAME);
-    }
-
-    /**
-     * @return the builder that built the current node.
-     */
-    public FactoryBuilderSupport getCurrentBuilder() {
-        return (FactoryBuilderSupport) getContextAttribute(CURRENT_BUILDER);
-    }
-
-    /**
-     * @return the node of the parent of the current node.
-     */
-    public Object getParentNode() {
-        return getContextAttribute(PARENT_NODE);
-    }
-
-    /**
-     * @return the factory of the parent of the current node.
-     */
-    public Factory getParentFactory() {
-        return (Factory) getContextAttribute(PARENT_FACTORY);
-    }
-
-    /**
-     * @return the context of the parent of the current node.
-     */
-    public Map getParentContext() {
-        return (Map) getContextAttribute(PARENT_CONTEXT);
-    }
-
-    /**
-     * @return the name of the parent of the current node.
-     */
-    public String getParentName() {
-        return (String) getContextAttribute(PARENT_NAME);
-    }
-
-    public FactoryBuilderSupport getChildBuilder() {
-        return (FactoryBuilderSupport) getContextAttribute(CHILD_BUILDER);
-    }
-
-    public Object getContextAttribute(String key) {
-        Map context = getContext();
-        if (context != null) {
-            return context.get(key);
-        }
-        return null;
-    }
-
-    /**
-     * Convenience method when no arguments are required
-     *
-     * @param methodName the name of the method to invoke
-     * @return the result of the call
-     */
-    public Object invokeMethod(String methodName) {
-        return getProxyBuilder().invokeMethod(methodName, null);
-    }
-
-    public Object invokeMethod(String methodName, Object args) {
-        Object name = getProxyBuilder().getName(methodName);
-        Object result;
-        Object previousContext = getProxyBuilder().getContext();
-        try {
-            result = getProxyBuilder().doInvokeMethod(methodName, name, args);
-        } catch (RuntimeException e) {
-            // remove contexts created after we started
-            if (getContexts().contains(previousContext)) {
-                Map<String, Object> context = getProxyBuilder().getContext();
-                while (context != null && context != previousContext) {
-                    getProxyBuilder().popContext();
-                    context = getProxyBuilder().getContext();
-                }
-            }
-            throw e;
-        }
-        return result;
-    }
-
-    /**
-     * Add an attribute delegate so it can intercept attributes being set.
-     * Attribute delegates are fired in a FILO pattern, so that nested delegates
-     * get first crack.
-     *
-     * @param attrDelegate the closure to be called
-     * @return attrDelegate
-     */
-    public Closure addAttributeDelegate(Closure attrDelegate) {
-        getProxyBuilder().attributeDelegates.addFirst(attrDelegate);
-        return attrDelegate;
-    }
-
-    /**
-     * Remove the most recently added instance of the attribute delegate.
-     *
-     * @param attrDelegate the instance of the closure to be removed
-     */
-    public void removeAttributeDelegate(Closure attrDelegate) {
-        getProxyBuilder().attributeDelegates.remove(attrDelegate);
-    }
-
-    /**
-     * Add a preInstantiate delegate so it can intercept nodes before they are
-     * created. PreInstantiate delegates are fired in a FILO pattern, so that
-     * nested delegates get first crack.
-     *
-     * @param delegate the closure to invoke
-     * @return delegate
-     */
-    public Closure addPreInstantiateDelegate(Closure delegate) {
-        getProxyBuilder().preInstantiateDelegates.addFirst(delegate);
-        return delegate;
-    }
-
-    /**
-     * Remove the most recently added instance of the preInstantiate delegate.
-     *
-     * @param delegate the closure to invoke
-     */
-    public void removePreInstantiateDelegate(Closure delegate) {
-        getProxyBuilder().preInstantiateDelegates.remove(delegate);
-    }
-
-    /**
-     * Add a postInstantiate delegate so it can intercept nodes after they are
-     * created. PostInstantiate delegates are fired in a FILO pattern, so that
-     * nested delegates get first crack.
-     *
-     * @param delegate the closure to invoke
-     * @return delegate
-     */
-    public Closure addPostInstantiateDelegate(Closure delegate) {
-        getProxyBuilder().postInstantiateDelegates.addFirst(delegate);
-        return delegate;
-    }
-
-    /**
-     * Remove the most recently added instance of the postInstantiate delegate.
-     *
-     * @param delegate the closure to invoke
-     */
-    public void removePostInstantiateDelegate(Closure delegate) {
-        getProxyBuilder().postInstantiateDelegates.remove(delegate);
-    }
-
-    /**
-     * Add a nodeCompletion delegate so it can intercept nodes after they done
-     * with building. NodeCompletion delegates are fired in a FILO pattern, so
-     * that nested delegates get first crack.
-     *
-     * @param delegate the closure to invoke
-     * @return delegate
-     */
-    public Closure addPostNodeCompletionDelegate(Closure delegate) {
-        getProxyBuilder().postNodeCompletionDelegates.addFirst(delegate);
-        return delegate;
-    }
-
-    /**
-     * Remove the most recently added instance of the nodeCompletion delegate.
-     *
-     * @param delegate the closure to be removed
-     */
-    public void removePostNodeCompletionDelegate(Closure delegate) {
-        getProxyBuilder().postNodeCompletionDelegates.remove(delegate);
-    }
-
-    public void registerExplicitProperty(String name, Closure getter, Closure setter) {
-        registerExplicitProperty(name, registrationGroupName, getter, setter);
-    }
-
-    public void registerExplicitProperty(String name, String groupName, Closure getter, Closure setter) {
-        // set the delegate to FBS so the closure closes over the builder
-        if (getter != null) getter.setDelegate(this);
-        if (setter != null) setter.setDelegate(this);
-        explicitProperties.put(name, new Closure[]{getter, setter});
-        String methodNameBase = MetaClassHelper.capitalize(name);
-        if (getter != null) {
-            getRegistrationGroup(groupName).add("get" + methodNameBase);
-        }
-        if (setter != null) {
-            getRegistrationGroup(groupName).add("set" + methodNameBase);
-        }
-    }
-
-    public void registerExplicitMethod(String name, Closure closure) {
-        registerExplicitMethod(name, registrationGroupName, closure);
-    }
-
-    public void registerExplicitMethod(String name, String groupName, Closure closure) {
-        // set the delegate to FBS so the closure closes over the builder
-        closure.setDelegate(this);
-        explicitMethods.put(name, closure);
-        getRegistrationGroup(groupName).add(name);
-    }
-
-    /**
-     * Registers a factory for a JavaBean.<br>
-     * The JavaBean class should have a no-args constructor.
-     *
-     * @param theName   name of the node
-     * @param beanClass the factory to handle the name
-     */
-    public void registerBeanFactory(String theName, Class beanClass) {
-        registerBeanFactory(theName, registrationGroupName, beanClass);
-    }
-
-    /**
-     * Registers a factory for a JavaBean.<br>
-     * The JavaBean class should have a no-args constructor.
-     *
-     * @param theName   name of the node
-     * @param groupName thr group to register this node in
-     * @param beanClass the factory to handle the name
-     */
-    public void registerBeanFactory(String theName, String groupName, final Class beanClass) {
-        getProxyBuilder().registerFactory(theName, new AbstractFactory() {
-            public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
-                                      Map properties) throws InstantiationException, IllegalAccessException {
-                if (checkValueIsTypeNotString(value, name, beanClass)) {
-                    return value;
-                } else {
-                    return beanClass.newInstance();
-                }
-            }
-        });
-        getRegistrationGroup(groupName).add(theName);
-    }
-
-    /**
-     * Registers a factory for a node name.
-     *
-     * @param name    the name of the node
-     * @param factory the factory to return the values
-     */
-    public void registerFactory(String name, Factory factory) {
-        registerFactory(name, registrationGroupName, factory);
-    }
-
-    /**
-     * Registers a factory for a node name.
-     *
-     * @param name      the name of the node
-     * @param groupName thr group to register this node in
-     * @param factory   the factory to return the values
-     */
-    public void registerFactory(String name, String groupName, Factory factory) {
-        getProxyBuilder().factories.put(name, factory);
-        getRegistrationGroup(groupName).add(name);
-        factory.onFactoryRegistration(this, name, groupName);
-    }
-
-    /**
-     * This method is responsible for instantiating a node and configure its
-     * properties.
-     *
-     * @param name       the name of the node
-     * @param attributes the attributes for the node
-     * @param value      the value arguments for the node
-     * @return the object return from the factory
-     */
-    protected Object createNode(Object name, Map attributes, Object value) {
-        Object node;
-
-        Factory factory = getProxyBuilder().resolveFactory(name, attributes, value);
-        if (factory == null) {
-            LOG.log(Level.WARNING, "Could not find match for name '" + name + "'");
-            throw new MissingMethodExceptionNoStack((String) name, Object.class, new Object[]{attributes, value});
-            //return null;
-        }
-        getProxyBuilder().getContext().put(CURRENT_FACTORY, factory);
-        getProxyBuilder().getContext().put(CURRENT_NAME, String.valueOf(name));
-        getProxyBuilder().preInstantiate(name, attributes, value);
-        try {
-            node = factory.newInstance(getProxyBuilder().getChildBuilder(), name, value, attributes);
-            if (node == null) {
-                LOG.log(Level.WARNING, "Factory for name '" + name + "' returned null");
-                return null;
-            }
-
-            if (LOG.isLoggable(Level.FINE)) {
-                LOG.fine("For name: " + name + " created node: " + node);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to create component for '" + name + "' reason: "
-                    + e, e);
-        }
-        getProxyBuilder().postInstantiate(name, attributes, node);
-        getProxyBuilder().handleNodeAttributes(node, attributes);
-        return node;
-    }
-
-    /**
-     * This is a hook for subclasses to plugin a custom strategy for mapping
-     * names to factories.
-     *
-     * @param name       the name of the factory
-     * @param attributes the attributes from the node
-     * @param value      value arguments from te node
-     * @return the Factory associated with name.<br>
-     */
-    protected Factory resolveFactory(Object name, Map attributes, Object value) {
-        getProxyBuilder().getContext().put(CHILD_BUILDER, getProxyBuilder());
-        return getProxyBuilder().getFactories().get(name);
-    }
-
-    /**
-     * This is a hook for subclasses to plugin a custom strategy for mapping
-     * names to explicit methods.
-     *
-     * @param methodName the name of the explicit method
-     * @param args       the arguments for the method
-     * @return the closure for the matched explicit method.<br>
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    protected Closure resolveExplicitMethod(String methodName, Object args) {
-        return getExplicitMethods().get(methodName);
-    }
-
-    /**
-     * This is a hook for subclasses to plugin a custom strategy for mapping
-     * names to property methods.
-     *
-     * @param propertyName the name of the explicit method
-     * @return the get and set closures (in that order) for the matched explicit property.<br>
-     */
-    protected Closure[] resolveExplicitProperty(String propertyName) {
-        return getExplicitProperties().get(propertyName);
-    }
-
-    /**
-     * This method is the workhorse of the builder.
-     *
-     * @param methodName the name of the method being invoked
-     * @param name       the name of the node
-     * @param args       the arguments passed into the node
-     * @return the object from the factory
-     */
-    private Object doInvokeMethod(String methodName, Object name, Object args) {
-        Reference explicitResult = new Reference();
-        if (checkExplicitMethod(methodName, args, explicitResult)) {
-            return explicitResult.get();
-        } else {
-            try {
-                return dispatchNodeCall(name, args);
-            } catch(MissingMethodException mme) {
-                if(mme.getMethod().equals(methodName) && methodMissingDelegate != null) {
-                    return methodMissingDelegate.call(new Object[]{methodName, args});
-                }
-                throw mme;
-            }
-        }
-    }
-
-    protected boolean checkExplicitMethod(String methodName, Object args, Reference result) {
-        Closure explicitMethod = resolveExplicitMethod(methodName, args);
-        if (explicitMethod != null) {
-            if (args instanceof Object[]) {
-                result.set(explicitMethod.call((Object[]) args));
-            } else {
-                //todo push through InvokerHelper.asList?
-                result.set(explicitMethod.call(args));
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Use {@link FactoryBuilderSupport#dispatchNodeCall(Object, Object)} instead.
-     */
-    @Deprecated
-    protected Object dispathNodeCall(Object name, Object args) {
-        return dispatchNodeCall(name, args);
-    }
-
-    protected Object dispatchNodeCall(Object name, Object args) {
-        Object node;
-        Closure closure = null;
-        List list = InvokerHelper.asList(args);
-
-        final boolean needToPopContext;
-        if (getProxyBuilder().getContexts().isEmpty()) {
-            // should be called on first build method only
-            getProxyBuilder().newContext();
-            needToPopContext = true;
-        } else {
-            needToPopContext = false;
-        }
-
-        try {
-            Map namedArgs = Collections.EMPTY_MAP;
-
-            // the arguments come in like [named_args?, args..., closure?]
-            // so peel off a hashmap from the front, and a closure from the
-            // end and presume that is what they meant, since there is
-            // no way to distinguish node(a:b,c,d) {..} from
-            // node([a:b],[c,d], {..}), i.e. the user can deliberately confuse
-            // the builder and there is nothing we can really do to prevent
-            // that
-
-            if ((!list.isEmpty())
-                    && (list.get(0) instanceof LinkedHashMap)) {
-                namedArgs = (Map) list.get(0);
-                list = list.subList(1, list.size());
-            }
-            if ((!list.isEmpty())
-                    && (list.get(list.size() - 1) instanceof Closure)) {
-                closure = (Closure) list.get(list.size() - 1);
-                list = list.subList(0, list.size() - 1);
-            }
-            Object arg;
-            if (list.isEmpty()) {
-                arg = null;
-            } else if (list.size() == 1) {
-                arg = list.get(0);
-            } else {
-                arg = list;
-            }
-            node = getProxyBuilder().createNode(name, namedArgs, arg);
-
-            Object current = getProxyBuilder().getCurrent();
-            if (current != null) {
-                getProxyBuilder().setParent(current, node);
-            }
-
-            if (closure != null) {
-                Factory parentFactory = getProxyBuilder().getCurrentFactory();
-                if (parentFactory.isLeaf()) {
-                    throw new RuntimeException("'" + name + "' doesn't support nesting.");
-                }
-                boolean processContent = true;
-                if (parentFactory.isHandlesNodeChildren()) {
-                    processContent = parentFactory.onNodeChildren(this, node, closure);
-                }
-                if (processContent) {
-                    // push new node on stack
-                    String parentName = getProxyBuilder().getCurrentName();
-                    Map parentContext = getProxyBuilder().getContext();
-                    getProxyBuilder().newContext();
-                    try {
-                        getProxyBuilder().getContext().put(OWNER, closure.getOwner());
-                        getProxyBuilder().getContext().put(CURRENT_NODE, node);
-                        getProxyBuilder().getContext().put(PARENT_FACTORY, parentFactory);
-                        getProxyBuilder().getContext().put(PARENT_NODE, current);
-                        getProxyBuilder().getContext().put(PARENT_CONTEXT, parentContext);
-                        getProxyBuilder().getContext().put(PARENT_NAME, parentName);
-                        getProxyBuilder().getContext().put(PARENT_BUILDER, parentContext.get(CURRENT_BUILDER));
-                        getProxyBuilder().getContext().put(CURRENT_BUILDER, parentContext.get(CHILD_BUILDER));
-                        // lets register the builder as the delegate
-                        getProxyBuilder().setClosureDelegate(closure, node);
-                        closure.call();
-                    } finally {
-                        getProxyBuilder().popContext();
-                    }
-                }
-            }
-
-            getProxyBuilder().nodeCompleted(current, node);
-            node = getProxyBuilder().postNodeCompletion(current, node);
-        } finally {
-            if (needToPopContext) {
-                // pop the first context
-                getProxyBuilder().popContext();
-            }
-        }
-        return node;
-    }
-
-    /**
-     * A hook to allow names to be converted into some other object such as a
-     * QName in XML or ObjectName in JMX.
-     *
-     * @param methodName the name of the desired method
-     * @return the object representing the name
-     */
-    public Object getName(String methodName) {
-        if (getProxyBuilder().nameMappingClosure != null) {
-            return getProxyBuilder().nameMappingClosure.call(methodName);
-        }
-        return methodName;
-    }
-
-    /**
-     * Proxy builders are useful for changing the building context, thus
-     * enabling mix &amp; match builders.
-     *
-     * @return the current builder that serves as a proxy.<br>
-     */
-    protected FactoryBuilderSupport getProxyBuilder() {
-        FactoryBuilderSupport proxy = localProxyBuilder.get();
-        if (proxy == null) {
-            return globalProxyBuilder;
-        } else {
-            return proxy;
-        }
-    }
-
-    /**
-     * Sets the builder to be used as a proxy.
-     *
-     * @param proxyBuilder the new proxy
-     */
-    protected void setProxyBuilder(FactoryBuilderSupport proxyBuilder) {
-        globalProxyBuilder = proxyBuilder;
-    }
-
-    public Closure getNameMappingClosure() {
-        return nameMappingClosure;
-    }
-
-    public void setNameMappingClosure(Closure nameMappingClosure) {
-        this.nameMappingClosure = nameMappingClosure;
-    }
-
-    /**
-     * Assigns any existing properties to the node.<br>
-     * It will call attributeDelegates before passing control to the factory
-     * that built the node.
-     *
-     * @param node       the object returned by tne node factory
-     * @param attributes the attributes for the node
-     */
-    protected void handleNodeAttributes(Object node, Map attributes) {
-        // first, short circuit
-        if (node == null) {
-            return;
-        }
-
-        for (Closure attrDelegate : getProxyBuilder().getAttributeDelegates()) {
-            FactoryBuilderSupport builder = this;
-            if (attrDelegate.getOwner() instanceof FactoryBuilderSupport) {
-                builder = (FactoryBuilderSupport) attrDelegate.getOwner();
-            } else if (attrDelegate.getDelegate() instanceof FactoryBuilderSupport) {
-                builder = (FactoryBuilderSupport) attrDelegate.getDelegate();
-            }
-
-            attrDelegate.call(new Object[]{builder, node, attributes});
-        }
-
-        if (getProxyBuilder().getCurrentFactory().onHandleNodeAttributes(getProxyBuilder().getChildBuilder(), node, attributes)) {
-            getProxyBuilder().setNodeAttributes(node, attributes);
-        }
-    }
-
-    /**
-     * Pushes a new context on the stack.
-     */
-    protected void newContext() {
-        getContexts().addFirst(new HashMap<String, Object>());
-    }
-
-    /**
-     * A hook to allow nodes to be processed once they have had all of their
-     * children applied.
-     *
-     * @param node   the current node being processed
-     * @param parent the parent of the node being processed
-     */
-    protected void nodeCompleted(Object parent, Object node) {
-        getProxyBuilder().getCurrentFactory().onNodeCompleted(getProxyBuilder().getChildBuilder(), parent, node);
-    }
-
-    /**
-     * Removes the last context from the stack.
-     *
-     * @return the content just removed
-     */
-    protected Map<String, Object> popContext() {
-        if (!getProxyBuilder().getContexts().isEmpty()) {
-            return getProxyBuilder().getContexts().removeFirst();
-        }
-        return null;
-    }
-
-    /**
-     * A hook after the factory creates the node and before attributes are set.<br>
-     * It will call any registered postInstantiateDelegates, if you override
-     * this method be sure to call this impl somewhere in your code.
-     *
-     * @param name       the name of the node
-     * @param attributes the attributes for the node
-     * @param node       the object created by the node factory
-     */
-    protected void postInstantiate(Object name, Map attributes, Object node) {
-        for (Closure postInstantiateDelegate : getProxyBuilder().getPostInstantiateDelegates()) {
-            (postInstantiateDelegate).call(new Object[]{this, attributes, node});
-        }
-    }
-
-    /**
-     * A hook to allow nodes to be processed once they have had all of their
-     * children applied and allows the actual node object that represents the
-     * Markup element to be changed.<br>
-     * It will call any registered postNodeCompletionDelegates, if you override
-     * this method be sure to call this impl at the end of your code.
-     *
-     * @param node   the current node being processed
-     * @param parent the parent of the node being processed
-     * @return the node, possibly new, that represents the markup element
-     */
-    protected Object postNodeCompletion(Object parent, Object node) {
-        for (Closure postNodeCompletionDelegate : getProxyBuilder().getPostNodeCompletionDelegates()) {
-            (postNodeCompletionDelegate).call(new Object[]{this, parent, node});
-        }
-
-        return node;
-    }
-
-    /**
-     * A hook before the factory creates the node.<br>
-     * It will call any registered preInstantiateDelegates, if you override this
-     * method be sure to call this impl somewhere in your code.
-     *
-     * @param name       the name of the node
-     * @param attributes the attributes of the node
-     * @param value      the value argument(s) of the node
-     */
-    protected void preInstantiate(Object name, Map attributes, Object value) {
-        for (Closure preInstantiateDelegate : getProxyBuilder().getPreInstantiateDelegates()) {
-            (preInstantiateDelegate).call(new Object[]{this, attributes, value});
-        }
-    }
-
-    /**
-     * Clears the context stack.
-     */
-    protected void reset() {
-        getProxyBuilder().getContexts().clear();
-    }
-
-    /**
-     * A strategy method to allow derived builders to use builder-trees and
-     * switch in different kinds of builders. This method should call the
-     * setDelegate() method on the closure which by default passes in this but
-     * if node is-a builder we could pass that in instead (or do something wacky
-     * too)
-     *
-     * @param closure the closure on which to call setDelegate()
-     * @param node    the node value that we've just created, which could be a
-     *                builder
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    protected void setClosureDelegate(Closure closure, Object node) {
-        closure.setDelegate(this);
-    }
-
-    /**
-     * Maps attributes key/values to properties on node.
-     *
-     * @param node       the object from the node
-     * @param attributes the attributes to be set
-     */
-    protected void setNodeAttributes(Object node, Map attributes) {
-        // set the properties
-        //noinspection unchecked
-        for (Map.Entry entry : (Set<Map.Entry>) attributes.entrySet()) {
-            String property = entry.getKey().toString();
-            Object value = entry.getValue();
-            InvokerHelper.setProperty(node, property, value);
-        }
-    }
-
-    /**
-     * Strategy method to establish parent/child relationships.
-     *
-     * @param parent the object from the parent node
-     * @param child  the object from the child node
-     */
-    protected void setParent(Object parent, Object child) {
-        getProxyBuilder().getCurrentFactory().setParent(getProxyBuilder().getChildBuilder(), parent, child);
-        Factory parentFactory = getProxyBuilder().getParentFactory();
-        if (parentFactory != null) {
-            parentFactory.setChild(getProxyBuilder().getCurrentBuilder(), parent, child);
-        }
-    }
-
-    /**
-     * @return the stack of available contexts.
-     */
-    protected LinkedList<Map<String, Object>> getContexts() {
-        LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
-        if (contexts == null) {
-            contexts = new LinkedList<Map<String, Object>>();
-            getProxyBuilder().contexts.set(contexts);
-        }
-        return contexts;
-    }
-
-    /**
-     * Stores the thread local states in a Map that can be passed across threads
-     * @return the map
-     */
-    protected Map<String, Object> getContinuationData() {
-        Map<String, Object> data = new HashMap<String, Object>();
-        data.put("proxyBuilder", localProxyBuilder.get());
-        data.put("contexts", contexts.get());
-        return data;
-    }
-
-    /**
-     * Restores the state of the current builder to the same state as an older build.
-     * 
-     * Caution, this will destroy rather than merge the current build context if there is any,
-     * @param data the data retrieved from a compatible getContinuationData call
-     */
-    protected void restoreFromContinuationData(Map<String, Object> data) {
-        //noinspection unchecked
-        localProxyBuilder.set((FactoryBuilderSupport) data.get("proxyBuilder"));
-        //noinspection unchecked
-        contexts.set((LinkedList<Map<String, Object>>) data.get("contexts"));
-    }
-
-    public Object build(Class viewClass) {
-        if (Script.class.isAssignableFrom(viewClass)) {
-            Script script = InvokerHelper.createScript(viewClass, this);
-            return build(script);
-        } else {
-            throw new RuntimeException("Only scripts can be executed via build(Class)");
-        }
-    }
-
-    public Object build(Script script) {
-        // this used to be synchronized, but we also used to remove the
-        // metaclass.  Since adding the metaclass is now a side effect, we
-        // don't need to ensure the meta-class won't be observed and don't
-        // need to hide the side effect.
-        MetaClass scriptMetaClass = script.getMetaClass();
-        script.setMetaClass(new FactoryInterceptorMetaClass(scriptMetaClass, this));
-        script.setBinding(this);
-        Object oldScriptName = getProxyBuilder().getVariables().get(SCRIPT_CLASS_NAME);
-        try {
-            getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, script.getClass().getName());
-            return script.run();
-        } finally {
-            if(oldScriptName != null) {
-                getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, oldScriptName);
-            } else {
-                getProxyBuilder().getVariables().remove(SCRIPT_CLASS_NAME);
-            }
-        }
-    }
-
-    public Object build(final String script, GroovyClassLoader loader) {
-        return build(loader.parseClass(script));
-    }
-
-    /**
-     * Switches the builder's proxyBuilder during the execution of a closure.<br>
-     * This is useful to temporary change the building context to another builder
-     * without the need for a contrived setup. It will also take care of restoring
-     * the previous proxyBuilder when the execution finishes, even if an exception
-     * was thrown from inside the closure.
-     *
-     * @param builder the temporary builder to switch to as proxyBuilder.
-     * @param closure the closure to be executed under the temporary builder.
-     * @return the execution result of the closure.
-     * @throws RuntimeException - any exception the closure might have thrown during
-     *                          execution.
-     */
-    public Object withBuilder(FactoryBuilderSupport builder, Closure closure) {
-        if (builder == null || closure == null) {
-            return null;
-        }
-
-        Object result = null;
-        Object previousContext = getProxyBuilder().getContext();
-        FactoryBuilderSupport previousProxyBuilder = localProxyBuilder.get();
-        try {
-            localProxyBuilder.set(builder);
-            closure.setDelegate(builder);
-            result = closure.call();
-        }
-        catch (RuntimeException e) {
-            // remove contexts created after we started
-            localProxyBuilder.set(previousProxyBuilder);
-            if (getProxyBuilder().getContexts().contains(previousContext)) {
-                Map<String, Object> context = getProxyBuilder().getContext();
-                while (context != null && context != previousContext) {
-                    getProxyBuilder().popContext();
-                    context = getProxyBuilder().getContext();
-                }
-            }
-            throw e;
-        }
-        finally {
-            localProxyBuilder.set(previousProxyBuilder);
-        }
-
-        return result;
-    }
-
-    /**
-     * Switches the builder's proxyBuilder during the execution of a closure.<br>
-     * This is useful to temporary change the building context to another builder
-     * without the need for a contrived setup. It will also take care of restoring
-     * the previous proxyBuilder when the execution finishes, even if an exception
-     * was thrown from inside the closure. Additionally it will use the closure's
-     * result as the value for the node identified by 'name'.
-     *
-     * @param builder the temporary builder to switch to as proxyBuilder.
-     * @param name    the node to build on the 'parent' builder.
-     * @param closure the closure to be executed under the temporary builder.
-     * @return a node that responds to value of name with the closure's result as its
-     *         value.
-     * @throws RuntimeException - any exception the closure might have thrown during
-     *                          execution.
-     */
-    public Object withBuilder(FactoryBuilderSupport builder, String name, Closure closure) {
-        if (name == null) {
-            return null;
-        }
-        Object result = getProxyBuilder().withBuilder(builder, closure);
-        return getProxyBuilder().invokeMethod(name, new Object[]{result});
-    }
-
-    /**
-     * Switches the builder's proxyBuilder during the execution of a closure.<br>
-     * This is useful to temporary change the building context to another builder
-     * without the need for a contrived setup. It will also take care of restoring
-     * the previous proxyBuilder when the execution finishes, even if an exception
-     * was thrown from inside the closure. Additionally it will use the closure's
-     * result as the value for the node identified by 'name' and assign any attributes
-     * that might have been set.
-     *
-     * @param attributes additional properties for the node on the parent builder.
-     * @param builder    the temporary builder to switch to as proxyBuilder.
-     * @param name       the node to build on the 'parent' builder.
-     * @param closure    the closure to be executed under the temporary builder.
-     * @return a node that responds to value of name with the closure's result as its
-     *         value.
-     * @throws RuntimeException - any exception the closure might have thrown during
-     *                          execution.
-     */
-    public Object withBuilder(Map attributes, FactoryBuilderSupport builder, String name, Closure closure) {
-        if (name == null) {
-            return null;
-        }
-        Object result = getProxyBuilder().withBuilder(builder, closure);
-        return getProxyBuilder().invokeMethod(name, new Object[]{attributes, result});
-    }
-
-    public void addDisposalClosure(Closure closure) {
-        disposalClosures.add(closure);
-    }
-
-    public List<Closure> getDisposalClosures() {
-        return Collections.unmodifiableList(disposalClosures);
-    }
-
-    public void dispose() {
-        for (int i = disposalClosures.size() - 1; i >= 0; i--) {
-            disposalClosures.get(i).call();
-        }
-    }
-}
-
-class FactoryInterceptorMetaClass extends DelegatingMetaClass {
-
-    FactoryBuilderSupport builder;
-
-    public FactoryInterceptorMetaClass(MetaClass delegate, FactoryBuilderSupport builder) {
-        super(delegate);
-        this.builder = builder;
-    }
-
-    public Object invokeMethod(Object object, String methodName, Object arguments) {
-        try {
-            return delegate.invokeMethod(object, methodName, arguments);
-        } catch (MissingMethodException mme) {
-            // attempt builder resolution
-            try {
-                if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
-                    // dispatch to factories if it is not a literal method
-                    return builder.invokeMethod(methodName, arguments);
-                } else {
-                    return InvokerHelper.invokeMethod(builder, methodName, arguments);
-                }
-            } catch (MissingMethodException mme2) {
-                // chain secondary exception
-                Throwable root = mme;
-                while (root.getCause() != null) {
-                    root = root.getCause();
-                }
-                root.initCause(mme2);
-                // throw original
-                throw mme;
-            }
-        }
-    }
-
-    public Object invokeMethod(Object object, String methodName, Object[] arguments) {
-        try {
-            return delegate.invokeMethod(object, methodName, arguments);
-        } catch (MissingMethodException mme) {
-            // attempt builder resolution
-            try {
-                if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
-                    // dispatch to factories if it is not a literal method
-                    return builder.invokeMethod(methodName, arguments);
-                } else {
-                    return InvokerHelper.invokeMethod(builder, methodName, arguments);
-                }
-            } catch (MissingMethodException mme2) {
-                // chain secondary exception
-                Throwable root = mme;
-                while (root.getCause() != null) {
-                    root = root.getCause();
-                }
-                root.initCause(mme2);
-                // throw original
-                throw mme;
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FileNameByRegexFinder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FileNameByRegexFinder.groovy b/src/main/groovy/util/FileNameByRegexFinder.groovy
deleted file mode 100644
index fbb16e7..0000000
--- a/src/main/groovy/util/FileNameByRegexFinder.groovy
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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 groovy.util
-
-/**
- * Find files according to a base directory and an includes and excludes pattern.
- * The include and exclude patterns conform to regex conventions.
- *
- * @author Dierk Koenig
- * @author Paul King
- */
-class FileNameByRegexFinder implements IFileNameFinder {
-
-    List<String> getFileNames(String basedir, String pattern) {
-        getFileNames(basedir, pattern, "")
-    }
-
-    List<String> getFileNames(String basedir, String pattern, String excludesPattern) {
-        def result = []
-        new File(basedir).eachFileRecurse {
-            if (it.path =~ pattern && (!excludesPattern || !(it.path =~ excludesPattern))) {
-                result << it.absolutePath
-            }
-        }
-        return result
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FileTreeBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FileTreeBuilder.groovy b/src/main/groovy/util/FileTreeBuilder.groovy
deleted file mode 100644
index f76c95a..0000000
--- a/src/main/groovy/util/FileTreeBuilder.groovy
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  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 groovy.util
-
-import groovy.transform.CompileStatic
-
-/**
- * A builder dedicated at generating a file directory structure from a
- * specification. For example, imagine that you want to create the following tree:
- * <pre>
- * src/
- *  |--- main
- *  |     |--- groovy
- *  |            |--- Foo.groovy
- *  |--- test
- *        |--- groovy
- *               |--- FooTest.groovy
- *
- * </pre>
- *
- * <p>Then you can create the structure using:</p>
- * <pre><code>
- *     def tree = new FileTreeBuilder()
- *     tree.dir('src') {
- *        dir('main') {
- *           dir('groovy') {
- *              file('Foo.groovy', 'println "Hello"')
- *           }
- *        }
- *        dir('test') {
- *           dir('groovy') {
- *              file('FooTest.groovy', 'class FooTest extends GroovyTestCase {}')
- *           }
- *        }
- *     }
- * </code></pre>
- *
- * <p>or with this shorthand syntax:</p>
- * <pre><code>
- *     def tree = new FileTreeBuilder()
- *     tree.src {
- *        main {
- *           groovy {
- *              'Foo.groovy'('println "Hello"')
- *           }
- *        }
- *        test {
- *           groovy {
- *              'FooTest.groovy'('class FooTest extends GroovyTestCase {}')
- *           }
- *        }
- *     }
- * </code></pre>
- *
- * @since 2.4.2
- */
-@CompileStatic
-class FileTreeBuilder {
-
-    File baseDir
-
-    FileTreeBuilder(File baseDir = new File('.')) {
-        this.baseDir = baseDir
-    }
-
-    /**
-     * Creates a file with the specified name and the text contents using the system default encoding.
-     * @param name name of the file to be created
-     * @param contents the contents of the file, written using the system default encoding
-     * @return the file being created
-     */
-    File file(String name, CharSequence contents) {
-        new File(baseDir, name) << contents
-    }
-
-    /**
-     * Creates a file with the specified name and the specified binary contents
-     * @param name name of the file to be created
-     * @param contents the contents of the file
-     * @return the file being created
-     */
-    File file(String name, byte[] contents) {
-        new File(baseDir, name) << contents
-    }
-
-    /**
-     * Creates a file with the specified name and the contents from the source file (copy).
-     * @param name name of the file to be created
-     * @param contents the contents of the file
-     * @return the file being created
-     */
-    File file(String name, File source) {
-        // TODO: Avoid using bytes and prefer streaming copy
-        file(name, source.bytes)
-    }
-
-    /**
-     * Creates a new file in the current directory, whose contents is going to be generated in the
-     * closure. The delegate of the closure is the file being created.
-     * @param name name of the file to create
-     * @param spec closure for generating the file contents
-     * @return the created file
-     */
-    File file(String name, @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) {
-        def file = new File(baseDir, name)
-        def clone = (Closure) spec.clone()
-        clone.delegate = file
-        clone.resolveStrategy = Closure.DELEGATE_FIRST
-        clone(file)
-        file
-    }
-
-    /**
-     * Creates a new empty directory
-     * @param name the name of the directory to create
-     * @return the created directory
-     */
-    File dir(String name) {
-        def f = new File(baseDir, name)
-        f.mkdirs()
-        f
-    }
-
-    /**
-     * Creates a new directory and allows to specify a subdirectory structure using the closure as a specification
-     * @param name name of the directory to be created
-     * @param cl specification of the subdirectory structure
-     * @return the created directory
-     */
-    File dir(String name, @DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure cl) {
-        def oldBase = baseDir
-        def newBase = dir(name)
-        try {
-            baseDir = newBase
-            cl.delegate = this
-            cl.resolveStrategy = Closure.DELEGATE_FIRST
-            cl()
-        } finally {
-            baseDir = oldBase
-        }
-        newBase
-    }
-
-    File call(@DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure spec) {
-        def clone = (Closure) spec.clone()
-        clone.delegate = this
-        clone.resolveStrategy = Closure.DELEGATE_FIRST
-        clone.call()
-        baseDir
-    }
-
-
-    def methodMissing(String name, args) {
-        if (args instanceof Object[] && ((Object[]) args).length == 1) {
-            def arg = ((Object[]) args)[0]
-            if (arg instanceof Closure) {
-                dir(name, arg)
-            } else if (arg instanceof CharSequence) {
-                file(name, arg.toString())
-            } else if (arg instanceof byte[]) {
-                file(name, arg)
-            } else if (arg instanceof File) {
-                file(name, arg)
-            }
-        }
-    }
-}
\ No newline at end of file


[08/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/IndexedProperty.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/IndexedProperty.java b/src/main/groovy/transform/IndexedProperty.java
deleted file mode 100644
index cf77d98..0000000
--- a/src/main/groovy/transform/IndexedProperty.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Field annotation used with properties to provide an indexed getter and setter for the property.
- * Groovy provides nice GPath syntax support for accessing indexed properties but Java tools
- * or frameworks may expect the JavaBean style setters and getters.
- * <p>
- * <em>Example usage:</em> suppose you have a class with the following properties:
- * <pre>
- * {@code @IndexedProperty} FieldType[] someField
- * {@code @IndexedProperty} List<FieldType> otherField
- * {@code @IndexedProperty} List furtherField
- * </pre>
- * will add the following methods to the class containing the properties:
- * <pre>
- * FieldType getSomeField(int index) {
- *     someField[index]
- * }
- * FieldType getOtherField(int index) {
- *     otherField[index]
- * }
- * Object getFurtherField(int index) {
- *     furtherField[index]
- * }
- * void setSomeField(int index, FieldType val) {
- *     someField[index] = val
- * }
- * void setOtherField(int index, FieldType val) {
- *     otherField[index] = val
- * }
- * void setFurtherField(int index, Object val) {
- *     furtherField[index] = val
- * }
- * </pre>
- * Normal Groovy visibility rules for properties apply
- * (i.e. no <code>public</code>, <code>private</code> or <code>package</code>
- * visibility can be specified) or you will receive a compile-time error message.
- * The normal Groovy property getters and setters will also be created.
- * <p>
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.IndexedProperty
- *
- * class Group {
- *     String name
- *     List members = []
- * }
- *
- * class IndexedGroup {
- *     String name
- *     &#64;IndexedProperty List members = []
- * }
- *
- * def group = new Group(name: 'Groovy')
- * group.members[0] = 'mrhaki'
- * group.members[1] = 'Hubert'
- * assert 2 == group.members.size()
- * assert ['mrhaki', 'Hubert'] == group.members
- *
- * try {
- *     group.setMembers(0, 'hubert') // Not index property
- * } catch (MissingMethodException e) {
- *     assert e
- * }
- *
- * def indexedGroup = new IndexedGroup(name: 'Grails')
- * indexedGroup.members[0] = 'mrhaki'
- * indexedGroup.setMembers 1, 'Hubert'
- * assert 2 == indexedGroup.members.size()
- * assert 'mrhaki' == indexedGroup.getMembers(0)
- * assert 'Hubert' == indexedGroup.members[1]
- * </pre>
- *
- * @author Paul King
- * @since 1.7.3
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.FIELD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.IndexedPropertyASTTransformation")
-public @interface IndexedProperty {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/InheritConstructors.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/InheritConstructors.java b/src/main/groovy/transform/InheritConstructors.java
deleted file mode 100644
index f4c77f5..0000000
--- a/src/main/groovy/transform/InheritConstructors.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation to make constructors from a super class available in a sub class.
- * Should be used with care with other annotations which create constructors - see "Known
- * Limitations" for more details.
- * <p>
- * {@code @InheritConstructors} saves you typing some boilerplate code.
- * <p>
- * <em>Example usage:</em>
- * <pre class="groovyTestCase">
- * class Person {
- *     String first, last
- *     Person(String first, String last) {
- *         this.first = first
- *         this.last = last.toUpperCase()
- *     }
- * }
- *
- * {@code @groovy.transform.InheritConstructors}
- * class PersonAge extends Person {
- *     int age
- * }
- *
- * def js = new PersonAge('John', 'Smith')
- * js.age = 25
- * 
- * assert "$js.last, $js.first is $js.age years old" == 'SMITH, John is 25 years old'
- * </pre>
- * for this case, the <code>PersonAge</code> class will be
- * equivalent to the following code:
- * <pre>
- * class PersonAge extends Person {
- *     PersonAge(String first, String last) {
- *         super(first, last)
- *     }
- *     int age
- * }
- * </pre>
- * You may add additional constructors in addition to inherited ones.
- * If the argument types of a supplied constructor exactly match those
- * of a parent constructor, then that constructor won't be inherited.
- * <p>
- * <em>Style note:</em> Don't go overboard using this annotation.
- * Typical Groovy style is to use named-arg constructors when possible.
- * This is easy to do for Groovy objects or any objects following JavaBean
- * conventions. In other cases, inheriting the constructors may be useful.
- * However, sub-classes often introduce new properties and these are often best
- * set in a constructor; especially if that matches the style adopted
- * in parent classes. So, even for the example above, it may have been
- * better style to define an explicit constructor for <code>PersonAge</code>
- * that also set the <code>age</code> property. Sometimes, consistent
- * style is much more important than saving a few keystrokes.
- * <p>
- * As another example, this:
- * <pre>
- * {@code @InheritConstructors} class CustomException extends RuntimeException { }
- * </pre>
- * is equivalent to this:
- * <pre>
- * class CustomException extends RuntimeException {
- *     CustomException() {
- *         super()
- *     }
- *     CustomException(String message) {
- *         super(message)
- *     }
- *     CustomException(String message, Throwable cause) {
- *         super(message, cause)
- *     }
- *     CustomException(Throwable cause) {
- *         super(cause)
- *     }
- * }
- * </pre>
- * Known Limitations:
- * <ul>
- * <li>This AST transform creates (potentially) numerous constructors.
- * You should take care to avoid constructors with duplicate signatures if you are defining your own constructors or
- * combining with other AST transforms which create constructors (e.g. {@code @TupleConstructor});
- * the order in which the particular transforms are processed becomes important in that case.</li>
- * <li>If you create Groovy constructors with optional
- * arguments this leads to multiple constructors created in the byte code.
- * The expansion to multiple constructors occurs in a later phase to
- * this AST transformation. This means that you can't override (i.e. not
- * inherit) the constructors with signatures that Groovy adds later.
- * If you get it wrong you will get a compile-time error about the duplication.</li>
- * </ul>
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.InheritConstructors
- *
- * &#64;InheritConstructors
- * class MyException extends Exception {
- * }
- *
- * def e = new MyException()
- * def e1 = new MyException('message')   // Other constructors are available.
- * assert 'message' == e1.message
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.InheritConstructors
-
- * class Person {
- *     String name
- *
- *     Person(String name) {
- *         this.name = name
- *     }
- * }
- *
- * &#64;InheritConstructors
- * class Child extends Person {}
- *
- * def child = new Child('Liam')
- * assert 'Liam' == child.name
- * </pre>
- *
- * @author Paul King
- * @since 1.7.3
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.InheritConstructorsASTTransformation")
-public @interface InheritConstructors {
-    /**
-     * Whether to carry over annotations on the copied constructors.
-     * Currently Closure annotation members are not supported.
-     *
-     * @return true if copied constructor should keep constructor annotations
-     */
-    boolean constructorAnnotations() default false;
-
-    /**
-     * Whether to carry over parameter annotations on the copied constructors.
-     * Currently Closure annotation members are not supported.
-     *
-     * @return true if copied constructor should keep parameter annotations
-     */
-    boolean parameterAnnotations() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/MapConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/MapConstructor.java b/src/main/groovy/transform/MapConstructor.java
deleted file mode 100644
index 5608001..0000000
--- a/src/main/groovy/transform/MapConstructor.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of map constructors in classes.
- * <p>
- * It allows you to write classes in this shortened form:
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * {@code @TupleConstructor}
- * class Person {
- *     String first, last
- * }
- *
- * {@code @CompileStatic} // optional
- * {@code @ToString(includeSuperProperties=true)}
- * {@code @MapConstructor}(pre={ super(args?.first, args?.last); args = args ?: [:] }, post = { first = first?.toUpperCase() })
- * class Author extends Person {
- *     String bookName
- * }
- *
- * assert new Author(first: 'Dierk', last: 'Koenig', bookName: 'ReGinA').toString() == 'Author(ReGinA, DIERK, Koenig)'
- * assert new Author().toString() == 'Author(null, null, null)'
- * </pre>
- * The {@code @MapConstructor} annotation instructs the compiler to execute an
- * AST transformation which adds the necessary constructor method to your class.
- * <p>
- * A map constructor is created which sets properties, and optionally fields and
- * super properties if the property/field name is a key within the map.
- * <p>
- * For the above example, the generated constructor will be something like:
- * <pre>
- * public Author(java.util.Map args) {
- *     super(args?.first, args?.last)
- *     args = args ? args : [:]
- *     if (args.containsKey('bookName')) {
- *         this.bookName = args['bookName']
- *     }
- *     first = first?.toUpperCase()
- * }
- * </pre>
- *
- * @since 2.5.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.MapConstructorASTTransformation")
-public @interface MapConstructor {
-    /**
-     * List of field and/or property names to exclude from the constructor.
-     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * List of field and/or property names to include within the constructor.
-     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined; all fields and/or properties
-     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * Include fields in the constructor.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Include properties in the constructor.
-     */
-    boolean includeProperties() default true;
-
-    /**
-     * Include properties from super classes in the constructor.
-     */
-    boolean includeSuperProperties() default false;
-
-    /**
-     * By default, properties are set directly using their respective field.
-     * By setting {@code useSetters=true} then a writable property will be set using its setter.
-     * If turning on this flag we recommend that setters that might be called are
-     * made null-safe wrt the parameter.
-     */
-    boolean useSetters() default false;
-
-    /**
-     * A Closure containing statements which will be prepended to the generated constructor. The first statement within the Closure may be "super(someArgs)" in which case the no-arg super constructor won't be called.
-     */
-    Class pre() default Undefined.CLASS.class;
-
-    /**
-     * A Closure containing statements which will be appended to the end of the generated constructor. Useful for validation steps or tweaking the populated fields/properties.
-     */
-    Class post() default Undefined.CLASS.class;
-
-    /**
-     * Whether to include all fields and/or properties within the constructor, including those with names that are considered internal.
-     */
-    boolean allNames() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Memoized.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Memoized.java b/src/main/groovy/transform/Memoized.java
deleted file mode 100644
index efecb17..0000000
--- a/src/main/groovy/transform/Memoized.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Method annotation that creates a cache for the results of the execution of the annotated method. Whenever the method
- * is called, the mapping between the parameters and the return value is preserved in a cache making subsequent calls with
- * the same arguments fast.
- * 
- * <p>
- * Example usage:
- * 
- * <pre>
- * class MemoizedExample {
- * 
- *     {@code @Memoized}
- *     int sum(int n1, int n2) {
- *         println "$n1 + $n2 = ${n1 + n2}" 
- *         n1 + n2
- *     }
- * }
- * </pre>
- * 
- * which becomes (approximately):
- * 
- * <pre>
- * class MemoizedExample {
- * 
- *     private final Closure memoizedSum = { int n1, int n2 ->
- *         private$method$memoizedSum(n1,n2)
- *     }.memoize()
- * 
- *     int sum(int n1, int n2) {
- *         memoizedSum(n1, n2)
- *     }
- *
- *     private private$method$memoizedSum(int n1, int n2) {
- *         println "$n1 + $n2 = ${n1 + n2}"
- *         n1 + n2
- *     }
- * }
- * </pre>
- * 
- * <p>
- * Upon execution of this code:
- * 
- * <pre>
- * def instance = new MemoizedExample()
- * println instance.sum(1, 2)
- * println instance.sum(1, 2)
- * println instance.sum(2, 3)
- * println instance.sum(2, 3)
- * </pre>
- * 
- * The following will be output:
- * 
- * <pre>
- * 1 + 2 = 3
- * 3
- * 3
- * 2 + 3 = 5
- * 5
- * 5
- * </pre>
- * 
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * // Script variable which is changed when increment()
- * // method is invoked. 
- * // If cached method call is invoked then the value
- * // of this variable will not change.
- * &#64;Field boolean incrementChange = false
- *
- * &#64;Memoized 
- * int increment(int value) {
- *     incrementChange = true
- *     value + 1 
- * }
- *
- * // Invoke increment with argument 10.
- * increment(10)
- *
- * // increment is invoked so incrementChange is true.
- * assert incrementChange
- *
- * // Set incrementChange back to false.
- * incrementChange = false
- *
- * // Invoke increment with argument 10.
- * increment(10)
- *
- * // Now the cached method is used and
- * // incrementChange is not changed.
- * assert !incrementChange
- *
- * // Invoke increment with other argument value.
- * increment(11)
- *
- * // increment is invoked so incrementChange is true.
- * assert incrementChange
- * </pre>
- * 
- * @author Andrey Bloschetsov
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ ElementType.METHOD })
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.MemoizedASTTransformation")
-public @interface Memoized {
-    
-    /**
-     * Number of cached return values to protect from garbage collection.
-     */
-    int protectedCacheSize() default 0;
-    
-    /**
-     * The maximum size the cache can grow to.
-     */
-    int maxCacheSize() default 0;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/PackageScope.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/PackageScope.java b/src/main/groovy/transform/PackageScope.java
deleted file mode 100644
index 1bcec9c..0000000
--- a/src/main/groovy/transform/PackageScope.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation used for turning off Groovy's auto visibility conventions.
- * By default, Groovy automatically turns package protected fields into properties
- * and makes package protected methods, constructors and classes public.
- * This annotation allows this feature to be turned
- * off and revert back to Java behavior if needed.
- *
- * Place it on classes, fields, constructors or methods of interest as follows:
- * <pre>
- * {@code @}PackageScope class Bar {      // package protected
- *     {@code @}PackageScope int field    // package protected; not a property
- *     {@code @}PackageScope method(){}   // package protected
- * }
- * </pre>
- * or for greater control, at the class level with one or more
- * <code>PackageScopeTarget</code> values:
- * <pre>
- * import static groovy.transform.PackageScopeTarget.*
- * {@code @}PackageScope([CLASS, FIELDS])
- * class Foo {              // class will have package protected scope
- *     int field1, field2   // both package protected
- *     def method(){}       // public
- * }
- * {@code @}PackageScope(METHODS)
- * class Bar {         // public
- *     int field       // treated as a property
- *     def method1(){} // package protected
- *     def method2(){} // package protected
- * }
- * </pre>
- *
- * This transformation is not frequently needed but can be useful in certain testing scenarios
- * or when using a third-party library or framework which relies upon package scoping.
- *
- * @author Paul King
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.PackageScopeASTTransformation")
-public @interface PackageScope {
-    groovy.transform.PackageScopeTarget[] value() default {PackageScopeTarget.CLASS};
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/PackageScopeTarget.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/PackageScopeTarget.java b/src/main/groovy/transform/PackageScopeTarget.java
deleted file mode 100644
index 07c9bae..0000000
--- a/src/main/groovy/transform/PackageScopeTarget.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  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 groovy.transform;
-
-/**
- * Intended target when {@code @}PackageScope is placed at the class level.
- *
- * @author Paul King
- * @since 1.8.0
- */
-public enum PackageScopeTarget {
-    /**
-     * Make the Class have package protected visibility.
-     */
-    CLASS,
-
-    /**
-     * Make the Class methods have package protected visibility.
-     */
-    METHODS,
-
-    /**
-     * Make the Class fields have package protected visibility.
-     */
-    FIELDS,
-
-    /**
-     * Make the Class constructors have package protected visibility.
-     */
-    CONSTRUCTORS
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/SelfType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/SelfType.java b/src/main/groovy/transform/SelfType.java
deleted file mode 100644
index 5b2ccb3..0000000
--- a/src/main/groovy/transform/SelfType.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation can be added on a trait to declare the list of types that a class
- * implementing that trait is supposed to extend. This is useful when you want to be
- * able to call methods from the class implementing the trait without having to declare
- * all of them as members of the trait.
- *
- * Self types are particularly useful in combination with {@link groovy.transform.CompileStatic},
- * if you know that a trait can only be applied to a specific type but that the trait cannot extend
- * that type itself. For example, imagine the following code:
- * <pre><code>
- *     class Component { void methodInComponent() }
- *     trait ComponentDecorator {
- *         void logAndCall() {
- *             println "Calling method in component"
- *             methodInComponent()
- *         }
- *         // other useful methods
- *     }
- *     class DecoratedComponent extends Component implements ComponentDecorator {}
- * </code></pre>
- *
- * This will work because the trait uses the dynamic backend, so there is no check at
- * compile time that the <i>methodInComponent</i> call in <i>logAndCall</i> is actually
- * defined. If you annotate the trait with {@link groovy.transform.CompileStatic}, compilation
- * will fail because the trait does not define the method. To declare that the trait can be
- * applied on something that will extend <i>Component</i>, you need to add the <i>SelfType</i>
- * annotation like this:
- * <pre><code>
- *     class Component { void methodInComponent() }
- *
- *     {@literal @}CompileStatic
- *     {@literal @}SelfType(Component)
- *     trait ComponentDecorator {
- *         void logAndCall() {
- *             println "Calling method in component"
- *             methodInComponent()
- *         }
- *         // other useful methods
- *     }
- *     class DecoratedComponent extends Component implements ComponentDecorator {}
- * </code></pre>
- *
- * This pattern can therefore be used to avoid explicit casts everywhere you need to call a method
- * that you know is defined in the class that will implement the trait but normally don't have access
- * to, which is often the case where a trait needs to be applied on a class provided by a third-party
- * library.
- *
- * @author Cédric Champeau
- * @since 2.4.0
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-public @interface SelfType {
-    Class[] value();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Sortable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Sortable.java b/src/main/groovy/transform/Sortable.java
deleted file mode 100644
index b235bfa..0000000
--- a/src/main/groovy/transform/Sortable.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * A class annotation used to make a class Comparable by multiple Comparators.
- *
- * As an example, given this class:
- * <pre>
- * {@code @Sortable} class Person {
- *     String first
- *     String last
- *     Integer born
- * }
- * </pre>
- * The generated Groovy class will:
- * <ul>
- *     <li>implement the {@code Comparable} interface</li>
- *     <li>have a {@code compareTo} method based on the {@code first},
- *     {@code last} and {@code born} properties (priority ordering will be according
- *     to the ordering of property definition, highest first, unless 'includes' is used; in which case,
- *     priority will be according to the order given in the includes list)</li>
- *     <li>have three {@code Comparator} methods named {@code comparatorByFirst},
- *     {@code comparatorByLast} and {@code comparatorByBorn}</li>
- *     <li>sort by natural order by default, reversed natural order can be specified</li>
- * </ul>
- * The properties within the class must themselves be {@code Comparable} or {@code @Sortable}.
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.Sortable
- * import groovy.transform.ToString
- *
- * &#64;Sortable
- * &#64;ToString
- * class Course {
- *     // Order of properties determines priority when sorting
- *     String title
- *     Date beginDate
- *     Integer maxAttendees  // int doesn't implement Comparable, so use Integer
- * }
- *
- *
- * final Course groovy = new Course(
- *         title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
- * final Course groovy2 = new Course(
- *         title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
- * final Course grails = new Course(
- *         title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)
- *
- *
- * final List&lt;Course&gt; courses = [groovy, groovy2, grails]
- * assert courses.last().title == 'Grails'
- *
- * // Use toSorted() method to sort
- * final List&lt;Course&gt; sorted = courses.toSorted()
- *
- * assert sorted.first().title == 'Grails'
- * assert sorted.last().title == 'Groovy'
- * assert sorted.maxAttendees == [20, 50, 40]
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Order of fields for includes determines priority when sorting
- * import groovy.transform.Sortable
- * import groovy.transform.ToString
- *
- * &#64;Sortable(includes = ['title', 'maxAttendees'])
- * // Or &#64;Sortable(excludes = ['beginDate'])
- * &#64;ToString
- * class Course {
- *     String title
- *     Date beginDate
- *     Integer maxAttendees
- * }
- *
- * final Course groovy = new Course(
- *         title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
- * final Course groovy2 = new Course(
- *         title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
- * final Course grails = new Course(
- *         title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)
- *
- *
- * final List&lt;Course&gt; courses = [groovy, groovy2, grails]
- *
- * // Use toSorted() method to sort
- * final List&lt;Course&gt; sorted = courses.toSorted()
- *
- * assert sorted.first().title == 'Grails'
- * assert sorted.last().title == 'Groovy'
- * assert sorted.maxAttendees == [20, 40, 50]
- *
- * //--------------------------------------------------------------------------
- * // Static methods to create comparators.
- * final Comparator byMaxAttendees = Course.comparatorByMaxAttendees()
- * final List&lt;Course&gt; sortedByMaxAttendees = courses.sort(false, byMaxAttendees)
- *
- * assert sortedByMaxAttendees.maxAttendees == [20, 40, 50]
- * // beginDate is not used for sorting
- * assert sortedByMaxAttendees[2].beginDate &lt; sortedByMaxAttendees[1].beginDate
- *
- * assert Course.declaredMethods.name.findAll { it.startsWith('comparatorBy') }.toSorted() == ['comparatorByMaxAttendees', 'comparatorByTitle']
- *
- * //--------------------------------------------------------------------------
- * // Sorting by max attendees using reversed order
- * import groovy.transform.Sortable
- * import groovy.transform.ToString
- *
- * &#64;Sortable(includes = ['points'], reversed = true)
- * &#64;ToString
- * class LeaderBoardEntry {
- *     String team
- *     int points
- * }
- *
- *
- * final LeaderBoardEntry teamA = new LeaderBoardEntry(team: "Team A", points: 30)
- * final LeaderBoardEntry teamB = new LeaderBoardEntry(team: "Team B", points: 80)
- * final LeaderBoardEntry teamC = new LeaderBoardEntry(team: "Team C", points: 50)
- *
- * final List&lt;LeaderBoardEntry&gt; leaderBoard = [teamA, teamB, teamC].toSorted()
- *
- * assert leaderBoard.first().team == 'Team B'
- * assert leaderBoard.last().team == 'Team A'
- * assert leaderBoard.points == [80, 50, 30]
- *
- * </pre>
- *
- * @author Andres Almiray
- * @author Paul King
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.SortableASTTransformation")
-public @interface Sortable {
-    /**
-     * Property names to include in the comparison algorithm.
-     * Must not be used if 'excludes' is used.
-     * The default value is a special marker value indicating that no includes are defined; all properties
-     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * Property names to exclude in the comparison algorithm.
-     * Must not be used if 'includes' is used.
-     */
-    String[] excludes() default {};
-
-    /**
-     * Set to true so that comparator uses reversed natural order.
-     * @since 2.5.0
-     */
-    boolean reversed() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/SourceURI.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/SourceURI.java b/src/main/groovy/transform/SourceURI.java
deleted file mode 100644
index 4104369..0000000
--- a/src/main/groovy/transform/SourceURI.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Variable annotation used for getting the URI of the current script.
- * <p>
- * The type of the variable annotated with {@code @SourceURI} must be assignment compatible with {@link java.net.URI}.
- * It will be used to hold a URI object that references the source for the current script.
- * </p><p>By default the URI
- * will be made absolute (which is to say it will have an authority) in the case where a relative path was used
- * for the source of the script.  If you want to leave relative URIs as relative, then set <code>allowRelative</code>
- * to <code>true</code>.
- * </p>
- *
- * Example usage:
- * <pre class="groovyTestCase">
- * {@code @groovy.transform.SourceURI} def sourceURI
- *
- * assert sourceURI instanceof java.net.URI
- * </pre>
- *
- * @author Jim White
- * @since 2.3.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.LOCAL_VARIABLE, ElementType.FIELD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.SourceURIASTTransformation")
-public @interface SourceURI {
-    boolean allowRelative() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Synchronized.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Synchronized.java b/src/main/groovy/transform/Synchronized.java
deleted file mode 100644
index dc8867c..0000000
--- a/src/main/groovy/transform/Synchronized.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Method annotation to make a method call synchronized for concurrency handling
- * with some useful baked-in conventions.
- * <p>
- * {@code @Synchronized} is a safer variant of the <code>synchronized</code> method modifier.
- * The annotation can only be used on static and instance methods. It operates similarly to
- * the <code>synchronized</code> keyword, but it locks on different objects. When used with
- * an instance method, the <code>synchronized</code> keyword locks on <code>this</code>, but the annotation
- * locks on a (by default automatically generated) field named <code>$lock</code>.
- * If the field does not exist, it is created for you. If you annotate a static method,
- * the annotation locks on a static field named <code>$LOCK</code> instead.
- * <p>
- * If you want, you can create these locks yourself.
- * The <code>$lock</code> and <code>$LOCK</code> fields will not be generated if you create
- * them yourself. You can also choose to lock on another field, by specifying its name as
- * parameter to the {@code @Synchronized} annotation. In this usage variant, the lock field
- * will not be created automatically, and you must explicitly create it yourself.
- * <p>
- * <em>Rationale:</em> Locking on <code>this</code> or your own class object can have unfortunate side-effects,
- * as other code not under your control can lock on these objects as well, which can
- * cause race conditions and other nasty threading-related bugs.
- * <p>
- * <em>Example usage:</em>
- * <pre>
- * class SynchronizedExample {
- *   private final myLock = new Object()
- *
- *   {@code @}Synchronized
- *   static void greet() {
- *     println "world"
- *   }
- *
- *   {@code @}Synchronized
- *   int answerToEverything() {
- *     return 42
- *   }
- *
- *   {@code @}Synchronized("myLock")
- *   void foo() {
- *     println "bar"
- *   }
- * }
- * </pre>
- * which becomes:
- * <pre>
- * class SynchronizedExample {
- *   private static final $LOCK = new Object[0]
- *   private final $lock = new Object[0]
- *   private final myLock = new Object()
- *
- *   static void greet() {
- *     synchronized($LOCK) {
- *       println "world"
- *     }
- *   }
- *
- *   int answerToEverything() {
- *     synchronized($lock) {
- *       return 42
- *     }
- *   }
- *
- *   void foo() {
- *     synchronized(myLock) {
- *       println "bar"
- *     }
- *   }
- * }
- * </pre>
- *
- * <em>Credits:</em> this annotation is inspired by the Project Lombok annotation of the
- * same name. The functionality has been kept similar to ease the learning
- * curve when swapping between these two tools.
- * <p>
- * <em>Details:</em> If <code>$lock</code> and/or <code>$LOCK</code> are auto-generated, the fields are initialized
- * with an empty <code>Object[]</code> array, and not just a new <code>Object()</code> as many snippets using
- * this pattern tend to use. This is because a new <code>Object</code> is NOT serializable, but
- * a 0-size array is. Therefore, using {@code @Synchronized} will not prevent your
- * object from being serialized.
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.Synchronized
- *
- * class Util {
- *     private counter = 0
- *
- *     private def list = ['Groovy']
- *
- *     private Object listLock = new Object[0]
- *
- *     &#64;Synchronized
- *     void workOnCounter() {
- *         assert 0 == counter
- *         counter++
- *         assert 1 == counter
- *         counter --
- *         assert 0 == counter
- *     }
- *
- *     &#64;Synchronized('listLock')
- *     void workOnList() {
- *         assert 'Groovy' == list[0]
- *         list &lt;&lt; 'Grails'
- *         assert 2 == list.size()
- *         list = list - 'Grails'
- *         assert 'Groovy' == list[0]
- *     }
- * }
- *
- * def util = new Util()
- * def tc1 = Thread.start {
- *     100.times {
- *         util.workOnCounter()
- *         sleep 20 
- *         util.workOnList()
- *         sleep 10
- *     }
- * }
- * def tc2 = Thread.start {
- *     100.times {
- *         util.workOnCounter()
- *         sleep 10 
- *         util.workOnList()
- *         sleep 15
- *     }
- * }
- * tc1.join()
- * tc2.join()
- * </pre>
- *
- * @author Paul King
- * @since 1.7.3
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.METHOD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.SynchronizedASTTransformation")
-public @interface Synchronized {
-    /**
-     * @return if a user specified lock object with the given name should be used
-     */
-    String value () default "";
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/TailRecursive.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TailRecursive.groovy b/src/main/groovy/transform/TailRecursive.groovy
deleted file mode 100644
index afbee50..0000000
--- a/src/main/groovy/transform/TailRecursive.groovy
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *  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 groovy.transform
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.ElementType
-import java.lang.annotation.Retention
-import java.lang.annotation.RetentionPolicy
-import java.lang.annotation.Target
-
-/**
- * Method annotation used to transform methods with tail recursive calls into iterative methods automagically
- * since the JVM cannot do this itself. This works for both static and non-static methods.
- * <p/>
- * It allows you to write a method like this:
- * <pre class="groovyTestCase">
- * import groovy.transform.TailRecursive
- * class Target {
- *      {@code @TailRecursive}
- *      long sumUp(long number, long sum = 0) {
- *          if (number == 0)
- *              return sum;
- *          sumUp(number - 1, sum + number)
- *      }
- * }
- * def target = new Target()
- * assert target.sumUp(100) == 5050
- * assert target.sumUp(1000000) == 500000500000 //will blow the stack on most machines when used without {@code @TailRecursive}
- * </pre>
- *
- * {@code @TailRecursive} is supposed to work in combination with {@code @CompileStatic}
- *
- * Known shortcomings:
- * <ul>
- * <li>Only non-void methods are currently being handled. Void methods will fail compilation.
- * <li>Only direct recursion (calling the exact same method again) is supported.
- * <li>Mixing of tail calls and non-tail calls is not possible. The compiler will complain if some recursive calls cannot be handled.
- * <li>Checking if a recursive call is really tail-recursive is not very strict. You might run into cases where non-tail calls will be considered tail calls.
- * <li>In the presence of method overloading and method overriding you might run into situations where a call is considered recursive although it really is not.
- * <li>Catching {@code Throwable} around a recursive might lead to problems
- * <li>Non trivial continuation passing style examples do not work.
- * <li>Probably many unrecognized edge cases.
- * </ul>
- * 
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.TailRecursive
- *
- * &#64;TailRecursive
- * long sizeOfList(list, counter = 0) {
- *     if (list.size() == 0) {
- *         counter
- *     } else {
- *        sizeOfList(list.tail(), counter + 1) 
- *     }
- * }
- *
- * // Without &#64;TailRecursive a StackOverFlowError
- * // is thrown.
- * assert sizeOfList(1..10000) == 10000
- * </pre>
- *
- * @author Johannes Link
- * @since 2.3
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target([ElementType.METHOD])
-@GroovyASTTransformationClass(["org.codehaus.groovy.transform.tailrec.TailRecursiveASTTransformation"])
-public @interface TailRecursive {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ThreadInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ThreadInterrupt.groovy b/src/main/groovy/transform/ThreadInterrupt.groovy
deleted file mode 100644
index 817507a..0000000
--- a/src/main/groovy/transform/ThreadInterrupt.groovy
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- *  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 groovy.transform
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.Documented
-import java.lang.annotation.ElementType
-import java.lang.annotation.Retention
-import java.lang.annotation.RetentionPolicy
-import java.lang.annotation.Target
-
-/**
- * Allows "interrupt-safe" executions of scripts by adding Thread.currentThread().isInterrupted()
- * checks into loops (for, while) and at the start of closures and methods.
- * <p>
- * This is especially useful when executing foreign scripts that you do not have control over. Inject this
- * transformation into a script that you need to interrupt.
- * <p>
- * Annotating anything in a script will cause for loops, while loops, methods, and closures to make an
- * isInterruptedCheck and throw a InterruptedException if the check yields true. The annotation by default
- * will apply to any classes defined in the script as well. Annotated a class will cause (by default) all classes
- * in the entire file ('Compilation Unit') to be enhanced. You can fine tune what is enhanced using the annotation
- * parameters. 
- * <p>
- * The following is sample usage of the annotation:
- *
- * <pre>
- * <code>@groovy.transform.ThreadInterrupt</code>
- * def scriptMethod() {
- *   4.times {
- *     println 'executing script method...'
- *   }
- * }
- *
- * class MyClass {
- *   def myMethod() {
- *     for (i in (1..10)) {
- *       println 'executing method...'
- *     }
- *   }
- * }
- *
- * scriptMethod()
- * new MyClass().myMethod()
- * </pre>
- *
- * Which results in the following code being generated. Notice the checks and exceptions:
- *
- * <pre>
- * public class script1290627909406 extends groovy.lang.Script {
- *
- *     public java.lang.Object scriptMethod() {
- *         if (java.lang.Thread.currentThread().isInterrupted()) {
- *             throw new java.lang.InterruptedException('Execution Interrupted')
- *         }
- *         4.times({
- *             if (java.lang.Thread.currentThread().isInterrupted()) {
- *                 throw new java.lang.InterruptedException('Execution Interrupted')
- *             }
- *             this.println('executing script method...')
- *         })
- *     }
- * }
- * public class MyClass extends java.lang.Object {
- *
- *   public java.lang.Object myMethod() {
- *     if (java.lang.Thread.currentThread().isInterrupted()) {
- *       throw new java.lang.InterruptedException('Execution Interrupted')
- *     }
- *     for (java.lang.Object i : (1..10)) {
- *       if (java.lang.Thread.currentThread().isInterrupted()) {
- *         throw new java.lang.InterruptedException('Execution Interrupted')
- *       }
- *       this.println('executing method...')
- *     }
- *   }
- * }
- *
- * this.scriptMethod()
- * new MyClass().myMethod()
- * </pre>
- * Additional usage examples can be found in the unit test for this class.
- *
- * @see TimedInterrupt
- * @see ConditionalInterrupt
- * @author Cedric Champeau
- * @author Hamlet D'Arcy
- * @author Paul King
- * @since 1.8.0
- */
-@Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target([ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
-@GroovyASTTransformationClass(["org.codehaus.groovy.transform.ThreadInterruptibleASTTransformation"])
-@interface ThreadInterrupt {
-  /**
-   * Set this to false if you have multiple classes within one source file and only
-   * want isInterrupted checks on some of the classes. Place annotations on the classes
-   * you want enhanced. Set to true (the default) for blanket coverage of isInterrupted
-   * checks on all methods, loops and closures within all classes/script code.
-   *
-   * For even finer-grained control see {@code applyToAllMembers}.
-   *
-   * @see #applyToAllMembers()
-   */
-  boolean applyToAllClasses() default true
-
-  /**
-   * Set this to false if you have multiple methods/closures within a class or script and only
-   * want isInterrupted checks on some of them. Place annotations on the methods/closures that
-   * you want enhanced. When false, {@code applyToAllClasses} is automatically set to false.
-   *
-   * Set to true (the default) for blanket coverage of isInterrupted checks on all methods, loops
-   * and closures within the class/script.
-   *
-   * @since 2.2.0
-   * @see #applyToAllClasses()
-   */
-  boolean applyToAllMembers() default true
-
-  /**
-   * By default an isInterrupted check is added to the start of all user-defined methods. To turn this off simply
-   * set this parameter to false.
-   */
-  boolean checkOnMethodStart() default true
-
-  /**
-   * Sets the type of exception which is thrown.
-   */
-  Class thrown() default InterruptedException
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/TimedInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TimedInterrupt.groovy b/src/main/groovy/transform/TimedInterrupt.groovy
deleted file mode 100644
index 0a0c193..0000000
--- a/src/main/groovy/transform/TimedInterrupt.groovy
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  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 groovy.transform
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.Documented
-import java.lang.annotation.ElementType
-import java.lang.annotation.Retention
-import java.lang.annotation.RetentionPolicy
-import java.lang.annotation.Target
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeoutException
-
-/**
- * Allows safe timed executions of scripts by adding elapsed time checks into loops (for, while)
- * and at the start of closures and methods and throwing an exception if a timeout occurs.
- * <p>
- * This is especially useful when executing foreign scripts that you do not have control over.
- * Inject this transformation into a script that you want to timeout after a specified amount of time.
- * <p>
- * Annotating anything in a script will cause for loops, while loops, methods, and closures to make an
- * elapsed time check and throw a TimeoutException if the check yields true. The annotation by default
- * will apply to any classes defined in the script as well. Annotating a class will cause (by default)
- * all classes in the entire file ('Compilation Unit') to be enhanced. You can fine tune what is
- * enhanced using the annotation parameters. Static methods and static fields are ignored.
- * <p>
- * The following is sample usage of the annotation forcing the script to timeout after 5 minutes (300 seconds):
- *
- * <pre>
- * import groovy.transform.TimedInterrupt
- * import java.util.concurrent.TimeUnit
- *
- * {@code @TimedInterrupt}(value = 300L, unit = TimeUnit.SECONDS)
- * class MyClass {
- *      def method() {
- *          println '...'
- *      }
- * }
- * </pre>
- * This sample script will be transformed at compile time to something that resembles this:
- * <pre>
- * import java.util.concurrent.TimeUnit
- * import java.util.concurrent.TimeoutException
- *
- * public class MyClass {
- *     // XXXXXX below is a placeholder for a hashCode value at runtime
- *     final private long timedInterruptXXXXXX$expireTime
- *     final private java.util.Date timedInterruptXXXXXX$startTime
- *
- *     public MyClass() {
- *         timedInterruptXXXXXX$expireTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(300, TimeUnit.SECONDS)
- *         timedInterruptXXXXXX$startTime = new java.util.Date()
- *     }
- *
- *     public java.lang.Object method() {
- *         if (timedInterruptXXXXXX$expireTime < System.nanoTime()) {
- *             throw new TimeoutException('Execution timed out after 300 units. Start time: ' + timedInterruptXXXXXX$startTime)
- *         }
- *         return this.println('...')
- *     }
- * }
- * </pre>
- * See the unit test for this class for additional examples.
- *
- * @author Hamlet D'Arcy
- * @author Cedric Champeau
- * @author Paul King
- * @see ThreadInterrupt
- * @see ConditionalInterrupt
- * @since 1.8.0
- */
-@Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target([ ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
-@GroovyASTTransformationClass(["org.codehaus.groovy.transform.TimedInterruptibleASTTransformation"])
-@interface TimedInterrupt {
-    /**
-     * Set this to false if you have multiple classes within one source file and only want
-     * timeout checks on some of the classes (or you want different time constraints on different classes).
-     * Place an annotation with appropriate parameters on each class you want enhanced.
-     * Set to true (the default) for blanket coverage of timeout checks on all methods, loops
-     * and closures within all classes/script code.
-     *
-     * For even finer-grained control see {@code applyToAllMembers}.
-     *
-     * @see #applyToAllMembers()
-     */
-    boolean applyToAllClasses() default true
-
-    /**
-     * Set this to false if you have multiple methods/closures within a class or script and only
-     * want timeout checks on some of them (or you want different time constraints on different methods/closures).
-     * Place annotations with appropriate parameters on the methods/closures that you want enhanced.
-     * When false, {@code applyToAllClasses} is automatically set to false.
-     *
-     * Set to true (the default) for blanket coverage of timeout checks on all methods, loops
-     * and closures within the class/script.
-     *
-     * @since 2.2.0
-     * @see #applyToAllClasses()
-     */
-    boolean applyToAllMembers() default true
-
-    /**
-     * By default a time check is added to the start of all user-defined methods. To turn this off
-     * simply set this parameter to false.
-     */
-    boolean checkOnMethodStart() default true
-
-    /**
-     * The maximum elapsed time the script will be allowed to run for. By default it is measure in seconds
-     */
-    long value()
-
-    /**
-     * The TimeUnit of the value parameter. By default it is TimeUnit.SECONDS.
-     */
-    TimeUnit unit() default TimeUnit.SECONDS
-
-    /**
-     * The type of exception thrown when timeout is reached.
-     */
-    Class thrown() default TimeoutException
-}
-

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ToString.java b/src/main/groovy/transform/ToString.java
deleted file mode 100644
index 9fc4627..0000000
--- a/src/main/groovy/transform/ToString.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of {@code toString()} methods in classes.
- * The {@code @ToString} annotation instructs the compiler to execute an
- * AST transformation which adds the necessary toString() method.
- * <p>
- * It allows you to write classes in this shortened form:
- * <pre>
- * {@code @ToString}
- * class Customer {
- *     String first, last
- *     int age
- *     Date since = new Date()
- *     Collection favItems
- *     private answer = 42
- * }
- * println new Customer(first:'Tom', last:'Jones', age:21, favItems:['Books', 'Games'])
- * </pre>
- * Which will have this output:
- * <pre>
- * Customer(Tom, Jones, 21, Wed Jul 14 23:57:14 EST 2010, [Books, Games])
- * </pre>
- * There are numerous options to customize the format of the generated output.
- * E.g. if you change the first annotation to:
- * <pre>
- * {@code @ToString(includeNames=true)}
- * </pre>
- * Then the output will be:
- * <pre>
- * Customer(first:Tom, last:Jones, age:21, since:Wed Jul 14 23:57:50 EST 2010, favItems:[Books, Games])
- * </pre>
- * Or if you change the first annotation to:
- * <pre>
- * {@code @ToString(includeNames=true,includeFields=true,excludes="since,favItems")}
- * </pre>
- * Then the output will be:
- * <pre>
- * Customer(first:Tom, last:Jones, age:21, answer:42)
- * </pre>
- * If you have this example:
- * <pre class="groovyTestCase">
- * import groovy.transform.ToString
- * {@code @ToString} class NamedThing {
- *     String name
- * }
- * {@code @ToString}(includeNames=true,includeSuper=true)
- * class AgedThing extends NamedThing {
- *     int age
- * }
- * String agedThingAsString = new AgedThing(name:'Lassie', age:5).toString()
- * assert agedThingAsString == 'AgedThing(age:5, super:NamedThing(Lassie))'
- * </pre>
- * {@code @ToString} can also be used in conjunction with {@code @Canonical} and {@code @Immutable}.
- * <p>
- * If you want to omit fields or properties referring to <tt>null</tt>, you can use the <tt>ignoreNulls</tt> flag:
- * <pre class="groovyTestCase">
- * import groovy.transform.ToString
- * {@code @ToString(ignoreNulls = true)} class NamedThing {
- *     String name
- * }
- * assert new NamedThing(name: null).toString() == 'NamedThing()'
- * </pre>
- * <p>
- * By default the fully-qualified class name is used as part of the generated toString.
- * If you want to exclude the package, you can set the includePackage flag to false, e.g.:
- * <pre>
- * package my.company
- * import groovy.transform.ToString
- * {@code @ToString(includePackage = false)} class NamedThing {
- *     String name
- * }
- * println new NamedThing(name: "Lassie")
- * </pre>
- * Which results in:
- * <pre>
- * NamedThing(name: Lassie)
- * </pre>
- * If the includePackage flag is {@code true} (the default), then the output will be:
- * <pre>
- * my.company.NamedThing(name: Lassie)
- * </pre>
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------    
- * // Most simple implementation of toString.
- * import groovy.transform.ToString
- *
- * {@code @ToString}
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
- *
- * assert person.toString() == 'Person(mrhaki, [Groovy, Java])'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------    
- * // includeNames to output the names of the properties.
- * import groovy.transform.ToString
- *
- * &#64;ToString(includeNames=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
- *
- * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java])'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // includeFields to not only output properties, but also field values.
- * import groovy.transform.ToString
- *
- * &#64;ToString(includeNames=true, includeFields=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
- *
- * assert person.toString() == 'Person(name:mrhaki, likes:[Groovy, Java], active:false)'
- * </pre>
- * <pre>
- * //--------------------------------------------------------------------------    
- * // Use includeSuper to include properties from super class in output.
- * import groovy.transform.ToString
- *
- * &#64;ToString(includeNames=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * &#64;ToString(includeSuper=true, includeNames=true)
- * class Student extends Person {
- *     List courses
- * }
- *
- * def student = new Student(name: 'mrhaki', likes: ['Groovy', 'Java'], courses: ['IT', 'Business'])
- *
- * assert student.toString() == 'Student(courses:[IT, Business], super:Person(name:mrhaki, likes:[Groovy, Java]))'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------    
- * // excludes active field and likes property from output
- * import groovy.transform.ToString
- *
- * &#64;ToString(includeNames=true, includeFields=true, excludes='active,likes')
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * def person = new Person(name: 'mrhaki', likes: ['Groovy', 'Java'])
- *
- * assert person.toString() == 'Person(name:mrhaki)'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Don't include the package name in the output
- * package com.mrhaki.blog.groovy
- *
- * import groovy.transform.*
- *
- * &#64;ToString(includePackage=false)
- * class Course {
- *     String title
- *     Integer maxAttendees
- * }
- *
- * final Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
- *
- * assert course.toString() == 'Course(Groovy 101, 200)'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Don't use properties with null value.
- * package com.mrhaki.blog.groovy
- *
- * import groovy.transform.*
- *
- * &#64;ToString(ignoreNulls=true)
- * class Course {
- *     String title
- *     Integer maxAttendees
- * }
- *
- * final Course course = new Course(title: 'Groovy 101')
- *
- * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101)'
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Cache toString() result.
- * package com.mrhaki.blog.groovy
- *
- * import groovy.transform.*
- *
- * &#64;ToString(cache=true)
- * class Course {
- *     String title
- *     Integer maxAttendees
- * }
- *
- * Course course = new Course(title: 'Groovy 101', maxAttendees: 200)
- *
- * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
- *
- * // Value change will not be reflected in toString().
- * course.title = 'Grails with REST'
- *
- * assert course.toString() == 'com.mrhaki.blog.groovy.Course(Groovy 101, 200)'
- * assert course.title == 'Grails with REST'
- * </pre> 
- *
- * @author Paul King
- * @author Andre Steingress
- * @see groovy.transform.Immutable
- * @see groovy.transform.Canonical
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ToStringASTTransformation")
-public @interface ToString {
-    /**
-     * List of field and/or property names to exclude from generated toString.
-     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * List of field and/or property names to include within the generated toString.
-     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined; all fields and/or properties
-     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
-     * The special name 'super' can be used instead of using the 'includeSuper' flag.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * Whether to include the toString() of super in the generated toString.
-     */
-    boolean includeSuper() default false;
-
-    /**
-     * Whether to include super properties in the generated toString.
-     * @since 2.4.0
-     */
-    boolean includeSuperProperties() default false;
-
-    /**
-     * Whether to include names of properties/fields in the generated toString.
-     */
-    boolean includeNames() default false;
-
-    /**
-     * Include fields as well as properties in the generated toString.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Don't display any fields or properties with value <tt>null</tt>.
-     */
-    boolean ignoreNulls() default false;
-
-    /**
-     * Whether to include the fully-qualified class name (i.e. including
-     * the package) or just the simple class name in the generated toString.
-     * @since 2.0.6
-     */
-    boolean includePackage() default true;
-
-    /**
-     * Whether to include all properties (as per the JavaBean spec) in the generated toString.
-     * Groovy recognizes any field-like definitions with no explicit visibility as property definitions
-     * and always includes them in the {@code @ToString} generated toString (as well as auto-generating the
-     * appropriate getters and setters). Groovy also treats any explicitly created getXxx() or isYyy()
-     * methods as property getters as per the JavaBean specification. Old versions of Groovy did not.
-     * So set this flag to false for the old behavior or if you want to explicitly exclude such properties.
-     *
-     * @since 2.5
-     */
-    boolean allProperties() default true;
-
-    /**
-     * Whether to cache toString() calculations. You should only set this to true if
-     * you know the object is immutable (or technically mutable but never changed).
-     * @since 2.1.0
-     */
-    boolean cache() default false;
-
-    /**
-     * Whether to include all fields and/or properties in the generated toString, including those with names that
-     * are considered internal.
-     *
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Trait.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Trait.java b/src/main/groovy/transform/Trait.java
deleted file mode 100644
index de88180..0000000
--- a/src/main/groovy/transform/Trait.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to mark a class as being a trait.
- *
- * @since 2.3.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.trait.TraitASTTransformation")
-public @interface Trait {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TupleConstructor.java b/src/main/groovy/transform/TupleConstructor.java
deleted file mode 100644
index 89d0eb7..0000000
--- a/src/main/groovy/transform/TupleConstructor.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of tuple constructors in classes.
- * Should be used with care with other annotations which create constructors - see "Known
- * Limitations" for more details.
- * <p>
- * It allows you to write classes in this shortened form:
- * <pre class="groovyTestCase">
- * {@code @groovy.transform.TupleConstructor} class Customer {
- *     String first, last
- *     int age
- *     Date since
- *     Collection favItems
- * }
- * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:new Date(), favItems:['Books', 'Games'])
- * def c2 = new Customer('Tom', 'Jones', 21, new Date(), ['Books', 'Games'])
- * def c3 = new Customer('Tom', 'Jones')
- * </pre>
- * The {@code @TupleConstructor} annotation instructs the compiler to execute an
- * AST transformation which adds the necessary constructor method to your class.
- * <p>
- * A tuple constructor is created with a parameter for each property (and optionally field and
- * super properties).
- * A default value is provided (using Java's default values) for all parameters in the constructor.
- * Groovy's normal conventions then allows any number of parameters to be left off the end of the parameter list
- * including all of the parameters - giving a no-arg constructor which can be used with the map-style naming conventions.
- * <p>
- * The order of parameters is given by the properties of any super classes with most super first
- * (if {@code includeSuperProperties} is set) followed by the properties of the class followed
- * by the fields of the class (if {@code includeFields} is set). Within each grouping the order
- * is as attributes appear within the respective class.
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.TupleConstructor
- *
- * &#64;TupleConstructor()
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- * }
- *
- * def person = new Person('mrhaki', ['Groovy', 'Java'])
- *
- * assert person.name == 'mrhaki'
- * assert person.likes == ['Groovy', 'Java']
- *
- * person = new Person('mrhaki')
- *
- * assert person.name == 'mrhaki'
- * assert !person.likes
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // includeFields in the constructor creation.
- * import groovy.transform.TupleConstructor
- *
- * &#64;TupleConstructor(includeFields=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- *
- *     boolean isActivated() { active }
- * }
- *
- * def person = new Person('mrhaki', ['Groovy', 'Java'], true)
- *
- * assert person.name == 'mrhaki'
- * assert person.likes == ['Groovy', 'Java']
- * assert person.activated
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // use force attribute to force creation of constructor
- * // even if we define our own constructors.
- * import groovy.transform.TupleConstructor
- *
- * &#64;TupleConstructor(force=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- *
- *     Person(boolean active) {
- *         this.active = active
- *     }
- *
- *     boolean isActivated() { active }
- * }
- *
- * def person = new Person('mrhaki', ['Groovy', 'Java'])
- *
- * assert person.name == 'mrhaki'
- * assert person.likes == ['Groovy', 'Java']
- * assert !person.activated
- *
- * person = new Person(true)
- *
- * assert person.activated
- * </pre>
- * <pre class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // include properties and fields from super class.
- * import groovy.transform.TupleConstructor
- *
- * &#64;TupleConstructor(includeFields=true)
- * class Person {
- *     String name
- *     List likes
- *     private boolean active = false
- *
- *     boolean isActivated() { active }
- * }
- *
- * &#64;TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)
- * class Student extends Person {
- *     List courses
- * }
- *
- * def student = new Student('mrhaki', ['Groovy', 'Java'], true, ['IT'])
- *
- * assert student.name == 'mrhaki'
- * assert student.likes == ['Groovy', 'Java']
- * assert student.activated
- * assert student.courses == ['IT']
- * </pre>
- * <p>
- * Known Limitations:
- * <ul>
- * <li>This AST transform might become a no-op if you are defining your own constructors or
- * combining with other AST transforms which create constructors (e.g. {@code @InheritConstructors});
- * the order in which the particular transforms are processed becomes important in that case.
- * See the {@code force} attribute for further details about customizing this behavior.</li>
- * <li>This AST transform normally uses default parameter values which creates multiple constructors under
- * the covers. You should use with care if you are defining your own constructors or
- * combining with other AST transforms which create constructors (e.g. {@code @InheritConstructors});
- * the order in which the particular transforms are processed becomes important in that case.
- * See the {@code defaults} attribute for further details about customizing this behavior.</li>
- * <li>Groovy's normal map-style naming conventions will not be available if the first property (or field)
- * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property (or field)</li>
- * </ul>
- *
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.TupleConstructorASTTransformation")
-public @interface TupleConstructor {
-    /**
-     * List of field and/or property names to exclude from the constructor.
-     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * List of field and/or property names to include within the constructor.
-     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined;
-     * all fields are included if includes remains undefined and excludes is explicitly or implicitly
-     * an empty list.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * Include fields in the constructor.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Include properties in the constructor.
-     */
-    boolean includeProperties() default true;
-
-    /**
-     * Include fields from super classes in the constructor.
-     */
-    boolean includeSuperFields() default false;
-
-    /**
-     * Include properties from super classes in the constructor.
-     */
-    boolean includeSuperProperties() default false;
-
-    /**
-     * Should super properties be called within a call to the parent constructor
-     * rather than set as properties. Typically used in combination with {@code includeSuperProperties}.
-     * Can't be true if using {@code pre} with a {@code super} first statement.
-     */
-    boolean callSuper() default false;
-
-    /**
-     * By default, this annotation becomes a no-op if you provide your own constructor.
-     * By setting {@code force=true} then the tuple constructor(s) will be added regardless of
-     * whether existing constructors exist. It is up to you to avoid creating duplicate constructors.
-     */
-    boolean force() default false;
-
-    /**
-     * Used to set whether default value processing is enabled (the default) or disabled.
-     *
-     * By default, every constructor parameter is given a default value. This value will
-     * be Java's default for primitive types (zero or false) and null for Objects, unless
-     * an initial value is given when declaring the property or field. A consequence of
-     * this design is that you can leave off parameters from the right if the default
-     * value will suffice. As far as Java interoperability is concerned, Groovy will
-     * create additional constructors under the covers representing the constructors
-     * with parameters left off, all the way from the constructor with all arguments
-     * to the no-arg constructor.
-     *
-     * However, when set to false, default values are not allowed for properties and fields.
-     * Only the constructor containing all arguments will be provided.
-     * In particular, a no-arg constructor won't be provided and since this is currently
-     * used by Groovy when using named-arguments, the named-argument style won't be available.
-     */
-    boolean defaults() default true;
-
-    /**
-     * By default, properties are set directly using their respective field.
-     * By setting {@code useSetters=true} then a writable property will be set using its setter.
-     * If turning on this flag we recommend that setters that might be called are
-     * made null-safe wrt the parameter.
-     */
-    boolean useSetters() default false;
-
-    /**
-     * Whether to include all fields and/or properties within the constructor, including those with names that are
-     * considered internal.
-     *
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
-
-    /**
-     * A Closure containing statements which will be prepended to the generated constructor. The first statement
-     * within the Closure may be {@code super(someArgs)} in which case the no-arg super constructor won't be called.
-     *
-     * @since 2.5.0
-     */
-    Class pre() default Undefined.CLASS.class;
-
-    /**
-     * A Closure containing statements which will be appended to the end of the generated constructor. Useful for validation steps or tweaking the populated fields/properties.
-     *
-     * @since 2.5.0
-     */
-    Class post() default Undefined.CLASS.class;
-}


[20/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Delegate.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Delegate.java b/src/main/groovy/lang/Delegate.java
deleted file mode 100644
index 3d418c7..0000000
--- a/src/main/groovy/lang/Delegate.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import groovy.transform.Undefined;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to automatically delegate part of the functionality of an owner class to the
- * annotated delegation target. The target can be a field (or property) or a method's return value.
- * <p>
- * The delegate type is either the type of the annotated field (or property) or the return type of
- * the annotated method. The method can be thought of as a getter or factory method for the delegate.
- * All public instance methods present in the delegate type and not present in the owner class
- * will be added to owner class at compile time. The implementation of such automatically added
- * methods is code which calls through to the delegate as per the normal delegate pattern.
- * <p>
- * As an example, consider this code:
- * <pre class="groovyTestCase">
- * class Event {
- *     {@code @Delegate} Date when
- *     String title, url
- * }
- *
- * def gr8conf = new Event(title: "GR8 Conference",
- *                           url: "http://www.gr8conf.org",
- *                          when: Date.parse("yyyy/MM/dd", "2009/05/18"))
- *
- * def javaOne = new Event(title: "JavaOne",
- *                           url: "http://java.sun.com/javaone/",
- *                          when: Date.parse("yyyy/MM/dd", "2009/06/02"))
- *
- * assert gr8conf.before(javaOne.when)
- * </pre>
- *
- * In this example, the {@code Event} class will have a method called
- * {@code before(Date otherDate)} as well as other public methods of the
- * {@code Date} class.
- * The implementation of the {@code before()} method will look like this:
- * <pre>
- *     public boolean before(Date otherDate) {
- *         return when.before(otherDate);
- *     }
- * </pre>
- *
- * By default, the owner class will also be modified to implement any interfaces
- * implemented by the delegate type. So, in the example above, because {@code Date}
- * implements {@code Cloneable} the following will be true:
- *
- * <pre>
- * assert gr8conf instanceof Cloneable
- * </pre>
- *
- * This behavior can be disabled by setting the
- * annotation's {@code interfaces} element to false,
- * i.e. {@code @Delegate(interfaces = false)}, e.g. in the above
- * example, the delegate definition would become:
- * <pre>
- *     {@code @Delegate}(interfaces = false) Date when
- * </pre>
- * and the following would be true:
- * <pre>
- * assert !(gr8conf instanceof Cloneable)
- * </pre>
- *
- * If multiple delegation targets are used and the same method signature occurs
- * in more than one of the respective delegate types, then the delegate will be
- * made to the first defined target having that signature. If this does occur,
- * it might be regarded as a smell (or at least poor style) and it might be
- * clearer to do the delegation by long hand.
- * <p>
- * By default, methods of the delegate type marked as {@code @Deprecated} are
- * not automatically added to the owner class (but see the technical note
- * about interfaces below). You can force these methods to
- * be added by setting the annotation's {@code deprecated} element to true,
- * i.e. {@code @Delegate(deprecated = true)}.
- * <p>
- * For example, in the example above if we change the delegate definition to:
- * <pre>
- *     {@code @Delegate}(deprecated = true) Date when
- * </pre>
- * then the following additional lines will execute successfully (during 2009):
- * <pre>
- * assert gr8conf.year + 1900 == 2009
- * assert gr8conf.toGMTString().contains(" 2009 ")
- * </pre>
- * Otherwise these lines produce a groovy.lang.MissingPropertyException
- * or groovy.lang.MissingMethodException respectively as those two methods are
- * {@code @Deprecated} in {@code Date}.
- * <p>
- * <b>Technical notes</b>:
- * <ul>
- * <li>Static methods, synthetic methods or methods from the <code>GroovyObject</code> interface
- * are not candidates for delegation</li>
- * <li>Non-abstract non-static methods defined in the owner class or its superclasses take
- * precedence over methods with identical signatures from a {@code @Delegate} target</li>
- * <li>All methods defined in the owner class (including static, abstract or private etc.)
- * take precedence over methods with identical signatures from a {@code @Delegate} target</li>
- * <li>Recursive delegation to your own class is not allowed</li>
- * <li>Mixing of {@code @Delegate} with default method arguments is known not to work in some cases.
- * We recommend not using these features together.</li>
- * <li>When the delegate type is an interface, the {@code deprecated} attribute will be
- * ignored if the owner class implements that interface (i.e. you must set {@code interfaces=false}
- * if you want the {@code deprecated} attribute to be used). Otherwise, the resulting class would
- * not compile anyway without manually adding in any deprecated methods in the interface.</li>
- * <li>{@code @Delegate} can work in combination with {@code @Lazy} when annotating a field (or property)</li>
- * </ul>
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.FIELD, ElementType.METHOD})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.DelegateASTTransformation")
-public @interface Delegate {
-    /**
-     * @return true if owner class should implement interfaces implemented by delegate type
-     */
-    boolean interfaces() default true;
-
-    /**
-     * Whether to apply the delegate pattern to deprecated methods; to avoid compilation
-     * errors, this is ignored if the type of the delegate target is an interface and
-     * {@code interfaces=true}.
-     *
-     * @return true if owner class should delegate to methods annotated with @Deprecated
-     */
-    boolean deprecated() default false;
-
-    /**
-     * Whether to carry over annotations from the methods of the delegate
-     * to your delegating method. Currently Closure annotation members are
-     * not supported.
-     *
-     * @return true if generated delegate methods should keep method annotations
-     */
-    boolean methodAnnotations() default false;
-
-    /**
-     * Whether to carry over annotations from the parameters of delegate
-     * methods to your delegating method. Currently Closure annotation members are
-     * not supported.
-     *
-     * @return true if generated delegate methods should keep parameter annotations
-     */
-    boolean parameterAnnotations() default false;
-
-    /**
-     * List of method and/or property names to exclude when delegating.
-     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
-     * For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * If interfaces is true (the default), you will need to manually supply any methods excluded
-     * from delegation that are required for the interface.
-     * @since 2.2.0
-     */
-    String[] excludes() default {};
-
-
-    /**
-     * List of interfaces containing method signatures to exclude when delegating.
-     * Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used.
-     * If interfaces is true (the default), you will need to manually supply any methods excluded
-     * from delegation that are required for the interface.
-     * @since 2.3.0
-     */
-    Class[] excludeTypes() default {};
-
-    /**
-     * List of method and/or property names to include when delegating.
-     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
-     * For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined; all fields
-     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
-     * If interfaces is true (the default), you will need to manually supply any methods not included
-     * via delegation that are required for the interface.
-     * @since 2.2.0
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * List of interfaces containing method signatures to include when delegating.
-     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
-     * The default value is a special marker value indicating that no includeTypes are defined.
-     * If interfaces is true (the default), you will need to manually supply any methods excluded
-     * from delegation that are required for the interface.
-     * @since 2.3.0
-     */
-    Class[] includeTypes() default {Undefined.CLASS.class};
-
-    /**
-     * Whether to apply the delegate pattern to all methods, including those with names that are considered internal.
-     *
-     * @return true if owner class should delegate to methods which have internal names
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/DelegatesTo.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/DelegatesTo.java b/src/main/groovy/lang/DelegatesTo.java
deleted file mode 100644
index 54a5e36..0000000
--- a/src/main/groovy/lang/DelegatesTo.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation can be used by API or DSL writers to document parameters which accept a closure.
- * In that case, using this annotation, you can specify what the delegate type of the closure will
- * be. This is important for IDE support.
- * <p>
- * This annotation can also be used to help the type checker ({@link groovy.transform.TypeChecked})
- * which would not report errors then if the delegate is of the documented type. Of course, it is
- * also compatible with {@link groovy.transform.CompileStatic}.
- * <p>
- * Example:
- * <pre>
- * // Document the fact that the delegate of the closure will be an ExecSpec
- * ExecResult exec(@DelegatesTo(ExecSpec) Closure closure) { ... }
- * </pre>
- *
- * @author Cedric Champeau
- * @author Peter Niderwieser
- * @since 2.1.0
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.PARAMETER})
-public @interface DelegatesTo {
-    Class value() default Target.class;
-
-    /**
-     * The {@link Closure#resolveStrategy} used by the closure.
-     */
-    int strategy() default Closure.OWNER_FIRST;
-
-    /**
-     * The index of the generic type that will be the type of the closure's delegate.
-     * The generic types are considered with respect to the {@code @DelegatesTo.Target} annotated
-     * parameter for this usage, with the index starting at 0.
-     */
-    int genericTypeIndex() default -1;
-
-    /**
-     * In cases when there are multiple {@code @DelegatesTo.Target} annotated parameters, this
-     * member should be set to the {@link DelegatesTo.Target#value()} of the correct target.
-     */
-    String target() default "";
-
-    /**
-     * The type member should be used when the type of the delegate cannot
-     * be represented with {@link #value()}, {@link #genericTypeIndex()} or
-     * {@link #target()}. In this case, it is possible to use a String to represent
-     * the type, at the cost of potential uncaught errors at compile time if the
-     * type is invalid and increased compile time.
-     *
-     * @return a String representation of a type
-     * @since 2.4.0
-     */
-    String type() default "";
-
-    /**
-     * Parameter annotation used to specify the delegate for a {@code @DelegatesTo} annotated
-     * parameter of the same method.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @java.lang.annotation.Target({ElementType.PARAMETER})
-    public static @interface Target {
-
-        /**
-         * An identifier that should be used to disambiguate targets when there are
-         * multiple {@code @DelegatesTo.Target} annotated parameters.
-         */
-        String value() default "";
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/DelegatingMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/DelegatingMetaClass.java b/src/main/groovy/lang/DelegatingMetaClass.java
deleted file mode 100644
index ee2ade9..0000000
--- a/src/main/groovy/lang/DelegatingMetaClass.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * @author John Wilson
- */
-
-public class DelegatingMetaClass implements MetaClass, MutableMetaClass, GroovyObject {
-    protected MetaClass delegate;
-
-    public DelegatingMetaClass(final MetaClass delegate) {
-        this.delegate = delegate;
-    }
-
-    public DelegatingMetaClass(final Class theClass) {
-        this(GroovySystem.getMetaClassRegistry().getMetaClass(theClass));
-    }
-
-    public boolean isModified() {
-        return this.delegate instanceof MutableMetaClass && ((MutableMetaClass) this.delegate).isModified();
-    }
-
-    /* (non-Javadoc)
-    * @see groovy.lang.MetaClass#addNewInstanceMethod(java.lang.reflect.Method)
-    */
-    public void addNewInstanceMethod(Method method) {
-        if (delegate instanceof MutableMetaClass)
-            ((MutableMetaClass) delegate).addNewInstanceMethod(method);
-    }
-
-    /* (non-Javadoc)
-    * @see groovy.lang.MetaClass#addNewStaticMethod(java.lang.reflect.Method)
-    */
-    public void addNewStaticMethod(Method method) {
-        if (delegate instanceof MutableMetaClass)
-            ((MutableMetaClass) delegate).addNewStaticMethod(method);
-    }
-
-    public void addMetaMethod(MetaMethod metaMethod) {
-        if (delegate instanceof MutableMetaClass)
-            ((MutableMetaClass) delegate).addMetaMethod(metaMethod);
-    }
-
-    public void addMetaBeanProperty(MetaBeanProperty metaBeanProperty) {
-        if (delegate instanceof MutableMetaClass)
-            ((MutableMetaClass) delegate).addMetaBeanProperty(metaBeanProperty);
-    }
-
-    /* (non-Javadoc)
-    * @see groovy.lang.MetaClass#initialize()
-    */
-    public void initialize() {
-        delegate.initialize();
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#getAttribute(java.lang.Object, java.lang.String)
-     */
-    public Object getAttribute(Object object, String attribute) {
-        return delegate.getAttribute(object, attribute);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#getClassNode()
-     */
-    public ClassNode getClassNode() {
-        return delegate.getClassNode();
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#getMetaMethods()
-     */
-    public List<MetaMethod> getMetaMethods() {
-        return delegate.getMetaMethods();
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#getMethods()
-     */
-    public List<MetaMethod> getMethods() {
-        return delegate.getMethods();
-    }
-
-    public List<MetaMethod> respondsTo(Object obj, String name, Object[] argTypes) {
-        return delegate.respondsTo(obj, name, argTypes);
-    }
-
-    public List<MetaMethod> respondsTo(Object obj, String name) {
-        return delegate.respondsTo(obj, name);
-    }
-
-    public MetaProperty hasProperty(Object obj, String name) {
-        return delegate.hasProperty(obj, name);
-    }
-
-    /* (non-Javadoc)
-    * @see groovy.lang.MetaClass#getProperties()
-    */
-    public List<MetaProperty> getProperties() {
-        return delegate.getProperties();
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#getProperty(java.lang.Object, java.lang.String)
-     */
-    public Object getProperty(Object object, String property) {
-        return delegate.getProperty(object, property);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#invokeConstructor(java.lang.Object[])
-     */
-    public Object invokeConstructor(Object[] arguments) {
-        return delegate.invokeConstructor(arguments);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object)
-     */
-    public Object invokeMethod(Object object, String methodName, Object arguments) {
-        return delegate.invokeMethod(object, methodName, arguments);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object[])
-     */
-    public Object invokeMethod(Object object, String methodName, Object[] arguments) {
-        return delegate.invokeMethod(object, methodName, arguments);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#invokeStaticMethod(java.lang.Object, java.lang.String, java.lang.Object[])
-     */
-    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
-        return delegate.invokeStaticMethod(object, methodName, arguments);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#setAttribute(java.lang.Object, java.lang.String, java.lang.Object)
-     */
-    public void setAttribute(Object object, String attribute, Object newValue) {
-        delegate.setAttribute(object, attribute, newValue);
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClass#setProperty(java.lang.Object, java.lang.String, java.lang.Object)
-     */
-    public void setProperty(Object object, String property, Object newValue) {
-        delegate.setProperty(object, property, newValue);
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object obj) {
-        return delegate.equals(obj);
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    public String toString() {
-        return super.toString() + "[" + delegate.toString() + "]";
-    }
-
-    /**
-     * @deprecated
-     */
-    @Deprecated
-    public MetaMethod pickMethod(String methodName, Class[] arguments) {
-        return delegate.pickMethod(methodName, arguments);
-    }
-
-    public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
-        return this.delegate.getAttribute(sender, receiver, messageName, useSuper);
-    }
-
-    public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
-        return this.delegate.getProperty(sender, receiver, messageName, useSuper, fromInsideClass);
-    }
-
-    public MetaProperty getMetaProperty(String name) {
-        return this.delegate.getMetaProperty(name);
-    }
-
-    public MetaMethod getStaticMetaMethod(String name, Object[] args) {
-        return this.delegate.getStaticMetaMethod(name, args);
-    }
-
-    public MetaMethod getStaticMetaMethod(String name, Class[] argTypes) {
-        return this.delegate.getStaticMetaMethod(name, argTypes);
-    }
-
-    public MetaMethod getMetaMethod(String name, Object[] args) {
-        return this.delegate.getMetaMethod(name, args);
-    }
-
-    public Class getTheClass() {
-        return this.delegate.getTheClass();
-    }
-
-    public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass) {
-        return this.delegate.invokeMethod(sender, receiver, methodName, arguments, isCallToSuper, fromInsideClass);
-    }
-
-    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
-        return this.delegate.invokeMissingMethod(instance, methodName, arguments);
-    }
-
-    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
-        return this.delegate.invokeMissingProperty(instance, propertyName, optionalValue, isGetter);
-    }
-
-    public boolean isGroovyObject() {
-        return GroovyObject.class.isAssignableFrom(this.delegate.getTheClass());
-    }
-
-    public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
-        this.delegate.setAttribute(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
-    }
-
-    public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
-        this.delegate.setProperty(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
-    }
-
-    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
-        return this.delegate.selectConstructorAndTransformArguments(numberOfConstructors, arguments);
-    }
-
-    public void setAdaptee(MetaClass adaptee) {
-        this.delegate = adaptee;
-    }
-
-    public MetaClass getAdaptee() {
-        return this.delegate;
-    }
-
-    public Object invokeMethod(String name, Object args) {
-        try {
-            return getMetaClass().invokeMethod(this, name, args);
-        }
-        catch (MissingMethodException e) {
-            if (delegate instanceof GroovyObject)
-                return ((GroovyObject) delegate).invokeMethod(name, args);
-            else
-                throw e;
-        }
-    }
-
-    public Object getProperty(String property) {
-        try {
-            return getMetaClass().getProperty(this, property);
-        }
-        catch (MissingPropertyException e) {
-            if (delegate instanceof GroovyObject)
-                return ((GroovyObject) delegate).getProperty(property);
-            else
-                throw e;
-        }
-    }
-
-    public void setProperty(String property, Object newValue) {
-        try {
-            getMetaClass().setProperty(this, property, newValue);
-        }
-        catch (MissingPropertyException e) {
-            if (delegate instanceof GroovyObject)
-                ((GroovyObject) delegate).setProperty(property, newValue);
-            else
-                throw e;
-        }
-    }
-
-    public MetaClass getMetaClass() {
-        return InvokerHelper.getMetaClass(getClass());
-    }
-
-    public void setMetaClass(MetaClass metaClass) {
-        throw new UnsupportedOperationException();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/DeprecationException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/DeprecationException.java b/src/main/groovy/lang/DeprecationException.java
deleted file mode 100644
index 36ad893..0000000
--- a/src/main/groovy/lang/DeprecationException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Use this exception to mark a method implementation as being deprecated.
- *
- * Use the message to indicate the recommended way of calling the desired functionality.
- * Make throwing this exception the only line in the method implementation, i.e. unlike
- * the JavaDoc deprecated feature there is no relay to the new implementation but an early
- * and deliberate halt of execution ("fail early").
- *
- * This exception is supposed to be used in the SNAPSHOT releases only. Before release, all
- * references to this exception should be resolved and the according methods removed.
- *
- * @author Dierk Koenig
- */
-public class DeprecationException extends RuntimeException {
-
-    public DeprecationException(String message) {
-        super(message);
-    }
-
-    public DeprecationException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/EmptyRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/EmptyRange.java b/src/main/groovy/lang/EmptyRange.java
deleted file mode 100644
index b67b32e..0000000
--- a/src/main/groovy/lang/EmptyRange.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Constructing Ranges like 0..&lt;0
- */
-public class EmptyRange<T extends Comparable> extends AbstractList<T> implements Range<T> {
-
-    /**
-     * The value at which the range originates (may be <code>null</code>).
-     */
-    protected T at;
-
-    /**
-     * Creates a new {@link EmptyRange}.
-     *
-     * @param at the value at which the range starts (may be <code>null</code>).
-     */
-    public EmptyRange(T at) {
-        this.at = at;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public T getFrom() {
-        return at;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public T getTo() {
-        return at;
-    }
-
-    /**
-     * Never true for an empty range.
-     *
-     * @return <code>false</code>
-     */
-    @Override
-    public boolean isReverse() {
-        return false;
-    }
-
-    /**
-     * Never true for an empty range.
-     *
-     * @return <code>false</code>
-     */
-    @Override
-    public boolean containsWithinBounds(Object o) {
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String inspect() {
-        return InvokerHelper.inspect(at) + "..<" + InvokerHelper.inspect(at);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String toString() {
-        return (null == at)
-                ? "null..<null"
-                : at + "..<" + at;
-    }
-
-    /**
-     * Always 0 for an empty range.
-     *
-     * @return 0
-     */
-    @Override
-    public int size() {
-        return 0;
-    }
-
-    /**
-     * Always throws <code>IndexOutOfBoundsException</code> for an empty range.
-     *
-     * @throws IndexOutOfBoundsException always
-     */
-    @Override
-    public T get(int index) {
-        throw new IndexOutOfBoundsException("can't get values from Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException always
-     */
-    @Override
-    public boolean add(T o) {
-        throw new UnsupportedOperationException("cannot add to Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public boolean addAll(int index, Collection<? extends T> c) {
-        throw new UnsupportedOperationException("cannot add to Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public boolean addAll(Collection<? extends T> c) {
-        throw new UnsupportedOperationException("cannot add to Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public boolean remove(Object o) {
-        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public T remove(int index) {
-        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public boolean removeAll(Collection<?> c) {
-        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public boolean retainAll(Collection<?> c) {
-        throw new UnsupportedOperationException("cannot retainAll in Empty Ranges");
-    }
-
-    /**
-     * Always throws <code>UnsupportedOperationException</code> for an empty range.
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public T set(int index, T element) {
-        throw new UnsupportedOperationException("cannot set in Empty Ranges");
-    }
-
-    /**
-     * Always does nothing for an empty range.
-     */
-    @Override
-    public void step(int step, Closure closure) {
-    }
-
-    /**
-     * Always returns an empty list for an empty range.
-     */
-    @Override
-    public List<T> step(int step) {
-        return new ArrayList<T>();
-    }
-}


[09/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AutoClone.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoClone.java b/src/main/groovy/transform/AutoClone.java
deleted file mode 100644
index dc96181..0000000
--- a/src/main/groovy/transform/AutoClone.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of {@code Cloneable} classes.
- * The {@code @AutoClone} annotation instructs the compiler to execute an
- * AST transformation which adds a public {@code clone()} method and adds
- * {@code Cloneable} to the list of interfaces which the class implements.
- * <p>
- * Because the JVM doesn't have a one-size fits all cloning strategy, several
- * customizations exist for the cloning implementation. By default, the {@code clone()}
- * method will call {@code super.clone()} before calling {@code clone()} on each
- * {@code Cloneable} property of the class.
- * <p>
- * Example usage:
- * <pre>
- * import groovy.transform.AutoClone
- * {@code @AutoClone}
- * class Person {
- *   String first, last
- *   List favItems
- *   Date since
- * }
- * </pre>
- * Which will create a class equivalent to the following:
- * <pre>
- * class Person implements Cloneable {
- *   ...
- *   public Person clone() throws CloneNotSupportedException {
- *     Person result = (Person) super.clone()
- *     result.favItems = favItems instanceof Cloneable ? (List) favItems.clone() : favItems
- *     result.since = (Date) since.clone()
- *     return result
- *   }
- *   ...
- * }
- * </pre>
- * Which can be used as follows:
- * <pre>
- * def p = new Person(first:'John', last:'Smith', favItems:['ipod', 'shiraz'], since:new Date())
- * def p2 = p.clone()
- *
- * assert p instanceof Cloneable
- * assert p.favItems instanceof Cloneable
- * assert p.since instanceof Cloneable
- * assert !(p.first instanceof Cloneable)
- *
- * assert !p.is(p2)
- * assert !p.favItems.is(p2.favItems)
- * assert !p.since.is(p2.since)
- * assert p.first.is(p2.first)
- * </pre>
- * In the above example, {@code super.clone()} is called which in this case
- * calls {@code clone()} from {@code java.lang.Object}. This does a bit-wise
- * copy of all the properties (references and primitive values). Properties
- * like {@code first} has type {@code String} which is not {@code Cloneable}
- * so it is left as the bit-wise copy. Both {@code Date} and {@code ArrayList}
- * are {@code Cloneable} so the {@code clone()} method on each of those properties
- * will be called. For the list, a shallow copy is made during its {@code clone()} method.
- * <p>
- * If your classes require deep cloning, it is up to you to provide the appropriate
- * deep cloning logic in the respective {@code clone()} method for your class.
- * <p>
- * If one of your properties contains an object that doesn't support cloning
- * or attempts deep copying of a data structure containing an object that
- * doesn't support cloning, then a {@code CloneNotSupportedException} may occur
- * at runtime.
- * <p>
- * Another popular cloning strategy is known as the copy constructor pattern.
- * If any of your fields are {@code final} and {@code Cloneable} you should set
- * {@code style=COPY_CONSTRUCTOR} which will then use the copy constructor pattern.
- * Here is an example making use of the copy constructor pattern:
- * <pre>
- * import groovy.transform.AutoClone
- * import static groovy.transform.AutoCloneStyle.*
- * {@code @AutoClone(style=COPY_CONSTRUCTOR)}
- * class Person {
- *   final String first, last
- *   final Date birthday
- * }
- * {@code @AutoClone(style=COPY_CONSTRUCTOR)}
- * class Customer extends Person {
- *   final int numPurchases
- *   final List favItems
- * }
- * </pre>
- * Which will create classes equivalent to the following:
- * <pre>
- * class Person implements Cloneable {
- *   ...
- *   protected Person(Person other) throws CloneNotSupportedException {
- *     first = other.first
- *     last = other.last
- *     birthday = (Date) other.birthday.clone()
- *   }
- *   public Person clone() throws CloneNotSupportedException {
- *     return new Person(this)
- *   }
- *   ...
- * }
- * class Customer extends Person {
- *   ...
- *   protected Customer(Customer other) throws CloneNotSupportedException {
- *     super(other)
- *     numPurchases = other.numPurchases
- *     favItems = other.favItems instanceof Cloneable ? (List) other.favItems.clone() : other.favItems
- *   }
- *   public Customer clone() throws CloneNotSupportedException {
- *     return new Customer(this)
- *   }
- *   ...
- * }
- * </pre>
- * If you use this style on a child class, the parent class must
- * also have a copy constructor (created using this annotation or by hand).
- * This approach can be slightly slower than the traditional cloning approach
- * but the {@code Cloneable} fields of your class can be final. When using the copy constructor style,
- * you can provide your own custom constructor by hand if you wish. If you do so, it is up to you to
- * correctly copy, clone or deep clone the properties of your class.
- * <p>
- * As a variation of the last two styles, if you set {@code style=SIMPLE}
- * then the no-arg constructor will be called followed by setting the
- * individual properties (and/or fields) calling {@code clone()} if the
- * property/field implements {@code Cloneable}. Here is an example:
- * <pre>
- * import groovy.transform.AutoClone
- * import static groovy.transform.AutoCloneStyle.*
- * {@code @AutoClone(style=SIMPLE)}
- * class Person {
- *   final String first, last
- *   final Date birthday
- * }
- * {@code @AutoClone(style=SIMPLE)}
- * class Customer {
- *   final List favItems
- * }
- * </pre>
- * Which will create classes equivalent to the following:
- * <pre>
- * class Person implements Cloneable {
- *   ...
- *   public Person clone() throws CloneNotSupportedException {
- *     def result = new Person()
- *     copyOrCloneMembers(result)
- *     return result
- *   }
- *   protected void copyOrCloneMembers(Person other) {
- *     other.first = first
- *     other.last = last
- *     other.birthday = (Date) birthday.clone()
- *   }
- *   ...
- * }
- * class Customer extends Person {
- *   ...
- *   public Customer clone() throws CloneNotSupportedException {
- *     def result = new Customer()
- *     copyOrCloneMembers(result)
- *     return result
- *   }
- *   protected void copyOrCloneMembers(Customer other) {
- *     super.copyOrCloneMembers(other)
- *     other.favItems = favItems instanceof Cloneable ? (List) favItems.clone() : favItems
- *   }
- *   ...
- * }
- * </pre>
- * You would typically use this style only for base classes where you didn't
- * want the normal {@code Object} {@code clone()} method to be called and
- * you would typically need to use the {@code SIMPLE} style for any child classes.
- * <p>
- * As a final example, if your class already implements the {@code Serializable}
- * or {@code Externalizable} interface, you can choose the following cloning style:
- * <pre>
- * {@code @AutoClone(style=SERIALIZATION)}
- * class Person implements Serializable {
- *   String first, last
- *   Date birthday
- * }
- * </pre>
- * which outputs a class with the following form:
- * <pre>
- * class Person implements Cloneable, Serializable {
- *   ...
- *   Person clone() throws CloneNotSupportedException {
- *     def baos = new ByteArrayOutputStream()
- *     baos.withObjectOutputStream{ it.writeObject(this) }
- *     def bais = new ByteArrayInputStream(baos.toByteArray())
- *     bais.withObjectInputStream(getClass().classLoader){ (Person) it.readObject() }
- *   }
- *   ...
- * }
- * </pre>
- * This will output an error if your class doesn't implement one of
- * {@code Serializable} or {@code Externalizable}, will typically be
- * significantly slower than the other approaches, also doesn't
- * allow fields to be final, will take up more memory as even immutable classes
- * like String will be cloned but does have the advantage that it performs
- * deep cloning automatically.
- * <p>
- * Further references on cloning:
- * <ul>
- * <li><a href="http://www.codeguru.com/java/tij/tij0128.shtml">http://www.codeguru.com/java/tij/tij0128.shtml</a>
- * <li><a href="http://www.artima.com/objectsandjava/webuscript/ClonCollInner1.html">http://www.artima.com/objectsandjava/webuscript/ClonCollInner1.html</a>
- * <li><a href="http://courses.dce.harvard.edu/~cscie160/JDCTipsCloning">http://courses.dce.harvard.edu/~cscie160/JDCTipsCloning</a>
- * <li><a href="http://www.agiledeveloper.com/articles/cloning072002.htm">http://www.agiledeveloper.com/articles/cloning072002.htm</a>
- * </ul>
- *
- * @author Paul King
- * @see AutoCloneStyle
- * @see ExternalizeMethods
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoCloneASTTransformation")
-public @interface AutoClone {
-    /**
-     * Comma separated list of property (and/or field) names to exclude from cloning.
-     * For convenience, a String with comma separated names can be used in addition
-     * to an array (using Groovy's literal list notation) of String values.
-     * <p>
-     * NOTE: When using the {@code CLONE} style, property (and/or field) copying might occur as part of
-     * calling {@code super.clone()} which will ignore this list. You can then use this list to
-     * streamline the provided {@code clone()} implementation by selecting which Cloneable properties
-     * (and/or fields) will have a subsequent call to their {@code clone()} method. If you have
-     * immutable properties (and/or fields) this can be useful as the extra {@code clone()} will
-     * not be necessary and cloning will be more efficient.
-     * <p>
-     * NOTE: This doesn't affect property (and/or field) copying that might occur as part
-     * of serialization when using the {@code SERIALIZATION} style, i.e. this flag is ignored;
-     * instead adjust your serialization code to include or exclude the desired
-     * properties (and/or fields) which should carry over during cloning.
-     */
-    String[] excludes() default {};
-
-    /**
-     * Include fields as well as properties when cloning.
-     * <p>
-     * NOTE: When using the {@code CLONE} style, field copying might occur as part of
-     * calling {@code super.clone()} and might be all you require; if you turn on
-     * this flag, the provided {@code clone()} implementation will also
-     * subsequently call {@code clone()} for each {@code Cloneable} field which can be
-     * useful if you have mutable fields.
-     * <p>
-     * NOTE: This doesn't affect field copying that might occur as part of
-     * serialization when using the {@code SERIALIZATION} style, i.e. this flag is ignored;
-     * instead adjust your serialization code to include or exclude your fields.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Style to use when cloning.
-     */
-    AutoCloneStyle style() default AutoCloneStyle.CLONE;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AutoCloneStyle.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoCloneStyle.java b/src/main/groovy/transform/AutoCloneStyle.java
deleted file mode 100644
index ef9be51..0000000
--- a/src/main/groovy/transform/AutoCloneStyle.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  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 groovy.transform;
-
-/**
- * Intended style to use for cloning when using the {@code @}AutoClone annotation.
- *
- * @author Paul King
- * @since 1.8.0
- * @see groovy.transform.AutoClone
- */
-public enum AutoCloneStyle {
-    /**
-     * Uses only cloning.
-     */
-    CLONE,
-
-    /**
-     * Uses the no-arg constructor followed by property/field copying/cloning.
-     */
-    SIMPLE,
-
-    /**
-     * Uses the copy constructor pattern.
-     */
-    COPY_CONSTRUCTOR,
-
-    /**
-     * Uses serialization to clone.
-     */
-    SERIALIZATION
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AutoExternalize.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoExternalize.groovy b/src/main/groovy/transform/AutoExternalize.groovy
deleted file mode 100644
index d1356b9..0000000
--- a/src/main/groovy/transform/AutoExternalize.groovy
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  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 groovy.transform
-
-/**
- * Class annotation used to assist in the creation of {@code Externalizable} classes.
- * The {@code @AutoExternalize} annotation instructs the compiler to execute an
- * AST transformation which adds {@code writeExternal()} and {@code readExternal()} methods
- * to a class and adds {@code Externalizable} to the interfaces which the class implements.
- * The {@code writeExternal()} method writes each property (or field) for the class while the
- * {@code readExternal()} method will read each one back in the same order. Properties or fields
- * marked as {@code transient} are ignored.
- * <p>
- * Example usage:
- * <pre>
- * import groovy.transform.*
- * {@code @AutoExternalize}
- * class Person {
- *   String first, last
- *   List favItems
- *   Date since
- * }
- * </pre>
- * Which will create a class of the following form:
- * <pre>
- * class Person implements Externalizable {
- *   ...
- *   public void writeExternal(ObjectOutput out) throws IOException {
- *     out.writeObject(first)
- *     out.writeObject(last)
- *     out.writeObject(favItems)
- *     out.writeObject(since)
- *   }
- *
- *   public void readExternal(ObjectInput oin) {
- *     first = oin.readObject()
- *     last = oin.readObject()
- *     favItems = oin.readObject()
- *     since = oin.readObject()
- *   }
- *   ...
- * }
- * </pre>
- * <p>
- * The {@code @AutoExternalize} transform is implemented as a combination of the {@code @ExternalizeMethods} and {@code @ExternalizeVerifier} transforms.
- *
- * @since 1.8.0
- */
-@AnnotationCollector([ExternalizeMethods, ExternalizeVerifier])
-@interface AutoExternalize { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AutoFinal.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoFinal.java b/src/main/groovy/transform/AutoFinal.java
deleted file mode 100644
index 58ce3ba..0000000
--- a/src/main/groovy/transform/AutoFinal.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to automatically add the final qualifier to method, constructor,
- * and closure parameters.
- * <p>The annotation can be placed at the class level in which case it applies to
- * all methods, constructors, and closures within the class and any inner classes.
- * It can also be applied to an individual method, constructor, field with a
- * Closure initial value or a Closure assigned to a local variable. In the case
- * of fields (or local variables) it only adjusts the parameters of the referenced
- * Closure not the field (or local variable) itself.
- * <p>If you wish to automatically apply the
- * annotation to all classes of a project, consider using
- * {@code groovyc --configscript}. Google "Customising The Groovy Compiler",
- * or see {@link CompilerConfiguration} for further details.
- * This will ensure that all arguments will automatically be final,
- * completely eliminating the need to clutter the code with final keywords
- * in any parameter list.
- * <p>
- * <em>Example usage:</em>
- * <pre class="groovyTestCase">
- * {@code @groovy.transform.AutoFinal}
- * class Person {
- *     final String first, last
- *     Person(String first, String last) {
- *         this.first = first
- *         this.last = last
- *     }
- *     String fullName(boolean reversed = false, String separator = ' ') {
- *         final concatCls = { String n0, String n1 -> "$n0$separator$n1" }
- *         concatCls(reversed ? last : first, reversed ? first : last)
- *     }
- * }
- *
- * final js = new Person('John', 'Smith')
- * assert js.fullName() == 'John Smith'
- * assert js.fullName(true, ', ') == 'Smith, John'
- * </pre>
- * for this case, the constructor for the <code>Person</code> class will be
- * equivalent to the following code:
- * <pre>
- * Person(final String first, final String last) {
- *   ...
- * }
- * </pre>
- * And after normal default parameter processing takes place, the following overloaded methods will exist:
- * <pre>
- * String fullName(final boolean reversed, final String separator) { ... }
- * String fullName(final boolean reversed) { fullName(reversed, ' ') }
- * String fullName() { fullName(false) }
- * </pre>
- * and the closure will have become:
- * <pre>
- * { final String n0, final String n1 -> "$n0$separator$n1" }
- * </pre>
- *
- * @since 2.5.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoFinalASTTransformation")
-public @interface AutoFinal {
-    /**
-     * Indicates that adding final to parameters should not be applied on this node.
-     * <p>Normally not required since leaving off the annotation will achieve the same affect.
-     * However, it can be useful for selectively disabling this annotation in just a small part
-     * of an otherwise annotated class. As an example, it would make sense to set this to {@code false} on
-     * a method which altered parameters in a class already marked as {@code @AutoFinal}.
-     * All nodes in the class except that single method would be processed.
-     */
-    boolean enabled() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/AutoImplement.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoImplement.java b/src/main/groovy/transform/AutoImplement.java
deleted file mode 100644
index 57e8152..0000000
--- a/src/main/groovy/transform/AutoImplement.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to provide default dummy methods for a class extending an abstract super class or
- * implementing one or more interfaces.
- * <p>
- * Example usage:
- * <pre>
- * import groovy.transform.AutoImplement
- *
- * {@code @AutoImplement}
- * class EmptyStringIterator implements Iterator<String> {
- *     boolean hasNext() { false }
- * }
- *
- * assert !new EmptyStringIterator().hasNext()
- * </pre>
- * In the above example, since {@code hasNext} returns false, the {@code next} method
- * should never be called, so any dummy implementation would do for {@code next}.
- * The "empty" implementation provided by default when using {@code @AutoImplement}
- * will suffice - which effectively returns {@code null} in Groovy for non-void,
- * non-primitive methods.
- *
- * As a point of interest, the default implementation for methods returning primitive
- * types is to return the default value (which incidentally never satisfies Groovy truth).
- * For {@code boolean} this means returning {@code false}, so for the above example we
- * could have (albeit perhaps less instructive of our intent) by just using:
- * <pre>
- * {@code @AutoImplement}
- * class EmptyStringIterator implements Iterator<String> { }
- * </pre>
- * If we didn't want to assume that callers of our {@code EmptyStringIterator} correctly followed
- * the {@code Iterator} contract, then we might want to guard against inappropriate calls to {@code next}.
- * Rather than just returning {@code null}, we might want to throw an exception. This is easily done using
- * the {@code exception} annotation attribute as shown below:
- * <pre>
- * import groovy.transform.AutoImplement
- * import static groovy.test.GroovyAssert.shouldFail
- *
- * {@code @AutoImplement}(exception=UnsupportedOperationException)
- * class EmptyStringIterator implements Iterator<String> {
- *     boolean hasNext() { false }
- * }
- *
- * shouldFail(UnsupportedOperationException) {
- *     new EmptyStringIterator().next()
- * }
- * </pre>
- * All implemented methods will throw an instance of this exception constructed using its no-arg constructor.
- *
- * You can also supply a single {@code message} annotation attribute in which case the message will be passed
- * as an argument during exception construction as shown in the following example:
- * <pre>
- * {@code @AutoImplement}(exception=UnsupportedOperationException, message='Not supported for this empty iterator')
- * class EmptyStringIterator implements Iterator<String> {
- *     boolean hasNext() { false }
- * }
- *
- * def ex = shouldFail(UnsupportedOperationException) {
- *     new EmptyStringIterator().next()
- * }
- * assert ex.message == 'Not supported for this empty iterator'
- * </pre>
- * Finally, you can alternatively supply a {@code code} annotation attribute in which case a closure
- * block can be supplied which should contain the code to execute for all implemented methods. This can be
- * seen in the following example:
- * <pre>
- * {@code @AutoImplement}(code = { throw new UnsupportedOperationException("Not supported for ${getClass().simpleName}") })
- * class EmptyStringIterator implements Iterator<String> {
- *     boolean hasNext() { false }
- * }
- *
- * def ex = shouldFail(UnsupportedOperationException) {
- *     new EmptyStringIterator().next()
- * }
- * assert ex.message == 'Not supported for EmptyStringIterator'
- * </pre>
- *
- * @since 2.5.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoImplementASTTransformation")
-public @interface AutoImplement {
-    /**
-     * If defined, all unimplemented methods will throw this exception.
-     * Will be ignored if {@code code} is defined.
-     */
-    Class<? extends RuntimeException> exception() default Undefined.EXCEPTION.class;
-
-    /**
-     * If {@code exception} is defined, {@code message} can be used to specify the exception message.
-     * Will be ignored if {@code code} is defined or {@code exception} isn't defined.
-     */
-    String message() default Undefined.STRING;
-
-    /**
-     * If defined, all unimplemented methods will execute the code found within the supplied closure.
-     */
-    Class code() default Undefined.CLASS.class;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/BaseScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/BaseScript.java b/src/main/groovy/transform/BaseScript.java
deleted file mode 100644
index 227333a..0000000
--- a/src/main/groovy/transform/BaseScript.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import groovy.lang.Script;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Variable annotation used for changing the base script class of the current script.
- * <p>
- * The type of the variable annotated with {@code @BaseScript} must extend {@link groovy.lang.Script}.
- * It will be used as the base script class.
- * The annotated variable will become shortcut to <code>this</code> object.
- * Using this annotation will override base script set by Groovy compiler or
- * {@link org.codehaus.groovy.control.CompilerConfiguration} of {@link groovy.lang.GroovyShell}
- * Example usage:
- * <pre>
- * abstract class CustomScript extends Script {
- *     int getTheMeaningOfLife() { 42 }
- * }
- *
- * &#64;BaseScript CustomScript baseScript
- *
- * assert baseScript == this
- * assert theMeaningOfLife == 42
- * assert theMeaningOfLife == baseScript.theMeaningOfLife
- * </pre>
- * In this example, the base script of the current script will be changed to 
- * <code>CustomScript</code> allowing usage of <code>getTheMeaningOfLife()</code>
- * method. <code>baseScript</code> variable will become typed shortcut for 
- * <code>this</code> object which enables better IDE support.
- * </p><p>
- * The custom base script may implement the run() method and specify a different
- * method name to be used for the script body by declaring a single abstract method.
- * For example:
- * <pre>
- * abstract class CustomScriptBodyMethod extends Script {
- *     abstract def runScript()
- *     def preRun() { println "preRunning" }
- *     def postRun() { println "postRunning" }
- *     def run() {
- *         preRun()
- *         try {
- *             3.times { runScript() }
- *         } finally {
- *             postRun()
- *         }
- *     }
- * }
- *
- * {@code @BaseScript} CustomScriptBodyMethod baseScript
- * println "Script body run"
- * </pre>
- * That will produce the following output:
- * <pre>
- * preRunning
- * Script body run
- * Script body run
- * Script body run
- * postRunning
- * </pre>
- *
- * Note that while you can declare arguments for the script body's method, as
- * the AST is currently implemented they are not accessible in the script body code.
- * </p>
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * // Simple Car class to save state and distance.
- * class Car {
- *     String state
- *     Long distance = 0
- * }
- *
- * // Custom Script with methods that change the Car's state.
- * // The Car object is passed via the binding.
- * abstract class CarScript extends Script {
- *     def start() {
- *         this.binding.car.state = 'started'
- *     }
- *
- *     def stop() {
- *         this.binding.car.state = 'stopped'
- *     }
- *
- *     def drive(distance) {
- *         this.binding.car.distance += distance
- *     }
- * }
- *
- *
- * // Define Car object here, so we can use it in assertions later on.
- * def car = new Car()
- * // Add to script binding (CarScript references this.binding.car).
- * def binding = new Binding(car: car)
- *
- * // Configure the GroovyShell.
- * def shell = new GroovyShell(this.class.classLoader, binding)
- *
- * // Simple DSL to start, drive and stop the car.
- * // The methods are defined in the CarScript class.
- * def carDsl = '''
- * start()
- * drive 20
- * stop()
- * '''
- *
- *
- * // Run DSL script.
- * shell.evaluate """
- * // Use BaseScript annotation to set script
- * // for evaluating the DSL.
- * &#64;groovy.transform.BaseScript CarScript carScript
- *
- * $carDsl
- * """
- *
- * // Checks to see that Car object has changed.
- * assert car.distance == 20
- * assert car.state == 'stopped'
- * </pre>
- * 
- * @author Paul King
- * @author Vladimir Orany
- * @author Jim White
- * @since 2.2.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.TYPE /*, ElementType.IMPORT*/})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.BaseScriptASTTransformation")
-public @interface BaseScript {
-    Class value() default Script.class;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Canonical.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Canonical.groovy b/src/main/groovy/transform/Canonical.groovy
deleted file mode 100644
index 6f99c80..0000000
--- a/src/main/groovy/transform/Canonical.groovy
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  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 groovy.transform
-/**
- * The {@code @Canonical} meta-annotation combines the {@code @EqualsAndHashCode},
- * {@code @ToString} and {@code @TupleConstructor} annotations. It is used to assist in
- * the creation of mutable classes. It instructs the compiler to execute AST transformations
- * which add positional constructors, equals, hashCode and a pretty print toString to your class.
- * <p>
- * You can write classes in this shortened form:
- * <pre class="groovyTestCase">
- * import groovy.transform.Canonical
- * {@code @Canonical} class Customer {
- *     String first, last
- *     int age
- *     Date since
- *     Collection favItems = ['Food']
- *     def object 
- * }
- * def d = new Date()
- * def anyObject = new Object()
- * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:d, favItems:['Books', 'Games'], object: anyObject)
- * def c2 = new Customer('Tom', 'Jones', 21, d, ['Books', 'Games'], anyObject)
- * assert c1 == c2
- * </pre>
- *
- * You don't need to provide all arguments in constructor calls. If using named parameters, any property names not
- * referenced will be given their default value (as per Java's default unless an explicit initialization constant is
- * provided when defining the property). If using a tuple constructor, parameters are supplied in the order in which
- * the properties are defined. Supplied parameters fill the tuple from the left. Any parameters missing on the right
- * are given their default value.
- * <pre>
- * def c3 = new Customer(last: 'Jones', age: 21)
- * def c4 = new Customer('Tom', 'Jones')
- *
- * assert null == c3.since
- * assert 0 == c4.age
- * assert c3.favItems == ['Food'] && c4.favItems == ['Food']
- * </pre>
- *
- * If you don't need all of the functionality of {@code @Canonical}, you can simply directly use one or more of the individual
- * annotations which {@code @Canonical} aggregates.
- * In addition, you can use {@code @Canonical} in combination with explicit use one or more of the individual annotations in
- * cases where you need to further customize the annotation attributes.
- * Any applicable annotation attributes from {@code @Canonical} missing from the explicit annotation will be merged
- * but any existing annotation attributes within the explicit annotation take precedence. So, for example in this case here:
- * <pre>
- * {@code @Canonical}(includeNames=true, excludes='c')
- * {@code @}{@link ToString}(excludes='a,b')
- * class MyClass { ... }
- * </pre>
- * The generated {@code toString} will include property names and exclude the {@code a} and {@code b} properties.
- * <p>
- * A class created using {@code @Canonical} has the following characteristics:
- * <ul>
- * <li>A no-arg constructor is provided which allows you to set properties by name using Groovy's normal bean conventions.
- * <li>Tuple-style constructors are provided which allow you to set properties in the same order as they are defined.
- * <li>Default {@code equals}, {@code hashCode} and {@code toString} methods are provided based on the property values.
- * See the GroovyDoc for the individual annotations for more details.
- * <p>
- * If you want similar functionality to what this annotation provides but also require immutability, see the
- * {@code @}{@link Immutable} annotation.
- * 
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * &#64;Canonical
- * class Building {
- *     String name
- *     int floors
- *     boolean officeSpace
- * }
- *
- * // Constructors are added.
- * def officeSpace = new Building('Initech office', 1, true)
- *
- * // toString() added.
- * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
- *
- * // Default values are used if constructor
- * // arguments are not assigned.
- * def theOffice = new Building('Wernham Hogg Paper Company')
- * assert theOffice.floors == 0
- * theOffice.officeSpace = true
- *
- * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
- *
- * // equals() method is added.
- * assert anotherOfficeSpace == officeSpace
- *
- * // equals() and hashCode() are added, so duplicate is not in Set.
- * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
- * assert offices.size() == 2 
- * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
- *
- * &#64;Canonical
- * &#64;ToString(excludes='age')  // Customize one of the transformations.
- * class Person {
- *     String name
- *     int age
- * }
- *
- * def mrhaki = new Person('mrhaki', 37)
- * assert mrhaki.toString() == 'Person(mrhaki)'
- * </pre>
- *
- * @see groovy.transform.EqualsAndHashCode
- * @see groovy.transform.ToString
- * @see groovy.transform.TupleConstructor
- * @see groovy.transform.Immutable
- * @since 1.8.0
- */
-@AnnotationCollector(value=[ToString, TupleConstructor, EqualsAndHashCode], mode=AnnotationCollectorMode.PREFER_EXPLICIT_MERGED)
-public @interface Canonical { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/CompilationUnitAware.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/CompilationUnitAware.java b/src/main/groovy/transform/CompilationUnitAware.java
deleted file mode 100644
index b609f43..0000000
--- a/src/main/groovy/transform/CompilationUnitAware.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.control.CompilationUnit;
-
-/**
- * This interface is for AST transformations which must be aware of the compilation unit where they are applied.
- *
- * @author Cedric Champeau
- */
-public interface CompilationUnitAware {
-    void setCompilationUnit(CompilationUnit unit);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/CompileDynamic.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/CompileDynamic.groovy b/src/main/groovy/transform/CompileDynamic.groovy
deleted file mode 100644
index c5247d4..0000000
--- a/src/main/groovy/transform/CompileDynamic.groovy
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  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 groovy.transform
-
-import java.lang.annotation.Documented
-
-/**
- * An annotation which is just a shortcut for @CompileStatic(TypeCheckingMode.SKIP).
- * This can be used for example if you statically compile a full class but you want to skip
- * some methods without having to use the full annotation.
- *
- * @author Cedric Champeau
- * @since 2.1.0
- */
-@Documented
-@AnnotationCollector(processor = "org.codehaus.groovy.transform.CompileDynamicProcessor")
-public @interface CompileDynamic {
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/CompileStatic.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/CompileStatic.java b/src/main/groovy/transform/CompileStatic.java
deleted file mode 100644
index 16dbc33..0000000
--- a/src/main/groovy/transform/CompileStatic.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This will let the Groovy compiler use compile time checks in the style of Java
- * then perform static compilation, thus bypassing the Groovy meta object protocol.
- * <p>
- * When a class is annotated, all methods, properties, files, inner classes, etc.
- * of the annotated class will be type checked. When a method is annotated, static
- * compilation applies only to items (closures and anonymous inner classes) within
- * the method.
- * <p>
- * By using {@link TypeCheckingMode#SKIP}, static compilation can be skipped on an
- * element within a class or method otherwise marked with CompileStatic. For example
- * a class can be annotated with CompileStatic, and a method within can be marked
- * to skip static checking to use dynamic language features.
- *
- * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
- * @author Cedric Champeau
- *
- * @see CompileDynamic
- */
-@Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({   ElementType.METHOD,         ElementType.TYPE,
-            ElementType.CONSTRUCTOR
-})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.sc.StaticCompileTransformation")
-public @interface CompileStatic {
-    TypeCheckingMode value() default TypeCheckingMode.PASS;
-
-    /**
-     * The list of (classpath resources) paths to type checking DSL scripts, also known
-     * as type checking extensions.
-     * @return an array of paths to groovy scripts that must be on compile classpath
-     */
-    String[] extensions() default {};
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ConditionalInterrupt.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ConditionalInterrupt.groovy b/src/main/groovy/transform/ConditionalInterrupt.groovy
deleted file mode 100644
index 66aa64c..0000000
--- a/src/main/groovy/transform/ConditionalInterrupt.groovy
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *  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 groovy.transform
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.ElementType
-import java.lang.annotation.Retention
-import java.lang.annotation.RetentionPolicy
-import java.lang.annotation.Target
-
-/**
- * Allows "interrupt-safe" executions of scripts by adding a custom check for interruption
- * into loops (for, while, ...) and at the start of closures and methods.
- * <p>
- * This is especially useful when executing foreign scripts that you do not have control over. Inject this
- * transformation into a script that you need to interrupt based on some custom criteria.
- * <p>
- * Annotating anything in a script will cause for loops, while loops, methods, and closures to make a
- * check against the specified closure. If the closure yields true (according to GroovyTruth), then the script
- * will throw an InterruptedException. The annotation by default applies to any classes defined in the script
- * as well. Annotated a class will cause (by default) all classes in the entire file ('Compilation Unit') to be
- * enhanced. You can fine tune what is enhanced using the annotation parameters.
- * <p>
- * The following is sample usage of the annotation:
- * <pre>
- * <code>@ConditionalInterrupt({ counter++> 10})</code>
- * import groovy.transform.ConditionalInterrupt
- *
- * counter = 0
- * def scriptMethod() {
- *      4.times {
- *          println 'executing script method...'
- *      }
- * }
- *
- * scriptMethod()
- * </pre>
- * Which results in the following code being generated (XXXXXX will be replaced with some runtime generated hashCode). Notice the checks and exceptions:
- * <pre>
- * public class script1291741477073 extends groovy.lang.Script {
- *   Object counter = 0
- *
- *   public java.lang.Object run() {
- *     counter = 0
- *   }
- *
- *   public java.lang.Object scriptMethod() {
- *     if (this.conditionalTransformXXXXXX$condition()) {
- *       throw new java.lang.InterruptedException('Execution interrupted. The following condition failed: { counter++> 10}')
- *     }
- *     4.times({
- *       if (this.conditionalTransformXXXXXX$condition()) {
- *         throw new java.lang.InterruptedException('Execution interrupted. The following condition failed: { counter++> 10}')
- *       }
- *       this.println('executing script method...')
- *     })
- *   }
- *
- *   private java.lang.Object conditionalTransformXXXXXX$condition() {
- *     counter++ > 10
- *   }
- * }
- * </pre>
- *
- * Note that when you're annotating scripts, the variable scoping semantics are unchanged. Therefore, you must be
- * careful about the variable scope you're using. Make sure that variables you reference in the closure parameter
- * are in scope during script execution. The following example will throw a MissingPropertyException because
- * counter is not in scope for a class:
- * <pre>
- * import groovy.transform.ConditionalInterrupt
- *
- * def counter = 0
- * <code>@ConditionalInterrupt({ counter++> 10})</code>
- * class MyClass {
- *   def myMethod() {
- *     4.times {
- *       println 'executing script method...'
- *     }
- *   }
- * }
- *
- * new MyClass().myMethod()
- * </pre>
- * Additional usage examples can be found in the unit test for this class.
- *
- * @see TimedInterrupt
- * @see ThreadInterrupt
- * @author Cedric Champeau
- * @author Hamlet D'Arcy
- * @author Paul King
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target([ElementType.PACKAGE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE])
-@GroovyASTTransformationClass(["org.codehaus.groovy.transform.ConditionalInterruptibleASTTransformation"])
-@interface ConditionalInterrupt {
-  /**
-   * Set this to false if you have multiple classes within one source file and only
-   * want a conditional check on some of the classes. Place annotations on the classes
-   * you want enhanced. Set to true (the default) for blanket coverage of conditional
-   * checks on all methods, loops and closures within all classes/script code.
-   *
-   * For even finer-grained control see {@code applyToAllMembers}.
-   *
-   * @see #applyToAllMembers()
-   */
-  boolean applyToAllClasses() default true
-
-  /**
-   * Set this to false if you have multiple methods/closures within a class or script and only
-   * want conditional checks on some of them. Place annotations on the methods/closures that
-   * you want enhanced. When false, {@code applyToAllClasses} is automatically set to false.
-   *
-   * Set to true (the default) for blanket coverage of conditional checks on all methods, loops
-   * and closures within the class/script.
-   *
-   * @since 2.2.0
-   * @see #applyToAllClasses()
-   */
-  boolean applyToAllMembers() default true
-
-  /**
-   * By default a conditional check is added to the start of all user-defined methods. To turn this off simply
-   * set this parameter to false.
-   */
-  boolean checkOnMethodStart() default true
-
-  /**
-   * Sets the type of exception which is thrown.
-   */
-  Class thrown() default InterruptedException
-
-  /**
-   * Conditional check - set as a closure expression.
-   */
-  Class value()
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/EqualsAndHashCode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/EqualsAndHashCode.java b/src/main/groovy/transform/EqualsAndHashCode.java
deleted file mode 100644
index 11a385e..0000000
--- a/src/main/groovy/transform/EqualsAndHashCode.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in creating appropriate {@code equals()} and {@code hashCode()} methods.
- * <p>
- * It allows you to write classes in this shortened form:
- * <pre class="groovyTestCase">
- * import groovy.transform.EqualsAndHashCode
- * {@code @EqualsAndHashCode}
- * class Person {
- *     String first, last
- *     int age
- * }
- * def p1 = new Person(first:'John', last:'Smith', age:21)
- * def p2 = new Person(first:'John', last:'Smith', age:21)
- * assert p1 == p2
- * def map = [:]
- * map[p1] = 45
- * assert map[p2] == 45
- * </pre>
- * The {@code @EqualsAndHashCode} annotation instructs the compiler to execute an
- * AST transformation which adds the necessary equals and hashCode methods to the class.
- * <p>
- * The {@code hashCode()} method is calculated using Groovy's {@code HashCodeHelper} class
- * which implements an algorithm similar to the one outlined in the book <em>Effective Java</em>.
- * <p>
- * The {@code equals()} method compares the values of the individual properties (and optionally fields)
- * of the class.  It can also optionally call equals on the super class. Two different equals method
- * implementations are supported both of which support the equals contract outlined in the javadoc
- * for <code>java.lang.Object</code>
- * <p>
- * To illustrate the 'canEqual' implementation style (see http://www.artima.com/lejava/articles/equality.html
- * for further details), consider this class:
- * <pre>
- * {@code @EqualsAndHashCode}
- * class IntPair {
- *     int x, y
- * }
- * </pre>
- * The generated <code>equals</code> and <code>canEqual</code> methods will be something like below:
- * <pre>
- * public boolean equals(java.lang.Object other)
- *     if (other == null) return false
- *     if (this.is(other)) return true
- *     if (!(other instanceof IntPair)) return false
- *     if (!other.canEqual(this)) return false
- *     if (x != other.x) return false
- *     if (y != other.y) return false
- *     return true
- * }
- *
- * public boolean canEqual(java.lang.Object other) {
- *     return other instanceof IntPair
- * }
- * </pre>
- * If no further options are specified, this is the default style for {@code @Canonical} and
- * {@code @EqualsAndHashCode} annotated classes. The advantage of this style is that it allows inheritance
- * to be used in limited cases where its purpose is for overriding implementation details rather than
- * creating a derived type with different behavior. This is useful when using JPA Proxies for example or
- * as shown in the following examples:
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- * {@code @Canonical} class IntPair { int x, y }
- * def p1 = new IntPair(1, 2)
- *
- * // overridden getter but deemed an IntPair as far as domain is concerned
- * def p2 = new IntPair(1, 1) { int getY() { 2 } }
- *
- * // additional helper method added through inheritance but
- * // deemed an IntPair as far as our domain is concerned
- * {@code @InheritConstructors} class IntPairWithSum extends IntPair {
- *     def sum() { x + y }
- * }
- *
- * def p3 = new IntPairWithSum(1, 2)
- *
- * assert p1 == p2 && p2 == p1
- * assert p1 == p3 && p3 == p1
- * assert p3 == p2 && p2 == p3
- * </pre>
- * Note that if you create any domain classes which don't have exactly the
- * same contract as <code>IntPair</code> then you should provide an appropriate
- * <code>equals</code> and <code>canEqual</code> method. The easiest way to
- * achieve this would be to use the {@code @Canonical} or
- * {@code @EqualsAndHashCode} annotations as shown below:
- * <pre>
- * {@code @EqualsAndHashCode}
- * {@code @TupleConstructor(includeSuperProperties=true)}
- * class IntTriple extends IntPair { int z }
- * def t1 = new IntTriple(1, 2, 3)
- * assert p1 != t1 && p2 != t1 && t1 != p3
- * </pre>
- *
- * The alternative supported style regards any kind of inheritance as creation of
- * a new type and is illustrated in the following example:
- * <pre>
- * {@code @EqualsAndHashCode(useCanEqual=false)}
- * class IntPair {
- *     int x, y
- * }
- * </pre>
- * The generated equals method will be something like below:
- * <pre>
- * public boolean equals(java.lang.Object other)
- *     if (other == null) return false
- *     if (this.is(other)) return true
- *     if (IntPair != other.getClass()) return false
- *     if (x != other.x) return false
- *     if (y != other.y) return false
- *     return true
- * }
- * </pre>
- * This style is appropriate for final classes (where inheritance is not
- * allowed) which have only <code>java.lang.Object</code> as a super class.
- * Most {@code @Immutable} classes fall in to this category. For such classes,
- * there is no need to introduce the <code>canEqual()</code> method.
- * <p>
- * Note that if you explicitly set <code>useCanEqual=false</code> for child nodes
- * in a class hierarchy but have it <code>true</code> for parent nodes and you
- * also have <code>callSuper=true</code> in the child, then your generated
- * equals methods will not strictly follow the equals contract.
- * <p>
- * Note that when used in the recommended fashion, the two implementations supported adhere
- * to the equals contract. You can provide your own equivalence relationships if you need,
- * e.g. for comparing instances of the <code>IntPair</code> and <code>IntTriple</code> classes
- * discussed earlier, you could provide the following method in <code>IntPair</code>:
- * <pre>
- * boolean hasEqualXY(other) { other.x == getX() && other.y == getY() }
- * </pre>
- * Then for the objects defined earlier, the following would be true:
- * <pre>
- * assert p1.hasEqualXY(t1) && t1.hasEqualXY(p1)
- * assert p2.hasEqualXY(t1) && t1.hasEqualXY(p2)
- * assert p3.hasEqualXY(t1) && t1.hasEqualXY(p3)
- * </pre>
- * There is also support for including or excluding fields/properties by name when constructing
- * the equals and hashCode methods as shown here:
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- * {@code @EqualsAndHashCode}(excludes="z")
- * {@code @TupleConstructor}
- * public class Point2D {
- *     int x, y, z
- * }
- *
- * assert  new Point2D(1, 1, 1).equals(new Point2D(1, 1, 2))
- * assert !new Point2D(1, 1, 1).equals(new Point2D(2, 1, 1))
- *
- * {@code @EqualsAndHashCode}(excludes=["y", "z"])
- * {@code @TupleConstructor}
- * public class Point1D {
- *     int x, y, z
- * }
- *
- * assert  new Point1D(1, 1, 1).equals(new Point1D(1, 1, 2))
- * assert  new Point1D(1, 1, 1).equals(new Point1D(1, 2, 1))
- * assert !new Point1D(1, 1, 1).equals(new Point1D(2, 1, 1))
- * </pre>
- * <b>Note:</b> {@code @EqualsAndHashCode} is a transform to help reduce boilerplate
- * in the common cases. It provides a useful implementation of {@code equals()}
- * and {@code hashCode()} but not necessarily the most appropriate or
- * efficient one for every use case. You should write custom versions if your
- * scenario demands it. In particular, if you have
- * mutually-referential classes, the implementations provided may not be suitable
- * and may recurse infinitely (leading to a {@code StackOverflowError}). In such cases,
- * you need to remove the infinite loop from your data structures or write your own custom methods.
- * If your data structures are self-referencing, the code generated by this transform will try to avoid
- * infinite recursion but the algorithm used may not suit your scenario, so use with caution if
- * you have such structures.
- * A future version of this transform may better handle some additional recursive scenarios.
- * <p>More examples:</p>
- * <pre class="groovyTestCase">
- * import groovy.transform.EqualsAndHashCode
- *
- * &#64;EqualsAndHashCode(includeFields=true)
- * class User {
- *     String name
- *     boolean active
- *     List likes
- *     private int age = 37
- * }
- *
- * def user = new User(name: 'mrhaki', active: false, likes: ['Groovy', 'Java'])
- * def mrhaki = new User(name: 'mrhaki', likes: ['Groovy', 'Java'])
- * def hubert = new User(name: 'Hubert Klein Ikkink', likes: ['Groovy', 'Java'])
- *
- * assert user == mrhaki
- * assert mrhaki != hubert
- *
- * Set users = new HashSet()
- * users.add user
- * users.add mrhaki
- * users.add hubert
- * assert users.size() == 2
- * </pre>
- *
- * @see org.codehaus.groovy.util.HashCodeHelper
- * @author Paul King
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.EqualsAndHashCodeASTTransformation")
-public @interface EqualsAndHashCode {
-    /**
-     * List of field and/or property names to exclude from the equals and hashCode calculations.
-     * Must not be used if 'includes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * List of field and/or property names to include within the equals and hashCode calculations.
-     * Must not be used if 'excludes' is used. For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     * The default value is a special marker value indicating that no includes are defined; all fields
-     * and/or properties are included if 'includes' remains undefined and 'excludes' is explicitly or
-     * implicitly an empty list.
-     */
-    String[] includes() default {Undefined.STRING};
-
-    /**
-     * Whether to cache hashCode calculations. You should only set this to true if
-     * you know the object is immutable (or technically mutable but never changed).
-     */
-    boolean cache() default false;
-
-    /**
-     * Whether to include super in equals and hashCode calculations.
-     */
-    boolean callSuper() default false;
-
-    /**
-     * Include fields as well as properties in equals and hashCode calculations.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Generate a canEqual method to be used by equals.
-     */
-    boolean useCanEqual() default true;
-
-    /**
-     * Whether to include all fields and/or properties in equals and hashCode calculations, including those
-     * with names that are considered internal.
-     *
-     * @since 2.5.0
-     */
-    boolean allNames() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ExternalizeMethods.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ExternalizeMethods.java b/src/main/groovy/transform/ExternalizeMethods.java
deleted file mode 100644
index 5ef37a0..0000000
--- a/src/main/groovy/transform/ExternalizeMethods.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of {@code Externalizable} classes.
- * The {@code @ExternalizeMethods} annotation instructs the compiler to execute an
- * AST transformation which adds {@code writeExternal()} and {@code readExternal()} methods
- * to a class and adds {@code Externalizable} to the interfaces which the class implements.
- * The {@code writeExternal()} method writes each property (and optionally field) of the class
- * while the {@code readExternal()} method will read each one back in the same order.
- * Properties or fields marked as {@code transient} are ignored.
- * This annotation is typically used in conjunction with the {@code @ExternalizeVerifier} annotation but
- * most usually not directly but rather via {@code @AutoExternalizable} which is a shortcut for both annotations.
- * <p>
- * Example usage:
- * <pre>
- * import groovy.transform.*
- * {@code @ExternalizeMethods}
- * class Person {
- *   String first, last
- *   List favItems
- *   Date since
- * }
- * </pre>
- * Which will create a class of the following form:
- * <pre>
- * class Person implements Externalizable {
- *   ...
- *   public void writeExternal(ObjectOutput out) throws IOException {
- *     out.writeObject(first)
- *     out.writeObject(last)
- *     out.writeObject(favItems)
- *     out.writeObject(since)
- *   }
- *
- *   public void readExternal(ObjectInput oin) {
- *     first = (String) oin.readObject()
- *     last = (String) oin.readObject()
- *     favItems = (List) oin.readObject()
- *     since = (Date) oin.readObject()
- *   }
- *   ...
- * }
- * </pre>
- *
- * @author Paul King
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ExternalizeMethodsASTTransformation")
-public @interface ExternalizeMethods {
-    /**
-     * Comma separated list of property names to exclude from externalizing.
-     * For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * Include fields as well as properties when externalizing.
-     */
-    boolean includeFields() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/ExternalizeVerifier.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ExternalizeVerifier.java b/src/main/groovy/transform/ExternalizeVerifier.java
deleted file mode 100644
index 185c935..0000000
--- a/src/main/groovy/transform/ExternalizeVerifier.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of {@code Externalizable} classes.
- * The {@code @ExternalizeVerifier} annotation instructs the compiler to check
- * that a class has {@code writeExternal()} and {@code readExternal()} methods,
- * implements the {@code Externalizable} interface and that each property (and optionally field) is not final
- * and, optionally for non-primitives, has a type which is either {@code Externalizable} or {@code Serializable}.
- * Properties or fields marked as {@code transient} are ignored.
- * This annotation is typically used in conjunction with the {@code @ExternalizeMethods} annotation but
- * most usually not directly but rather via {@code @AutoExternalizable} which is a shortcut for both annotations.
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ExternalizeVerifierASTTransformation")
-public @interface ExternalizeVerifier {
-    /**
-     * Comma separated list of property names to exclude from externalization verification.
-     * For convenience, a String with comma separated names
-     * can be used in addition to an array (using Groovy's literal list notation) of String values.
-     */
-    String[] excludes() default {};
-
-    /**
-     * Include fields as well as properties when verifying externalization properties.
-     */
-    boolean includeFields() default false;
-
-    /**
-     * Turns on strict type checking for property (or field) types. In strict mode, such types must also implement Serializable or Externalizable.
-     * If your properties have interface types that don't implement Serializable but all the concrete implementations do, or the
-     * type is of a non-Serializable class but the property will be null at runtime, then your instances will still be serializable
-     * but you can't turn on strict checking.
-     */
-    boolean checkPropertyTypes() default false;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Field.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Field.java b/src/main/groovy/transform/Field.java
deleted file mode 100644
index 546d045..0000000
--- a/src/main/groovy/transform/Field.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Variable annotation used for changing the scope of a variable within a script from
- * being within the run method of the script to being at the class level for the script.
- * <p>
- * The annotated variable will become a private field of the script class.
- * The type of the field will be the same as the type of the variable. Example usage:
- * <pre class="groovyTestCase">
- * import groovy.transform.Field
- * {@code @Field} List awe = [1, 2, 3]
- * def awesum() { awe.sum() }
- * assert awesum() == 6
- * </pre>
- * In this example, without the annotation, variable <code>awe</code> would be
- * a local script variable (technically speaking it will be a local variable within
- * the <code>run</code> method of the script class). Such a local variable would
- * not be visible inside the <code>awesum</code> method. With the annotation,
- * <code>awe</code> becomes a private List field in the script class and is
- * visible within the <code>awesum</code> method.
- *
- * @author Paul King
- * @since 1.8.0
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.LOCAL_VARIABLE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.FieldASTTransformation")
-public @interface Field {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Generated.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Generated.java b/src/main/groovy/transform/Generated.java
deleted file mode 100644
index 98eaf5b..0000000
--- a/src/main/groovy/transform/Generated.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The Generated annotation is used to mark members that have been generated.
- */
-@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Generated {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/Immutable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Immutable.java b/src/main/groovy/transform/Immutable.java
deleted file mode 100644
index 89876a4..0000000
--- a/src/main/groovy/transform/Immutable.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- *  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 groovy.transform;
-
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Class annotation used to assist in the creation of immutable classes.
- * <p>
- * It allows you to write classes in this shortened form:
- * <pre class="groovyTestCase">
- * {@code @groovy.transform.Immutable} class Customer {
- *     String first, last
- *     int age
- *     Date since
- *     Collection favItems
- * }
- * def d = new Date()
- * def c1 = new Customer(first:'Tom', last:'Jones', age:21, since:d, favItems:['Books', 'Games'])
- * def c2 = new Customer('Tom', 'Jones', 21, d, ['Books', 'Games'])
- * assert c1 == c2
- * </pre>
- * The {@code @Immutable} annotation instructs the compiler to execute an
- * AST transformation which adds the necessary getters, constructors,
- * equals, hashCode and other helper methods that are typically written
- * when creating immutable classes with the defined properties.
- * <p>
- * A class created in this way has the following characteristics:
- * <ul>
- * <li>The class is automatically made final.
- * <li>Properties must be of an immutable type or a type with a strategy for handling non-immutable
- * characteristics. Specifically, the type must be one of the primitive or wrapper types, Strings, enums,
- * other {@code @Immutable} classes or known immutables (e.g. java.awt.Color, java.net.URI, java.util.UUID).
- * Also handled are Cloneable classes, collections, maps and arrays, other "effectively immutable"
- * classes with special handling (e.g. java.util.Date), and usages of java.util.Optional where the
- * contained type is immutable (e.g. Optional&lt;String&gt;).
- * <li>Properties automatically have private, final backing fields with getters.
- * Attempts to update the property will result in a {@code ReadOnlyPropertyException}.
- * <li>A map-based constructor is provided which allows you to set properties by name.
- * <li>A tuple-style constructor is provided which allows you to set properties in the same order as they are defined.
- * <li>Default {@code equals}, {@code hashCode} and {@code toString} methods are provided based on the property values.
- * Though not normally required, you may write your own implementations of these methods. For {@code equals} and {@code hashCode},
- * if you do write your own method, it is up to you to obey the general contract for {@code equals} methods and supply
- * a corresponding matching {@code hashCode} method.
- * If you do provide one of these methods explicitly, the default implementation will be made available in a private
- * "underscore" variant which you can call. E.g., you could provide a (not very elegant) multi-line formatted
- * {@code toString} method for {@code Customer} above as follows:
- * <pre>
- *     String toString() {
- *        _toString().replaceAll(/\(/, '(\n\t').replaceAll(/\)/, '\n)').replaceAll(/, /, '\n\t')
- *    }
- * </pre>
- * If an "underscore" version of the respective method already exists, then no default implementation is provided.
- * <li>{@code Date}s, {@code Cloneable}s and arrays are defensively copied on the way in (constructor) and out (getters).
- * Arrays and {@code Cloneable} objects use the {@code clone} method. For your own classes,
- * it is up to you to define this method and use deep cloning if appropriate.
- * <li>{@code Collection}s and {@code Map}s are wrapped by immutable wrapper classes (but not deeply cloned!).
- * Attempts to update them will result in an {@code UnsupportedOperationException}.
- * <li>Fields that are enums or other {@code @Immutable} classes are allowed but for an
- * otherwise possible mutable property type, an error is thrown.
- * <li>You don't have to follow Groovy's normal property conventions, e.g. you can create an explicit private field and
- * then you can write explicit get and set methods. Such an approach, isn't currently prohibited (to give you some
- * wiggle room to get around these conventions) but any fields created in this way are deemed not to be part of the
- * significant state of the object and aren't factored into the {@code equals} or {@code hashCode} methods.
- * Similarly, you may use static properties (though usually this is discouraged) and these too will be ignored
- * as far as significant state is concerned. If you do break standard conventions, you do so at your own risk and
- * your objects may no longer be immutable. It is up to you to ensure that your objects remain immutable at least
- * to the extent expected in other parts of your program!
- * </ul>
- * Immutable classes are particularly useful for functional and concurrent styles of programming
- * and for use as key values within maps. If you want similar functionality to what this annotation
- * provides but don't need immutability then consider using {@code @Canonical}.
- * <p>
- * Customising behaviour:
- * <p>
- * You can customise the toString() method provided for you by {@code @Immutable}
- * by also adding the {@code @ToString} annotation to your class definition.
- * <p>
- * Limitations:
- * <ul>
- * <li>
- * As outlined above, Arrays and {@code Cloneable} objects use the {@code clone} method. For your own classes,
- * it is up to you to define this method and use deep cloning if appropriate.
- * </li>
- * <li>
- * As outlined above, {@code Collection}s and {@code Map}s are wrapped by immutable wrapper classes (but not deeply cloned!).
- * </li>
- * <li>
- * Currently {@code BigInteger} and {@code BigDecimal} are deemed immutable but see:
- * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348370
- * </li>
- * <li>
- * {@code java.awt.Color} is treated as "effectively immutable" but is not final so while not normally used with child
- * classes, it isn't strictly immutable. Use at your own risk.
- * </li>
- * <li>
- * {@code java.util.Date} is treated as "effectively immutable" but is not final so it isn't strictly immutable.
- * Use at your own risk.
- * </li>
- * <li>
- * Groovy's normal map-style naming conventions will not be available if the first property
- * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property.
- * </li>
- * </ul>
- * <p>More examples:</p>
- --------------------------------------------------------------------------------
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * &#64;Canonical
- * class Building {
- *     String name
- *     int floors
- *     boolean officeSpace
- * }
- *
- * // Constructors are added.
- * def officeSpace = new Building('Initech office', 1, true)
- *
- * // toString() added.
- * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
- *
- * // Default values are used if constructor
- * // arguments are not assigned.
- * def theOffice = new Building('Wernham Hogg Paper Company')
- * assert theOffice.floors == 0
- * theOffice.officeSpace = true
- *
- * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
- *
- * // equals() method is added.
- * assert anotherOfficeSpace == officeSpace
- *
- * // equals() and hashCode() are added, so duplicate is not in Set.
- * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
- * assert offices.size() == 2 
- * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
- *
- * &#64;Canonical
- * &#64;ToString(excludes='age')  // Customize one of the transformations.
- * class Person {
- *     String name
- *     int age
- * }
- *
- * def mrhaki = new Person('mrhaki', 37)
- * assert mrhaki.toString() == 'Person(mrhaki)'
- * </pre>
- *
- * @author Paul King
- * @author Andre Steingress
- * @see groovy.transform.ToString
- * @see groovy.transform.Canonical
- * @since 1.7
- */
-@java.lang.annotation.Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ImmutableASTTransformation")
-public @interface Immutable {
-    /**
-     * Allows you to provide {@code @Immutable} with a list of classes which
-     * are deemed immutable. By supplying a class in this list, you are vouching
-     * for its immutability and {@code @Immutable} will do no further checks.
-     * Example:
-     * <pre>
-     * import groovy.transform.*
-     * {@code @Immutable}(knownImmutableClasses = [Address])
-     * class Person {
-     *     String first, last
-     *     Address address
-     * }
-     *
-     * {@code @TupleConstructor}
-     * class Address {
-     *     final String street
-     * }
-     * </pre>
-     *
-     * @since 1.8.7
-     */
-    Class[] knownImmutableClasses() default {};
-
-    /**
-     * Allows you to provide {@code @Immutable} with a list of property names which
-     * are deemed immutable. By supplying a property's name in this list, you are vouching
-     * for its immutability and {@code @Immutable} will do no further checks.
-     * Example:
-     * <pre>
-     * {@code @groovy.transform.Immutable}(knownImmutables = ['address'])
-     * class Person {
-     *     String first, last
-     *     Address address
-     * }
-     * ...
-     * </pre>
-     *
-     * @since 2.1.0
-     */
-    String[] knownImmutables() default {};
-
-    /**
-     * If {@code true}, this adds a method {@code copyWith} which takes a Map of
-     * new property values and returns a new instance of the Immutable class with
-     * these values set.
-     * Example:
-     * <pre class="groovyTestCase">
-     * {@code @groovy.transform.Immutable}(copyWith = true)
-     * class Person {
-     *     String first, last
-     * }
-     *
-     * def tim   = new Person( 'tim', 'yates' )
-     * def alice = tim.copyWith( first:'alice' )
-     *
-     * assert tim.first   == 'tim'
-     * assert alice.first == 'alice'
-     * </pre>
-     * Unknown keys in the map are ignored, and if the values would not change
-     * the object, then the original object is returned.
-     *
-     * If a method called {@code copyWith} that takes a single parameter already
-     * exists in the class, then this setting is ignored, and no method is generated.
-     *
-     * @since 2.2.0
-     */
-    boolean copyWith() default false;
-}


[19/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ExpandoMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ExpandoMetaClass.java b/src/main/groovy/lang/ExpandoMetaClass.java
deleted file mode 100644
index d56f738..0000000
--- a/src/main/groovy/lang/ExpandoMetaClass.java
+++ /dev/null
@@ -1,1510 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.reflection.MixinInMetaClass;
-import org.codehaus.groovy.runtime.DefaultCachedMethodKey;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.MethodKey;
-import org.codehaus.groovy.runtime.callsite.CallSite;
-import org.codehaus.groovy.runtime.callsite.ConstructorMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.DefaultMetaClassInfo;
-import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
-import org.codehaus.groovy.runtime.metaclass.MixedInMetaClass;
-import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.OwnedMetaClass;
-import org.codehaus.groovy.runtime.metaclass.ThreadManagedMetaBeanProperty;
-import org.codehaus.groovy.util.FastArray;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * ExpandoMetaClass is a MetaClass that behaves like an Expando, allowing the addition or replacement
- * of methods, properties and constructors on the fly.
- * <p>
- * Some examples of usage:
- * <pre>
- * // defines or replaces instance method:
- * metaClass.myMethod = { args -> }
- *
- * // defines a new instance method
- * metaClass.myMethod << { args -> }
- *
- * // creates multiple overloaded methods of the same name
- * metaClass.myMethod << { String s -> } << { Integer i -> }
- *
- * // defines or replaces a static method with the 'static' qualifier
- * metaClass.'static'.myMethod = { args ->  }
- *
- * // defines a new static method with the 'static' qualifier
- * metaClass.'static'.myMethod << { args ->  }
- *
- * // defines a new constructor
- * metaClass.constructor << { String arg -> }
- *
- * // defines or replaces a constructor
- * metaClass.constructor = { String arg -> }
- *
- * // defines a new property with an initial value of "blah"
- * metaClass.myProperty = "blah"
- * </pre>
- * <p>
- * ExpandoMetaClass also supports a DSL/builder like notation to combine multiple definitions together. So instead of this:
- * <pre>
- * Number.metaClass.multiply = { Amount amount -> amount.times(delegate) }
- * Number.metaClass.div =      { Amount amount -> amount.inverse().times(delegate) }
- * </pre>
- * You can also now do this:
- * <pre>
- * Number.metaClass {
- *     multiply { Amount amount -> amount.times(delegate) }
- *     div      { Amount amount -> amount.inverse().times(delegate) }
- * }
- * </pre>
- * <p>
- * ExpandoMetaClass also supports runtime mixins. While {@code @Mixin} allows you to mix in new behavior
- * to classes you own and are designing, you can not easily mixin anything to types you didn't own, e.g.
- * from third party libraries or from JDK library classes.
- * Runtime mixins let you add a mixin on any type at runtime.
- * <pre>
- * interface Vehicle {
- *     String getName()
- * }
- *
- * // Category annotation style
- * {@code @Category}(Vehicle) class FlyingAbility {
- *     def fly() { "I'm the ${name} and I fly!" }
- * }
- *
- * // traditional category style
- * class DivingAbility {
- *     static dive(Vehicle self) { "I'm the ${self.name} and I dive!" }
- * }
- *
- * // provided by a third-party, so can't augment using Mixin annotation
- * class JamesBondVehicle implements Vehicle {
- *     String getName() { "James Bond's vehicle" }
- * }
- *
- * // Can be added via metaClass, e.g.:
- * // JamesBondVehicle.metaClass.mixin DivingAbility, FlyingAbility
- * // Or using shorthand through DGM method on Class
- * JamesBondVehicle.mixin DivingAbility, FlyingAbility
- *
- * assert new JamesBondVehicle().fly() ==
- *        "I'm the James Bond's vehicle and I fly!"
- * assert new JamesBondVehicle().dive() ==
- *        "I'm the James Bond's vehicle and I dive!"
- * </pre>
- * As another example, consider the following class definitions:
- * <pre>
- * class Student {
- *     List<String> schedule = []
- *     def addLecture(String lecture) { schedule << lecture }
- * }
- *
- * class Worker {
- *     List<String> schedule = []
- *     def addMeeting(String meeting) { schedule << meeting }
- * }
- * </pre>
- * We can mimic a form of multiple inheritance as follows:
- * <pre>
- * class CollegeStudent {
- *     static { mixin Student, Worker }
- * }
- * new CollegeStudent().with {
- *     addMeeting('Performance review with Boss')
- *     addLecture('Learn about Groovy Mixins')
- *     println schedule
- *     println mixedIn[Student].schedule
- *     println mixedIn[Worker].schedule
- * }
- * </pre>
- * Which outputs these lines when run:
- * <pre>
- * [Performance review with Boss]
- * [Learn about Groovy Mixins]
- * [Performance review with Boss]
- * </pre>
- * Perhaps some explanation is required here. The methods and properties of Student and Worker are
- * added to CollegeStudent. Worker is added last, so for overlapping methods, its methods will
- * be used, e.g. when calling <code>schedule</code>, it will be the schedule property (getSchedule method)
- * from Worker that is used. The schedule property from Student will be shadowed but the <code>mixedIn</code>
- * notation allows us to get to that too if we need as the last two lines show.
- * <p>
- * We can also be a little more dynamic and not require the CollegeStudent class to
- * be defined at all, e.g.:
- * <pre>
- * def cs = new Object()
- * cs.metaClass {
- *     mixin Student, Worker
- *     getSchedule {
- *         mixedIn[Student].schedule + mixedIn[Worker].schedule
- *     }
- * }
- * cs.with {
- *     addMeeting('Performance review with Boss')
- *     addLecture('Learn about Groovy Mixins')
- *     println schedule
- * }
- * </pre>
- * Which outputs this line when run:
- * <pre>
- * [Learn about Groovy Mixins, Performance review with Boss]
- * </pre>
- * As another example, we can also define a no dup queue by mixing in some
- * Queue and Set functionality as follows:
- * <pre>
- * def ndq = new Object()
- * ndq.metaClass {
- *     mixin ArrayDeque
- *     mixin HashSet
- *     leftShift = { Object o ->
- *         if (!mixedIn[Set].contains(o)) {
- *             mixedIn[Queue].push(o)
- *             mixedIn[Set].add(o)
- *         }
- *     }
- * }
- * ndq << 1
- * ndq << 2
- * ndq << 1
- * assert ndq.size() == 2
- * </pre>
- * As a final example, we sometimes need to pass such mixed in classes or objects
- * into Java methods which require a given static type but the ExpandoMetaClass mixin approach uses a very dynamic
- * approach based on duck typing rather than static interface definitions, so doesn't by default
- * produce objects matching the required static type. Luckily, there is a mixins capability
- * within ExpandoMetaClass which supports the use of Groovy's common 'as StaticType' notation to produce an object
- * having the correct static type so that it can be passed to the Java method call in question.
- * A slightly contrived example illustrating this feature:
- * <pre>
- * class CustomComparator implements Comparator {
- *     int compare(Object a, b) { return a.size() - b.size() }
- * }
- *
- * class CustomCloseable implements Closeable {
- *     void close() { println 'Lights out - I am closing' }
- * }
- *
- * import static mypackage.IOUtils.closeQuietly
- * import static java.util.Collections.sort
- * def o = new Object()
- * o.metaClass.mixin CustomComparator, CustomCloseable
- * def items = ['a', 'bbb', 'cc']
- * sort(items, o as Comparator)
- * println items                // => [a, cc, bbb]
- * closeQuietly(o as Closeable) // => Lights out - I am closing
- * </pre>
- * <p>
- * <b>Further details</b>
- * <p>
- * When using the default implementations of MetaClass, methods are only allowed to be added before initialize() is called.
- * In other words you create a new MetaClass, add some methods and then call initialize(). If you attempt to add new methods
- * after initialize() has been called, an error will be thrown. This is to ensure that the MetaClass can operate appropriately
- * in multi-threaded environments as it forces you to do all method additions at the beginning, before using the MetaClass.
- * <p>
- * ExpandoMetaClass differs here from the default in that it allows you to add methods after initialize has been called.
- * This is done by setting the initialize flag internally to false and then add the methods. Since this is not thread
- * safe it has to be done in a synchronized block. The methods to check for modification and initialization are
- * therefore synchronized as well. Any method call done through this meta class will first check if the it is
- * synchronized. Should this happen during a modification, then the method cannot be selected or called unless the
- * modification is completed.
- * <p>
- *
- * @author Graeme Rocher
- * @since 1.5
- */
-public class ExpandoMetaClass extends MetaClassImpl implements GroovyObject {
-
-    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-    private static final String META_CLASS = "metaClass";
-    private static final String CLASS = "class";
-    private static final String META_METHODS = "metaMethods";
-    private static final String METHODS = "methods";
-    private static final String PROPERTIES = "properties";
-    public static final String STATIC_QUALIFIER = "static";
-    public static final String CONSTRUCTOR = "constructor";
-
-    private static final String CLASS_PROPERTY = "class";
-    private static final String META_CLASS_PROPERTY = "metaClass";
-    private static final String GROOVY_CONSTRUCTOR = "<init>";
-
-    // These two properties are used when no ExpandoMetaClassCreationHandle is present
-
-    private MetaClass myMetaClass;
-    private boolean initialized;
-    private volatile boolean modified;
-
-    private boolean initCalled;
-    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
-    private final Lock readLock = rwl.readLock();
-    private final Lock writeLock = rwl.writeLock();
-    
-    private final boolean allowChangesAfterInit;
-    public boolean inRegistry;
-    
-    private final Set<MetaMethod> inheritedMetaMethods = new HashSet<MetaMethod>();
-    private final Map<String, MetaProperty> beanPropertyCache = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
-    private final Map<String, MetaProperty> staticBeanPropertyCache = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
-    private final Map<MethodKey, MetaMethod> expandoMethods = new ConcurrentHashMap<MethodKey, MetaMethod>(16, 0.75f, 1);
-
-    public Collection getExpandoSubclassMethods() {
-        return expandoSubclassMethods.values();
-    }
-
-    private final ConcurrentHashMap expandoSubclassMethods = new ConcurrentHashMap(16, 0.75f, 1);
-    private final Map<String, MetaProperty> expandoProperties = new ConcurrentHashMap<String, MetaProperty>(16, 0.75f, 1);
-    private ClosureStaticMetaMethod invokeStaticMethodMethod;
-    private final Set<MixinInMetaClass> mixinClasses = new LinkedHashSet<MixinInMetaClass>();
-
-    public ExpandoMetaClass(Class theClass, boolean register, boolean allowChangesAfterInit, MetaMethod[] add) {
-        this(GroovySystem.getMetaClassRegistry(), theClass, register, allowChangesAfterInit, add);
-    }
-    
-    public ExpandoMetaClass(MetaClassRegistry registry, Class theClass, boolean register, boolean allowChangesAfterInit, MetaMethod[] add) {
-        super(registry, theClass, add);
-        this.myMetaClass = InvokerHelper.getMetaClass(getClass());
-        this.inRegistry = register;
-        this.allowChangesAfterInit = allowChangesAfterInit;
-    }
-    
-    /**
-     * Constructs a new ExpandoMetaClass instance for the given class
-     *
-     * @param theClass The class that the MetaClass applies to
-     */
-    public ExpandoMetaClass(Class theClass) {
-        this(theClass,false,false,null);
-    }
-
-    public ExpandoMetaClass(Class theClass, MetaMethod [] add) {
-        this(theClass,false,false,add);
-    }
-
-    /**
-     * Constructs a new ExpandoMetaClass instance for the given class optionally placing the MetaClass
-     * in the MetaClassRegistry automatically
-     *
-     * @param theClass The class that the MetaClass applies to
-     * @param register True if the MetaClass should be registered inside the MetaClassRegistry. This defaults to true and ExpandoMetaClass will effect all instances if changed
-     */
-    public ExpandoMetaClass(Class theClass, boolean register) {
-        this(theClass,register,false,null);
-    }
-
-    public ExpandoMetaClass(Class theClass, boolean register, MetaMethod [] add) {
-        this(theClass, register, false, add);
-    }
-
-    /**
-     * Constructs a new ExpandoMetaClass instance for the given class optionally placing the MetaClass
-     * in the MetaClassRegistry automatically
-     *
-     * @param theClass The class that the MetaClass applies to
-     * @param register True if the MetaClass should be registered inside the MetaClassRegistry. This defaults to true and ExpandoMetaClass will effect all instances if changed
-     * @param allowChangesAfterInit Should the meta class be modifiable after initialization. Default is false.
-     */
-    public ExpandoMetaClass(Class theClass, boolean register, boolean allowChangesAfterInit) {
-        this(theClass, register, allowChangesAfterInit, null);
-    }
-
-    public MetaMethod findMixinMethod(String methodName, Class[] arguments) {
-        for (MixinInMetaClass mixin : mixinClasses) {
-            final CachedClass mixinClass = mixin.getMixinClass();
-            MetaClass metaClass = mixinClass.classInfo.getMetaClassForClass();
-            if (metaClass == null) {
-                metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(mixinClass.getTheClass());
-            }
-
-            MetaMethod metaMethod = metaClass.pickMethod(methodName, arguments);
-            if (metaMethod == null && metaClass instanceof MetaClassImpl) {
-                MetaClassImpl mc = (MetaClassImpl) metaClass;
-                for (CachedClass cl = mc.getTheCachedClass().getCachedSuperClass(); cl != null; cl = cl.getCachedSuperClass()) {
-                    metaMethod = mc.getMethodWithoutCaching(cl.getTheClass(), methodName, arguments, false);
-                    if (metaMethod != null)
-                        break;
-                }
-            }
-            if (metaMethod != null) {
-                MetaMethod method = new MixinInstanceMetaMethod(metaMethod, mixin);
-
-                if (method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].isPrimitive) {
-                    MetaMethod noParam = pickMethod(methodName, EMPTY_CLASS_ARRAY);
-                    // if the current call itself is with empty arg class array, no need to recurse with 'new Class[0]'
-                    if (noParam == null && arguments.length != 0) {
-                        try {
-                            findMixinMethod(methodName, EMPTY_CLASS_ARRAY);
-                        } catch (MethodSelectionException msex) {
-                            /*
-                             * Here we just additionally tried to find another no-arg mixin method of the same name and register that as well, if found.
-                             * Safe to ignore a MethodSelectionException in this additional exercise. (GROOVY-4999)
-                             */
-                        }
-                    }
-                }
-
-                registerInstanceMethod(method);
-                return method;
-            }
-        }
-        return null;
-    }
-
-    protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
-        this.invokeMethodMethod = method;
-    }
-
-    protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
-        addSuperMethodIfNotOverridden(method);
-    }
-
-    protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
-        addMetaBeanProperty(property);
-    }
-
-    protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
-        this.setPropertyMethod = method;
-    }
-
-    protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
-        this.getPropertyMethod = method;
-    }
-
-    public boolean isModified() {
-        return this.modified;
-    }
-
-    public void registerSubclassInstanceMethod(String name, Class klazz, Closure closure) {
-        final List<MetaMethod> list = ClosureMetaMethod.createMethodList(name, klazz, closure);
-        for (MetaMethod metaMethod : list) {
-            registerSubclassInstanceMethod(metaMethod);
-        }
-    }
-
-    public void registerSubclassInstanceMethod(MetaMethod metaMethod) {
-        modified = true;
-
-        final String name = metaMethod.getName();
-        Object methodOrList = expandoSubclassMethods.get(name);
-        if (methodOrList == null) {
-            expandoSubclassMethods.put(name, metaMethod);
-        } else {
-            if (methodOrList instanceof MetaMethod) {
-                FastArray arr = new FastArray(2);
-                arr.add(methodOrList);
-                arr.add(metaMethod);
-                expandoSubclassMethods.put(name, arr);
-            } else {
-                ((FastArray) methodOrList).add(metaMethod);
-            }
-        }
-    }
-
-    public void addMixinClass(MixinInMetaClass mixin) {
-        mixinClasses.add(mixin);
-    }
-
-    public Object castToMixedType(Object obj, Class type) {
-        for (MixinInMetaClass mixin : mixinClasses) {
-            if (type.isAssignableFrom(mixin.getMixinClass().getTheClass()))
-                return mixin.getMixinInstance(obj);
-        }
-        return null;
-    }
-
-    /**
-     * For simulating closures in Java
-     */
-    private interface Callable {
-        void call();
-    }
-
-    /**
-     * Call to enable global use of ExpandoMetaClass within the registry.
-     * This has the advantage that inheritance will function correctly and 
-     * metaclass modifications will also apply to existing objects,
-     * but has a higher memory usage on the JVM than normal Groovy
-     */
-    public static void enableGlobally() {
-        DefaultMetaClassInfo.setWithoutCustomMetaclassCreationHandle(false);
-        ExpandoMetaClassCreationHandle.enable();
-    }
-
-    /**
-     * Call to disable the global use of ExpandoMetaClass
-     */
-    public static void disableGlobally() {
-        DefaultMetaClassInfo.setWithoutCustomMetaclassCreationHandle(true);
-        ExpandoMetaClassCreationHandle.disable();
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClassImpl#initialize()
-     */
-
-    public void initialize() {
-        try {
-            writeLock.lock();
-            if (!isInitialized()) {
-                super.initialize();
-                setInitialized(true);
-                this.initCalled = true;
-            }
-        } finally {
-            // downgrade to readlock before releasing just in case
-            readLock.lock();
-            writeLock.unlock();
-            readLock.unlock();
-        }
-    }
-
-    /**
-     * Checks if the meta class is initialized.
-     * @see groovy.lang.MetaClassImpl#isInitialized()
-     */
-    protected boolean isInitialized() {
-        try {
-            readLock.lock();
-            return this.initialized;
-        } finally {
-            readLock.unlock();
-        }
-    }
-
-    protected void setInitialized(boolean b) {
-        this.initialized = b;
-    }
-
-    private void addSuperMethodIfNotOverridden(final MetaMethod metaMethodFromSuper) {
-        performOperationOnMetaClass(new Callable() {
-            public void call() {
-
-                MetaMethod existing = null;
-                try {
-                    existing = pickMethod(metaMethodFromSuper.getName(), metaMethodFromSuper.getNativeParameterTypes());
-                } catch ( GroovyRuntimeException e) {
-                    // ignore, this happens with overlapping method definitions
-                }
-
-                if (existing == null) {
-                    addMethodWithKey(metaMethodFromSuper);
-                } else {
-                    boolean isGroovyMethod = getMetaMethods().contains(existing);
-
-                    if (isGroovyMethod) {
-                        addMethodWithKey(metaMethodFromSuper);
-                    } else if (inheritedMetaMethods.contains(existing)) {
-                        inheritedMetaMethods.remove(existing);
-                        addMethodWithKey(metaMethodFromSuper);
-                    }
-                }
-            }
-
-            private void addMethodWithKey(final MetaMethod metaMethodFromSuper) {
-                inheritedMetaMethods.add(metaMethodFromSuper);
-                if (metaMethodFromSuper instanceof ClosureMetaMethod) {
-                    ClosureMetaMethod closureMethod = (ClosureMetaMethod)metaMethodFromSuper;
-                    String name = metaMethodFromSuper.getName();
-                    final Class declaringClass = metaMethodFromSuper.getDeclaringClass().getTheClass();
-                    ClosureMetaMethod localMethod = ClosureMetaMethod.copy(closureMethod);
-                    addMetaMethod(localMethod);
-
-                    MethodKey key = new DefaultCachedMethodKey(declaringClass, name, localMethod.getParameterTypes(), false);
-
-                    checkIfGroovyObjectMethod(localMethod);
-                    expandoMethods.put(key, localMethod);
-
-                }
-            }
-        });
-    }
-
-    /**
-     * Instances of this class are returned when using the << left shift operator.
-     * <p>
-     * Example:
-     * <p>
-     * metaClass.myMethod << { String args -> }
-     * <p>
-     * This allows callbacks to the ExpandoMetaClass for registering appending methods
-     *
-     * @author Graeme Rocher
-     */
-    protected class ExpandoMetaProperty extends GroovyObjectSupport {
-
-        protected String propertyName;
-        protected boolean isStatic;
-
-        protected ExpandoMetaProperty(String name) {
-            this(name, false);
-        }
-
-        protected ExpandoMetaProperty(String name, boolean isStatic) {
-            this.propertyName = name;
-            this.isStatic = isStatic;
-        }
-
-        public String getPropertyName() {
-            return this.propertyName;
-        }
-
-        public boolean isStatic() {
-            return this.isStatic;
-        }
-
-        public Object leftShift(Object arg) {
-            registerIfClosure(arg, false);
-            return this;
-        }
-
-        private void registerIfClosure(Object arg, boolean replace) {
-            if (arg instanceof Closure) {
-                Closure callable = (Closure) arg;
-                final List<MetaMethod> list = ClosureMetaMethod.createMethodList(propertyName, theClass, callable);
-                if (list.isEmpty() && this.isStatic) {
-                    Class[] paramTypes = callable.getParameterTypes();
-                    registerStatic(callable, replace, paramTypes);
-                    return;
-                }
-                for (MetaMethod method : list) {
-                    Class[] paramTypes = method.getNativeParameterTypes();
-                    if (this.isStatic) {
-                        registerStatic(callable, replace, paramTypes);
-                    } else {
-                        registerInstance(method, replace, paramTypes);
-                    }
-                }
-            }
-        }
-
-        private void registerStatic(Closure callable, boolean replace, Class[] paramTypes) {
-            Method foundMethod = checkIfMethodExists(theClass, propertyName, paramTypes, true);
-            if (foundMethod != null && !replace)
-                throw new GroovyRuntimeException("Cannot add new static method [" + propertyName + "] for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
-            registerStaticMethod(propertyName, callable, paramTypes);
-        }
-
-        private void registerInstance(MetaMethod method, boolean replace, Class[] paramTypes) {
-            Method foundMethod = checkIfMethodExists(theClass, propertyName, paramTypes, false);
-            if (foundMethod != null && !replace)
-                throw new GroovyRuntimeException("Cannot add new method [" + propertyName + "] for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
-            registerInstanceMethod(method);
-        }
-
-        private Method checkIfMethodExists(Class methodClass, String methodName, Class[] paramTypes, boolean staticMethod) {
-            Method foundMethod = null;
-            Method[] methods = methodClass.getMethods();
-            for (Method method : methods) {
-                if (method.getName().equals(methodName) && Modifier.isStatic(method.getModifiers()) == staticMethod) {
-                    if (MetaClassHelper.parametersAreCompatible(paramTypes, method.getParameterTypes())) {
-                        foundMethod = method;
-                        break;
-                    }
-                }
-            }
-            return foundMethod;
-        }
-
-        /* (non-Javadoc)
-           * @see groovy.lang.GroovyObjectSupport#getProperty(java.lang.String)
-           */
-
-        public Object getProperty(String property) {
-            this.propertyName = property;
-            return this;
-        }
-        /* (non-Javadoc)
-           * @see groovy.lang.GroovyObjectSupport#setProperty(java.lang.String, java.lang.Object)
-           */
-
-        public void setProperty(String property, Object newValue) {
-            this.propertyName = property;
-            registerIfClosure(newValue, true);
-        }
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.MetaClassImpl#invokeConstructor(java.lang.Object[])
-      */
-
-    public Object invokeConstructor(Object[] arguments) {
-
-        // TODO This is the only area where this MetaClass needs to do some interception because Groovy's current
-        // MetaClass uses hard coded references to the java.lang.reflect.Constructor class so you can't simply
-        // inject Constructor like you can do properties, methods and fields. When Groovy's MetaClassImpl is
-        // refactored we can fix this
-        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, argClasses);
-        if (method != null && method.getParameterTypes().length == arguments.length) {
-            return method.invoke(theClass, arguments);
-        }
-        return super.invokeConstructor(arguments);
-    }
-
-    /**
-     * Handles the ability to use the left shift operator to append new constructors
-     *
-     * @author Graeme Rocher
-     */
-    protected class ExpandoMetaConstructor extends GroovyObjectSupport {
-        public Object leftShift(Closure c) {
-            if (c != null) {
-                final List<MetaMethod> list = ClosureMetaMethod.createMethodList(GROOVY_CONSTRUCTOR, theClass, c);
-                for (MetaMethod method : list) {
-                    Class[] paramTypes = method.getNativeParameterTypes();
-                    Constructor ctor = retrieveConstructor(paramTypes);
-                    if (ctor != null)
-                        throw new GroovyRuntimeException("Cannot add new constructor for arguments [" + DefaultGroovyMethods.inspect(paramTypes) + "]. It already exists!");
-
-                    registerInstanceMethod(method);
-                }
-            }
-
-            return this;
-        }
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.GroovyObject#getMetaClass()
-      */
-
-    public MetaClass getMetaClass() {
-        return myMetaClass;
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
-      */
-
-    public Object getProperty(String property) {
-        if (isValidExpandoProperty(property)) {
-            if (property.equals(STATIC_QUALIFIER)) {
-                return new ExpandoMetaProperty(property, true);
-            } else if (property.equals(CONSTRUCTOR)) {
-                return new ExpandoMetaConstructor();
-            } else {
-                if (myMetaClass.hasProperty(this, property) == null)
-                    return new ExpandoMetaProperty(property);
-                else
-                    return myMetaClass.getProperty(this, property);
-            }
-        } else {
-            return myMetaClass.getProperty(this, property);
-        }
-    }
-
-    public static boolean isValidExpandoProperty(String property) {
-        return !(property.equals(META_CLASS) || property.equals(CLASS) || property.equals(META_METHODS) || property.equals(METHODS) || property.equals(PROPERTIES));
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
-      */
-
-    public Object invokeMethod(String name, Object args) {
-        final Object[] argsArr = args instanceof Object[] ? (Object[]) args : new Object[]{args};
-        MetaMethod metaMethod = myMetaClass.getMetaMethod(name, argsArr);
-        if (metaMethod != null) {
-            // we have to use doMethodInvoke here instead of simply invoke,
-            // because getMetaMethod may provide a method that can not be called
-            // without further argument transformation, which is done only in 
-            // doMethodInvoke
-            return metaMethod.doMethodInvoke(this, argsArr);
-        }
-
-        if (argsArr.length == 2 && argsArr[0] instanceof Class && argsArr[1] instanceof Closure) {
-            if (argsArr[0] == theClass)
-                registerInstanceMethod(name, (Closure) argsArr[1]);
-            else {
-                registerSubclassInstanceMethod(name, (Class) argsArr[0], (Closure) argsArr[1]);
-            }
-            return null;
-        }
-
-        if (argsArr.length == 1 && argsArr[0] instanceof Closure) {
-            registerInstanceMethod(name, (Closure) argsArr[0]);
-            return null;
-        }
-
-        throw new MissingMethodException(name, getClass(), argsArr);
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.GroovyObject#setMetaClass(groovy.lang.MetaClass)
-      */
-
-    public void setMetaClass(MetaClass metaClass) {
-        this.myMetaClass = metaClass;
-    }
-
-    /* (non-Javadoc)
-      * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
-      */
-
-    public void setProperty(String property, Object newValue) {
-        if (newValue instanceof Closure) {
-            if (property.equals(CONSTRUCTOR)) {
-                property = GROOVY_CONSTRUCTOR;
-            }
-            Closure callable = (Closure) newValue;
-            final List<MetaMethod> list = ClosureMetaMethod.createMethodList(property, theClass, callable);
-            for (MetaMethod method : list) {
-                // here we don't care if the method exists or not we assume the
-                // developer is responsible and wants to override methods where necessary
-                registerInstanceMethod(method);
-            }
-        } else {
-            registerBeanProperty(property, newValue);
-        }
-    }
-
-    public ExpandoMetaClass define(Closure closure) {
-        final DefiningClosure definer = new DefiningClosure();
-        Object delegate = closure.getDelegate();
-        closure.setDelegate(definer);
-        closure.setResolveStrategy(Closure.DELEGATE_ONLY);
-        closure.call((Object)null);
-        closure.setDelegate(delegate);
-        closure.setResolveStrategy(Closure.DELEGATE_FIRST);
-        definer.definition = false;
-        return this;
-    }
-
-    protected synchronized void performOperationOnMetaClass(Callable c) {
-        try {
-            writeLock.lock();
-            if (allowChangesAfterInit) {
-                setInitialized(false);
-            }
-            c.call();
-        }
-        finally {
-            if (initCalled) {
-                setInitialized(true);
-            }
-            // downgrade to readlock before releasing just in case
-            readLock.lock();
-            writeLock.unlock();
-            readLock.unlock();
-        }
-    }
-    
-    protected void checkInitalised() {
-        try {
-            readLock.lock();
-            super.checkInitalised();
-        } finally {
-            readLock.unlock();
-        }
-    }
-
-    /**
-     * Registers a new bean property
-     *
-     * @param property The property name
-     * @param newValue The properties initial value
-     */
-    public void registerBeanProperty(final String property, final Object newValue) {
-        performOperationOnMetaClass(new Callable() {
-            public void call() {
-                Class type = newValue == null ? Object.class : newValue.getClass();
-
-                MetaBeanProperty mbp = newValue instanceof MetaBeanProperty ? (MetaBeanProperty) newValue : new ThreadManagedMetaBeanProperty(theClass, property, type, newValue);
-
-                final MetaMethod getter = mbp.getGetter();
-                final MethodKey getterKey = new DefaultCachedMethodKey(theClass, getter.getName(), CachedClass.EMPTY_ARRAY, false);
-                final MetaMethod setter = mbp.getSetter();
-                final MethodKey setterKey = new DefaultCachedMethodKey(theClass, setter.getName(), setter.getParameterTypes(), false);
-                addMetaMethod(getter);
-                addMetaMethod(setter);
-
-                expandoMethods.put(setterKey, setter);
-                expandoMethods.put(getterKey, getter);
-                expandoProperties.put(mbp.getName(), mbp);
-
-                addMetaBeanProperty(mbp);
-                performRegistryCallbacks();
-            }
-
-        });
-    }
-
-    /**
-     * Registers a new instance method for the given method name and closure on this MetaClass
-     *
-     * @param metaMethod
-     */
-    public void registerInstanceMethod(final MetaMethod metaMethod) {
-        final boolean inited = this.initCalled;
-        performOperationOnMetaClass(new Callable() {
-            public void call() {
-                String methodName = metaMethod.getName();
-                checkIfGroovyObjectMethod(metaMethod);
-                MethodKey key = new DefaultCachedMethodKey(theClass, methodName, metaMethod.getParameterTypes(), false);
-
-                if (isInitialized()) {
-                    throw new RuntimeException("Already initialized, cannot add new method: " + metaMethod);
-                }
-                // we always adds meta methods to class itself
-                addMetaMethodToIndex(metaMethod, metaMethodIndex.getHeader(theClass));
-
-                dropMethodCache(methodName);
-                expandoMethods.put(key, metaMethod);
-
-                if (inited && isGetter(methodName, metaMethod.getParameterTypes())) {
-                    String propertyName = getPropertyForGetter(methodName);
-                    registerBeanPropertyForMethod(metaMethod, propertyName, true, false);
-
-                } else if (inited && isSetter(methodName, metaMethod.getParameterTypes())) {
-                    String propertyName = getPropertyForSetter(methodName);
-                    registerBeanPropertyForMethod(metaMethod, propertyName, false, false);
-                }
-                performRegistryCallbacks();
-            }
-
-        });
-    }
-
-    public void registerInstanceMethod(String name, Closure closure) {
-        final List<MetaMethod> list = ClosureMetaMethod.createMethodList(name, theClass, closure);
-        for (MetaMethod method : list) {
-            registerInstanceMethod(method);
-        }
-    }
-
-    /**
-     * Overrides the behavior of parent getMethods() method to make MetaClass aware of added Expando methods
-     *
-     * @return A list of MetaMethods
-     * @see MetaObjectProtocol#getMethods()
-     */
-    public List<MetaMethod> getMethods() {
-        List<MetaMethod> methodList = new ArrayList<MetaMethod>();
-        methodList.addAll(this.expandoMethods.values());
-        methodList.addAll(super.getMethods());
-        return methodList;
-    }
-
-    public List<MetaProperty> getProperties() {
-        List<MetaProperty> propertyList = new ArrayList<MetaProperty>();
-        propertyList.addAll(super.getProperties());
-        return propertyList;
-    }
-
-
-    private void performRegistryCallbacks() {
-        MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
-        incVersion();
-        if (!modified) {
-            modified = true;
-            // Implementation note: By default Groovy uses soft references to store MetaClass
-            // this insures the registry doesn't grow and get out of hand. By doing this we're
-            // saying this this EMC will be a hard reference in the registry. As we're only
-            // going have a small number of classes that have modified EMC this is ok
-            if (inRegistry) {
-                MetaClass currMetaClass = registry.getMetaClass(theClass);
-                if (!(currMetaClass instanceof ExpandoMetaClass) && currMetaClass instanceof AdaptingMetaClass) {
-                    ((AdaptingMetaClass) currMetaClass).setAdaptee(this);
-                } else {
-                    registry.setMetaClass(theClass, this);
-                }
-            }
-
-        }
-    }
-
-    private void registerBeanPropertyForMethod(MetaMethod metaMethod, String propertyName, boolean getter, boolean isStatic) {
-        Map<String, MetaProperty> propertyCache = isStatic ? staticBeanPropertyCache : beanPropertyCache;
-        MetaBeanProperty beanProperty = (MetaBeanProperty) propertyCache.get(propertyName);
-        if (beanProperty==null) {
-            MetaProperty metaProperty = super.getMetaProperty(propertyName);
-            if (metaProperty instanceof MetaBeanProperty) {
-                boolean staticProp = Modifier.isStatic(metaProperty.getModifiers());
-                if (isStatic==staticProp) {
-                    beanProperty = (MetaBeanProperty) metaProperty;
-                }
-            }
-        }
-        if (beanProperty == null) {
-            if (getter)
-                beanProperty = new MetaBeanProperty(propertyName, Object.class, metaMethod, null);
-            else
-                beanProperty = new MetaBeanProperty(propertyName, Object.class, null, metaMethod);
-
-            propertyCache.put(propertyName, beanProperty);
-        } else {
-            if (getter) {
-                MetaMethod setterMethod = beanProperty.getSetter();
-                Class type = setterMethod != null ? setterMethod.getParameterTypes()[0].getTheClass() : Object.class;
-                beanProperty = new MetaBeanProperty(propertyName, type, metaMethod, setterMethod);
-                propertyCache.put(propertyName, beanProperty);
-            } else {
-                MetaMethod getterMethod = beanProperty.getGetter();
-                beanProperty = new MetaBeanProperty(propertyName, metaMethod.getParameterTypes()[0].getTheClass(), getterMethod, metaMethod);
-                propertyCache.put(propertyName, beanProperty);
-            }
-        }
-        expandoProperties.put(beanProperty.getName(), beanProperty);
-        addMetaBeanProperty(beanProperty);
-    }
-
-    protected void registerStaticMethod(final String name, final Closure callable) {
-        registerStaticMethod(name, callable, null);
-    }
-
-    /**
-     * Registers a new static method for the given method name and closure on this MetaClass
-     *
-     * @param name     The method name
-     * @param callable The callable Closure
-     */
-    protected void registerStaticMethod(final String name, final Closure callable, final Class[] paramTypes) {
-        performOperationOnMetaClass(new Callable() {
-            public void call() {
-                String methodName;
-                if (name.equals(METHOD_MISSING))
-                    methodName = STATIC_METHOD_MISSING;
-                else if (name.equals(PROPERTY_MISSING))
-                    methodName = STATIC_PROPERTY_MISSING;
-                else
-                    methodName = name;
-
-                ClosureStaticMetaMethod metaMethod = null;
-
-                if (paramTypes != null) {
-                    metaMethod = new ClosureStaticMetaMethod(methodName, theClass, callable, paramTypes);
-                } else {
-                    metaMethod = new ClosureStaticMetaMethod(methodName, theClass, callable);
-                }
-
-                if (methodName.equals(INVOKE_METHOD_METHOD) && callable.getParameterTypes().length == 2) {
-                    invokeStaticMethodMethod = metaMethod;
-                } else {
-                    if (methodName.equals(METHOD_MISSING)) {
-                        methodName = STATIC_METHOD_MISSING;
-                    }
-                    MethodKey key = new DefaultCachedMethodKey(theClass, methodName, metaMethod.getParameterTypes(), false);
-
-                    addMetaMethod(metaMethod);
-                    dropStaticMethodCache(methodName);
-//                    cacheStaticMethod(key,metaMethod);
-
-                    if (isGetter(methodName, metaMethod.getParameterTypes())) {
-                        String propertyName = getPropertyForGetter(methodName);
-                        registerBeanPropertyForMethod(metaMethod, propertyName, true, true);
-
-                    } else if (isSetter(methodName, metaMethod.getParameterTypes())) {
-                        String propertyName = getPropertyForSetter(methodName);
-                        registerBeanPropertyForMethod(metaMethod, propertyName, false, true);
-                    }
-                    performRegistryCallbacks();
-                    expandoMethods.put(key, metaMethod);
-                }
-            }
-
-        });
-    }
-
-    protected Object getSubclassMetaMethods(String methodName) {
-        if (!isModified())
-            return null;
-
-        return expandoSubclassMethods.get(methodName);
-    }
-
-    /**
-     * @return The Java class enhanced by this MetaClass
-     */
-    public Class getJavaClass() {
-        return theClass;
-    }
-
-    /**
-     * Called from ExpandoMetaClassCreationHandle in the registry if it exists to
-     * set up inheritance handling
-     *
-     * @param modifiedSuperExpandos A list of modified super ExpandoMetaClass
-     */
-    public void refreshInheritedMethods(Set modifiedSuperExpandos) {
-        for (Iterator i = modifiedSuperExpandos.iterator(); i.hasNext();) {
-            ExpandoMetaClass superExpando = (ExpandoMetaClass) i.next();
-            if (superExpando != this) {
-                refreshInheritedMethods(superExpando);
-            }
-        }
-    }
-
-    private void refreshInheritedMethods(ExpandoMetaClass superExpando) {
-        List<MetaMethod> metaMethods = superExpando.getExpandoMethods();
-        for (MetaMethod metaMethod : metaMethods) {
-            if (metaMethod.isStatic()) {
-                if (superExpando.getTheClass() != getTheClass())
-                    continue; // don't inherit static methods except our own
-                registerStaticMethod(metaMethod.getName(), (Closure) ((ClosureStaticMetaMethod) metaMethod).getClosure().clone());
-            } else
-                addSuperMethodIfNotOverridden(metaMethod);
-        }
-        Collection<MetaProperty> metaProperties = superExpando.getExpandoProperties();
-        for (Object metaProperty : metaProperties) {
-            MetaBeanProperty property = (MetaBeanProperty) metaProperty;
-            expandoProperties.put(property.getName(), property);
-            addMetaBeanProperty(property);
-        }
-    }
-
-
-    /**
-     * Returns a list of expando MetaMethod instances added to this ExpandoMetaClass
-     *
-     * @return the expandoMethods
-     */
-    public List<MetaMethod> getExpandoMethods() {
-        return Collections.unmodifiableList(DefaultGroovyMethods.toList(expandoMethods.values()));
-    }
-
-
-    /**
-     * Returns a list of MetaBeanProperty instances added to this ExpandoMetaClass
-     *
-     * @return the expandoProperties
-     */
-    public Collection<MetaProperty> getExpandoProperties() {
-        return Collections.unmodifiableCollection(expandoProperties.values());
-    }
-
-    /**
-     * Overrides default implementation just in case invokeMethod has been overridden by ExpandoMetaClass
-     *
-     * @see groovy.lang.MetaClassImpl#invokeMethod(Class, Object, String, Object[], boolean, boolean)
-     */
-    public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
-        if (invokeMethodMethod != null) {
-            MetaClassHelper.unwrap(originalArguments);
-            return invokeMethodMethod.invoke(object, new Object[]{methodName, originalArguments});
-        }
-        return super.invokeMethod(sender, object, methodName, originalArguments, isCallToSuper, fromInsideClass);
-    }
-
-    /**
-     * Overrides default implementation just in case a static invoke method has been set on ExpandoMetaClass
-     *
-     * @see MetaClassImpl#invokeStaticMethod(Object, String, Object[])
-     */
-    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
-        if (invokeStaticMethodMethod != null) {
-            MetaClassHelper.unwrap(arguments);
-            return invokeStaticMethodMethod.invoke(object, new Object[]{methodName, arguments});
-        }
-        return super.invokeStaticMethod(object, methodName, arguments);
-    }
-
-    /**
-     * Overrides default implementation just in case getProperty method has been overridden by ExpandoMetaClass
-     *
-     * @see MetaClassImpl#getProperty(Class, Object, String, boolean, boolean)
-     */
-    public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {
-        if (hasOverrideGetProperty(name) && getJavaClass().isInstance(object)) {
-            return getPropertyMethod.invoke(object, new Object[]{name});
-        }
-
-        if ("mixedIn".equals(name)) {
-            return new MixedInAccessor(object, mixinClasses);
-        }
-
-        return super.getProperty(sender, object, name, useSuper, fromInsideClass);
-    }
-
-    /**
-     * Overrides default implementation just in case getProperty method has been overridden by ExpandoMetaClass
-     *
-     * @see MetaClassImpl#getProperty(Object, String)
-     */
-    public Object getProperty(Object object, String name) {
-        if (hasOverrideGetProperty(name) && getJavaClass().isInstance(object)) {
-            return getPropertyMethod.invoke(object, new Object[]{name});
-        }
-        return super.getProperty(object, name);
-    }
-
-    private boolean hasOverrideGetProperty(String name) {
-        return getPropertyMethod != null && !name.equals(META_CLASS_PROPERTY) && !name.equals(CLASS_PROPERTY);
-    }
-
-    /**
-     * Overrides default implementation just in case setProperty method has been overridden by ExpandoMetaClass
-     *
-     * @see MetaClassImpl#setProperty(Class, Object, String, Object, boolean, boolean)
-     */
-
-    public void setProperty(Class sender, Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
-        if (setPropertyMethod != null && !name.equals(META_CLASS_PROPERTY) && getJavaClass().isInstance(object)) {
-            setPropertyMethod.invoke(object, new Object[]{name, newValue});
-            return;
-        }
-        super.setProperty(sender, object, name, newValue, useSuper, fromInsideClass);
-    }
-
-    /**
-     * Looks up an existing MetaProperty by name
-     *
-     * @param name The name of the MetaProperty
-     * @return The MetaProperty or null if it doesn't exist
-     */
-    public MetaProperty getMetaProperty(String name) {
-        MetaProperty mp = this.expandoProperties.get(name);
-        if (mp != null) return mp;
-        return super.getMetaProperty(name);
-    }
-
-    /**
-     * Returns true if the MetaClass has the given property
-     *
-     * @param name The name of the MetaProperty
-     * @return True it exists as a MetaProperty
-     */
-    public boolean hasMetaProperty(String name) {
-        return getMetaProperty(name) != null;
-    }
-
-    /**
-     * Checks whether a MetaMethod for the given name and arguments exists
-     *
-     * @param name The name of the MetaMethod
-     * @param args The arguments to the meta method
-     * @return True if the method exists otherwise null
-     */
-    public boolean hasMetaMethod(String name, Class[] args) {
-        return super.pickMethod(name, args) != null;
-    }
-
-    /**
-     * Determine if this method name suffix is a legitimate bean property name.
-     * Either the first or second letter must be upperCase for that to be true.
-     */
-    private static boolean isPropertyName(String name) {
-        return ((name.length() > 0) && Character.isUpperCase(name.charAt(0))) || ((name.length() > 1) && Character.isUpperCase(name.charAt(1)));
-    }
-
-    /**
-     * Returns true if the name of the method specified and the number of arguments make it a javabean property
-     *
-     * @param name True if its a Javabean property
-     * @param args The arguments
-     * @return True if it is a javabean property method
-     */
-    private boolean isGetter(String name, CachedClass[] args) {
-        if (name == null || name.length() == 0 || args == null) return false;
-        if (args.length != 0) return false;
-
-        if (name.startsWith("get")) {
-            name = name.substring(3);
-            return isPropertyName(name);
-        } else if (name.startsWith("is")) {
-            name = name.substring(2);
-            return isPropertyName(name);
-        }
-        return false;
-    }
-
-    /**
-     * Returns a property name equivalent for the given getter name or null if it is not a getter
-     *
-     * @param getterName The getter name
-     * @return The property name equivalent
-     */
-    private String getPropertyForGetter(String getterName) {
-        if (getterName == null || getterName.length() == 0) return null;
-
-        if (getterName.startsWith("get")) {
-            String prop = getterName.substring(3);
-            return MetaClassHelper.convertPropertyName(prop);
-        } else if (getterName.startsWith("is")) {
-            String prop = getterName.substring(2);
-            return MetaClassHelper.convertPropertyName(prop);
-        }
-        return null;
-    }
-
-    /**
-     * Returns a property name equivalent for the given setter name or null if it is not a getter
-     *
-     * @param setterName The setter name
-     * @return The property name equivalent
-     */
-    public String getPropertyForSetter(String setterName) {
-        if (setterName == null || setterName.length() == 0) return null;
-
-        if (setterName.startsWith("set")) {
-            String prop = setterName.substring(3);
-            return MetaClassHelper.convertPropertyName(prop);
-        }
-        return null;
-    }
-
-    public boolean isSetter(String name, CachedClass[] args) {
-        if (name == null || name.length() == 0 || args == null) return false;
-
-        if (name.startsWith("set")) {
-            if (args.length != 1) return false;
-            name = name.substring(3);
-            return isPropertyName(name);
-        }
-
-        return false;
-    }
-
-    public CallSite createPojoCallSite(CallSite site, Object receiver, Object[] args) {
-        if (invokeMethodMethod != null)
-            return new PojoMetaClassSite(site, this);
-
-        return super.createPojoCallSite(site, receiver, args);
-    }
-
-    public CallSite createStaticSite(CallSite site, Object[] args) {
-        if (invokeStaticMethodMethod != null)
-            return new StaticMetaClassSite(site, this);
-
-        return super.createStaticSite(site, args);
-    }
-
-    public boolean hasCustomStaticInvokeMethod() {return invokeStaticMethodMethod!=null; }
-
-    public CallSite createPogoCallSite(CallSite site, Object[] args) {
-        if (invokeMethodMethod != null)
-            return new PogoMetaClassSite(site, this);
-        return super.createPogoCallSite(site, args);
-    }
-
-    public CallSite createPogoCallCurrentSite(CallSite site, Class sender, String name, Object[] args) {
-        if (invokeMethodMethod != null)
-            return new PogoMetaClassSite(site, this);
-        return super.createPogoCallCurrentSite(site, sender, args);
-    }
-    
-    @Override
-    public MetaMethod retrieveConstructor(Object[] args) {
-        Class[] params = MetaClassHelper.convertToTypeArray(args);
-        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, params);
-        if (method!=null) return method;
-        return super.retrieveConstructor(args);
-    }
-
-    public CallSite createConstructorSite(CallSite site, Object[] args) {
-        Class[] params = MetaClassHelper.convertToTypeArray(args);
-        MetaMethod method = pickMethod(GROOVY_CONSTRUCTOR, params);
-        if (method != null && method.getParameterTypes().length == args.length) {
-            if (method.getDeclaringClass().getTheClass().equals(getTheClass())) {
-                return new ConstructorMetaMethodSite(site, this, method, params);
-            }
-        }
-
-        return super.createConstructorSite(site, args);
-    }
-
-    private class SubClassDefiningClosure extends GroovyObjectSupport {
-        private final Class klazz;
-
-        public SubClassDefiningClosure(Class klazz) {
-            this.klazz = klazz;
-        }
-
-        public Object invokeMethod(String name, Object obj) {
-            if (obj instanceof Object[]) {
-                Object args[] = (Object[]) obj;
-                if (args.length == 1 && args[0] instanceof Closure) {
-                    registerSubclassInstanceMethod(name, klazz, (Closure) args[0]);
-                    return null;
-                }
-            }
-
-            throw new MissingMethodException(name, getClass(), new Object[]{obj});
-        }
-    }
-
-    private class DefiningClosure extends GroovyObjectSupport {
-        boolean definition = true;
-
-        public void mixin(Class category) {
-            mixin(Collections.singletonList(category));
-        }
-
-        public void mixin(List categories) {
-            DefaultGroovyMethods.mixin(ExpandoMetaClass.this, categories);
-        }
-
-        public void mixin(Class[] categories) {
-            DefaultGroovyMethods.mixin(ExpandoMetaClass.this, categories);
-        }
-
-        public void define(Class subClass, Closure closure) {
-            final SubClassDefiningClosure definer = new SubClassDefiningClosure(subClass);
-            closure.setDelegate(definer);
-            closure.setResolveStrategy(Closure.DELEGATE_FIRST);
-            closure.call((Object)null);
-        }
-
-        public Object invokeMethod(String name, Object obj) {
-            try {
-                return getMetaClass().invokeMethod(this, name, obj);
-            }
-            catch (MissingMethodException mme) {
-                if (obj instanceof Object[]) {
-                    if (STATIC_QUALIFIER.equals(name)) {
-                        final StaticDefiningClosure staticDef = new StaticDefiningClosure();
-                        Closure c = (Closure) ((Object[]) obj)[0];
-                        c.setDelegate(staticDef);
-                        c.setResolveStrategy(Closure.DELEGATE_ONLY);
-                        c.call((Object)null);
-                        return null;
-                    }
-                    Object args[] = (Object[]) obj;
-                    if (args.length == 1 && args[0] instanceof Closure) {
-                        registerInstanceMethod(name, (Closure) args[0]);
-                    } else if (args.length == 2 && args[0] instanceof Class && args[1] instanceof Closure)
-                        registerSubclassInstanceMethod(name, (Class) args[0], (Closure) args[1]);
-                    else
-                        ExpandoMetaClass.this.setProperty(name, ((Object[]) obj)[0]);
-
-                    return null;
-                }
-
-                throw mme;
-            }
-        }
-
-        public void setProperty(String property, Object newValue) {
-            ExpandoMetaClass.this.setProperty(property, newValue);
-        }
-
-        public Object getProperty(String property) {
-            if (STATIC_QUALIFIER.equals(property))
-                return new StaticDefiningClosure();
-
-            if (definition)
-                return new ExpandoMetaProperty(property);
-            else
-                throw new MissingPropertyException(property, getClass());
-        }
-    }
-
-    private class StaticDefiningClosure extends ExpandoMetaProperty {
-        protected StaticDefiningClosure() {
-            super(STATIC_QUALIFIER, true);
-        }
-
-        public Object invokeMethod(String name, Object obj) {
-            if (obj instanceof Object[]) {
-                final Object[] args = (Object[]) obj;
-                if (args.length == 1 && args[0] instanceof Closure) {
-                    registerStaticMethod(name, (Closure) args[0]);
-                    return null;
-                }
-            }
-
-            throw new MissingMethodException(name, getClass(), obj instanceof Object[] ? (Object[]) obj : new Object[]{obj});
-        }
-    }
-
-    private static class MixedInAccessor {
-        private final Object object;
-        private final Set<MixinInMetaClass> mixinClasses;
-
-        public MixedInAccessor(Object object, Set<MixinInMetaClass> mixinClasses) {
-            this.object = object;
-            this.mixinClasses = mixinClasses;
-        }
-
-        public Object getAt(Class key) {
-            if (key.isAssignableFrom(object.getClass())) {
-                return new GroovyObjectSupport() {
-                    {
-                        final MetaClass ownMetaClass = InvokerHelper.getMetaClass(object.getClass());
-                        setMetaClass(new OwnedMetaClass(ownMetaClass) {
-                            protected Object getOwner() {
-                                return object;
-                            }
-
-                            protected MetaClass getOwnerMetaClass(Object owner) {
-                                return getAdaptee();
-                            }
-                        });
-                    }
-                };
-            }
-
-            for (final MixinInMetaClass mixin : mixinClasses) {
-                if (key.isAssignableFrom(mixin.getMixinClass().getTheClass())) {
-                    return new GroovyObjectSupport() {
-                        {
-                            final Object mixedInInstance = mixin.getMixinInstance(object);
-                            setMetaClass(new OwnedMetaClass(InvokerHelper.getMetaClass(mixedInInstance)) {
-                                @Override
-                                protected Object getOwner() {
-                                    return mixedInInstance;
-                                }
-
-                                @Override
-                                protected MetaClass getOwnerMetaClass(Object owner) {
-                                    return ((MixedInMetaClass) getAdaptee()).getAdaptee();
-                                }
-                            });
-                        }
-                    };
-                }
-            }
-
-            throw new RuntimeException("Class " + key + " isn't mixed in " + object.getClass());
-        }
-
-        public void putAt(Class key, Object value) {
-            for (MixinInMetaClass mixin : mixinClasses)
-                if (mixin.getMixinClass().getTheClass() == key) {
-                    mixin.setMixinInstance(object, value);
-                    return;
-                }
-
-            throw new RuntimeException("Class " + key + " isn't mixed in " + object.getClass());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/ExpandoMetaClassCreationHandle.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/ExpandoMetaClassCreationHandle.java b/src/main/groovy/lang/ExpandoMetaClassCreationHandle.java
deleted file mode 100644
index 6e411a5..0000000
--- a/src/main/groovy/lang/ExpandoMetaClassCreationHandle.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import groovy.lang.MetaClassRegistry.MetaClassCreationHandle;
-import org.codehaus.groovy.reflection.ClassInfo;
-
-/**
- * <p>A handle for the MetaClassRegistry that changes all classes loaded into the Grails VM
- * to use ExpandoMetaClass instances
- *
- * <p>The handle should be registered with the Groovy runtime <strong>before</strong> Groovy loads, for example
- * in your main method.
- *
- * <code>GroovySystem.metaClassRegistry.metaClassCreationHandle = new ExpandoMetaClassCreationHandle()</code>
- *
- * @see groovy.lang.MetaClassRegistry
- * @see groovy.lang.MetaClassRegistry.MetaClassCreationHandle
- * @see org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl#setMetaClassCreationHandle(groovy.lang.MetaClassRegistry.MetaClassCreationHandle)
- *
- * @author Graeme Rocher
- * @since 1.5
- */
-public class ExpandoMetaClassCreationHandle extends MetaClassCreationHandle {
-
-    public static final ExpandoMetaClassCreationHandle instance = new ExpandoMetaClassCreationHandle();
-
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClassRegistry.MetaClassCreationHandle#create(java.lang.Class, groovy.lang.MetaClassRegistry)
-     */
-    protected MetaClass createNormalMetaClass(Class theClass, MetaClassRegistry registry) {
-        if(theClass != ExpandoMetaClass.class) {
-            return new ExpandoMetaClass(theClass, true, true);
-        }
-        else {
-            return super.createNormalMetaClass(theClass, registry);
-        }
-    }
-
-    /**
-     * Registers a modified ExpandoMetaClass with the creation handle
-     *
-     * @param emc The EMC
-     */
-    public void registerModifiedMetaClass(ExpandoMetaClass emc) {
-        final Class klazz = emc.getJavaClass();
-        GroovySystem.getMetaClassRegistry().setMetaClass(klazz,emc);
-    }
-
-    public boolean hasModifiedMetaClass(ExpandoMetaClass emc) {
-        return emc.getClassInfo().getModifiedExpando() != null;
-    }
-
-    /**
-     * <p>Enables the ExpandoMetaClassCreationHandle with the registry
-     *
-     * <code>ExpandoMetaClassCreationHandle.enable();</code>
-     *
-     */
-    public static void enable() {
-        final MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
-        synchronized (metaClassRegistry) {
-            if (metaClassRegistry.getMetaClassCreationHandler() != instance) {
-                ClassInfo.clearModifiedExpandos();
-                metaClassRegistry.setMetaClassCreationHandle(instance);
-            }
-        }
-    }
-
-    public static void disable() {
-        final MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
-        synchronized (metaClassRegistry) {
-            if (metaClassRegistry.getMetaClassCreationHandler() == instance) {
-                ClassInfo.clearModifiedExpandos();
-                metaClassRegistry.setMetaClassCreationHandle(new MetaClassCreationHandle());
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GString.java b/src/main/groovy/lang/GString.java
deleted file mode 100644
index 8323bf2..0000000
--- a/src/main/groovy/lang/GString.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.GStringImpl;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.StringGroovyMethods;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * Represents a String which contains embedded values such as "hello there
- * ${user} how are you?" which can be evaluated lazily. Advanced users can
- * iterate over the text and values to perform special processing, such as for
- * performing SQL operations, the values can be substituted for ? and the
- * actual value objects can be bound to a JDBC statement. The lovely name of
- * this class was suggested by Jules Gosnell and was such a good idea, I
- * couldn't resist :)
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public abstract class GString extends GroovyObjectSupport implements Comparable, CharSequence, Writable, Buildable, Serializable {
-
-    static final long serialVersionUID = -2638020355892246323L;
-
-    /**
-     * A GString containing a single empty String and no values.
-     */
-    public static final GString EMPTY = new GString(new Object[0]) {
-        @Override
-        public String[] getStrings() {
-            return new String[]{""};
-        }
-    };
-    public static final String[] EMPTY_STRING_ARRAY = new String[0];
-    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
-
-    private final Object[] values;
-
-    public GString(Object values) {
-        this.values = (Object[]) values;
-    }
-
-    public GString(Object[] values) {
-        this.values = values;
-    }
-
-    // will be static in an instance
-
-    public abstract String[] getStrings();
-
-    /**
-     * Overloaded to implement duck typing for Strings
-     * so that any method that can't be evaluated on this
-     * object will be forwarded to the toString() object instead.
-     */
-    @Override
-    public Object invokeMethod(String name, Object args) {
-        try {
-            return super.invokeMethod(name, args);
-        }
-        catch (MissingMethodException e) {
-            // lets try invoke the method on the real String
-            return InvokerHelper.invokeMethod(toString(), name, args);
-        }
-    }
-
-    public Object[] getValues() {
-        return values;
-    }
-
-    public GString plus(GString that) {
-        List<String> stringList = new ArrayList<String>(Arrays.asList(getStrings()));
-        List<Object> valueList = new ArrayList<Object>(Arrays.asList(getValues()));
-
-        List<String> thatStrings = Arrays.asList(that.getStrings());
-
-        int stringListSize = stringList.size();
-        if (stringListSize > valueList.size()) {
-            thatStrings = new ArrayList<String>(thatStrings);
-            // merge onto end of previous GString to avoid an empty bridging value
-            int lastIndexOfStringList = stringListSize - 1;
-            String s = stringList.get(lastIndexOfStringList);
-            s += thatStrings.remove(0);
-            stringList.set(lastIndexOfStringList, s);
-        }
-
-        stringList.addAll(thatStrings);
-        valueList.addAll(Arrays.asList(that.getValues()));
-
-        final String[] newStrings = stringList.toArray(EMPTY_STRING_ARRAY);
-        final Object[] newValues = valueList.toArray();
-
-        return new GStringImpl(newValues, newStrings);
-    }
-
-    public GString plus(String that) {
-        return plus(new GStringImpl(EMPTY_OBJECT_ARRAY, new String[] { that }));
-    }
-
-    public int getValueCount() {
-        return values.length;
-    }
-
-    public Object getValue(int idx) {
-        return values[idx];
-    }
-
-    @Override
-    public String toString() {
-        StringWriter buffer = new StringWriter();
-        try {
-            writeTo(buffer);
-        }
-        catch (IOException e) {
-            throw new StringWriterIOException(e);
-        }
-        return buffer.toString();
-    }
-
-    @Override
-    public Writer writeTo(Writer out) throws IOException {
-        String[] s = getStrings();
-        int numberOfValues = values.length;
-        for (int i = 0, size = s.length; i < size; i++) {
-            out.write(s[i]);
-            if (i < numberOfValues) {
-                final Object value = values[i];
-
-                if (value instanceof Closure) {
-                    final Closure c = (Closure) value;
-
-                    if (c.getMaximumNumberOfParameters() == 0) {
-                        InvokerHelper.write(out, c.call());
-                    } else if (c.getMaximumNumberOfParameters() == 1) {
-                        c.call(out);
-                    } else {
-                        throw new GroovyRuntimeException("Trying to evaluate a GString containing a Closure taking "
-                                + c.getMaximumNumberOfParameters() + " parameters");
-                    }
-                } else {
-                    InvokerHelper.write(out, value);
-                }
-            }
-        }
-        return out;
-    }
-
-    /* (non-Javadoc)
-     * @see groovy.lang.Buildable#build(groovy.lang.GroovyObject)
-     */
-
-    @Override
-    public void build(final GroovyObject builder) {
-        final String[] s = getStrings();
-        final int numberOfValues = values.length;
-
-        for (int i = 0, size = s.length; i < size; i++) {
-            builder.getProperty("mkp");
-            builder.invokeMethod("yield", new Object[]{s[i]});
-            if (i < numberOfValues) {
-                builder.getProperty("mkp");
-                builder.invokeMethod("yield", new Object[]{values[i]});
-            }
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        return 37 + toString().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-        if (that instanceof GString) {
-            return equals((GString) that);
-        }
-        return false;
-    }
-
-    public boolean equals(GString that) {
-        return toString().equals(that.toString());
-    }
-
-    @Override
-    public int compareTo(Object that) {
-        return toString().compareTo(that.toString());
-    }
-
-    @Override
-    public char charAt(int index) {
-        return toString().charAt(index);
-    }
-
-    @Override
-    public int length() {
-        return toString().length();
-    }
-
-    @Override
-    public CharSequence subSequence(int start, int end) {
-        return toString().subSequence(start, end);
-    }
-
-    /**
-     * Turns a String into a regular expression pattern
-     *
-     * @return the regular expression pattern
-     */
-    public Pattern negate() {
-        return StringGroovyMethods.bitwiseNegate(toString());
-    }
-
-    public byte[] getBytes() {
-        return toString().getBytes();
-    }
-
-    public byte[] getBytes(String charset) throws UnsupportedEncodingException {
-       return toString().getBytes(charset);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GeneratedGroovyProxy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GeneratedGroovyProxy.java b/src/main/groovy/lang/GeneratedGroovyProxy.java
deleted file mode 100644
index 55b25b5..0000000
--- a/src/main/groovy/lang/GeneratedGroovyProxy.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * An interface implemented by some Groovy proxies which gives access to the proxied object. In particular, dynamically
- * generated proxies that implement traits will implement this interface in order to give access to the proxied
- * instance.
- *
- * @author Cedric Champeau
- * @since 2.3.0
- */
-public interface GeneratedGroovyProxy {
-    /**
-     * @return the proxy target.
-     */
-    Object getProxyTarget();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Grab.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Grab.java b/src/main/groovy/lang/Grab.java
deleted file mode 100644
index 2d789e6..0000000
--- a/src/main/groovy/lang/Grab.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to grab the referenced artifact and its dependencies and make it available on the Classpath.
- * <p>
- * Some examples:
- * <pre>
- * {@code @Grab}(group='commons-lang', module='commons-lang', version='2.4')
- * import org.apache.commons.lang.WordUtils
- * println "Hello ${WordUtils.capitalize('world')}"
- * </pre>
- * Or using the compact Gradle-inspired syntax:
- * <pre>
- * {@code @Grab}('commons-lang:commons-lang:2.4')
- * import org.apache.commons.lang.WordUtils
- * println "Hello ${WordUtils.capitalize('world')}"
- * </pre>
- * or the same thing again using the Ivy-inspired syntax variant:
- * <pre>
- * {@code @Grab}('commons-lang#commons-lang;2.4')
- * import org.apache.commons.lang.WordUtils
- * println "Hello ${WordUtils.capitalize('world')}"
- * </pre>
- * Further information such as where artifacts are downloaded to, how to add additional resolvers,
- * how to customise artifact resolution etc., can be found on the Grape documentation page:
- * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target({
-        ElementType.CONSTRUCTOR,
-        ElementType.FIELD,
-        ElementType.LOCAL_VARIABLE,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.TYPE})
-public @interface Grab {
-    /**
-     * The organisation or group, e.g.: "org.apache.ant". A non-empty value is required unless value() is used.
-     */
-    String group() default "";
-
-    /**
-     * The module or artifact, e.g.: "ant-junit". A non-empty value is required unless value() is used.
-     */
-    String module() default "";
-
-    /**
-     * The revision or version, e.g.: "1.7.1". A non-empty value is required unless value() is used.
-     */
-    String version() default "";
-
-    /**
-     * The classifier if in use, e.g.: "jdk14"
-     */
-    String classifier() default "";
-
-    /**
-     * Defaults to {@code true} but set to {@code false} if you don't want transitive dependencies also to be downloaded.
-     * You may then need additional {@code @Grab} statements for any required dependencies.
-     */
-    boolean transitive() default true;
-
-    /**
-     * Defaults to {@code false} but set to {@code true} to indicate to the underlying Ivy conflict manager that this
-     * dependency should be forced to the given revision. Otherwise, depending on the conflict manager in play, a later
-     * compatible version might be used instead.
-     */
-    boolean force() default false;
-
-    /**
-     * Defaults to {@code false} but set to {@code true} if the dependency artifacts may change without a corresponding
-     * revision change. Not normally recommended but may be useful for certain kinds of snapshot artifacts.
-     * May reduce the amount of underlying Ivy caching. Proper behavior may be dependent on the resolver in use.
-     */
-    boolean changing() default false;
-
-    /**
-     * The configuration if in use (normally only used by internal ivy repositories).
-     * One or more comma separated values with or without square brackets,
-     * e.g.&#160;for hibernate you might have "default,proxool,oscache" or "[default,dbcp,swarmcache]".
-     * This last hibernate example assumes you have set up such configurations in your local Ivy repo
-     * and have changed your grape config (using grapeConfig.xml) or the {@code @GrabConfig} annotation
-     * to point to that repo.
-     */
-    String conf() default "";
-
-    /**
-     * The extension of the artifact (normally safe to leave at default value of "jar" but other values like "zip"
-     * are sometimes useful).
-     */
-    String ext() default "";
-
-    /**
-     * The type of the artifact (normally safe to leave at default value of "jar" but other values like "sources" and "javadoc" are sometimes useful).
-     * But see also the "classifier" attribute which is also sometimes used for "sources" and "javadoc".
-     */
-    String type() default "";
-
-    /**
-     * Allows a more compact convenience form in one of two formats with optional appended attributes.
-     * Must not be used if group(), module() or version() are used.
-     * <p>
-     * You can choose either format but not mix-n-match:<br>
-     * {@code group:module:version:classifier@ext} (where only group and module are required)<br>
-     * {@code group#module;version[confs]} (where only group and module are required and confs,
-     * if used, is one or more comma separated configuration names)<br>
-     * In addition, you can add any valid Ivy attributes at the end of your string value using
-     * semi-colon separated name = value pairs, e.g.:<br>
-     * {@code @Grab('junit:junit:*;transitive=false')}<br>
-     * {@code @Grab('group=junit;module=junit;version=4.8.2;classifier=javadoc')}<br>
-     */
-    String value() default "";
-
-    /**
-     * By default, when a {@code @Grab} annotation is used, a {@code Grape.grab()} call is added
-     * to the static initializers of the class the annotatable node appears in.
-     * If you wish to disable this, add {@code initClass=false} to the annotation.
-     */
-    boolean initClass() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GrabConfig.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GrabConfig.java b/src/main/groovy/lang/GrabConfig.java
deleted file mode 100644
index 7cbafb5..0000000
--- a/src/main/groovy/lang/GrabConfig.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to modify the grape configuration for grab requests.
- * <p>
- * An example involving databases:
- * <pre>
- * {@code @Grab}('mysql:mysql-connector-java:5.1.6'),
- * {@code @GrabConfig}(systemClassLoader=true)
- * import groovy.sql.Sql
- *
- * def sql=Sql.newInstance("jdbc:mysql://localhost/test", "user", "password", "com.mysql.jdbc.Driver")
- * println sql.firstRow('SELECT * FROM INFORMATION_SCHEMA.COLUMNS')
- * </pre>
- * Another example involving XStream:
- * <pre>
- * {@code @Grab}('com.thoughtworks.xstream:xstream:1.4.9'),
- * {@code @Grab}('xpp3:xpp3_min:1.1.4c'),
- * {@code @GrabConfig}(systemClassLoader=true, initContextClassLoader=true)
- * import com.thoughtworks.xstream.*
- *
- * class Staff {
- *     String firstname, lastname, position
- * }
- *
- * def xstream = new XStream()
- * def john1 = new Staff(firstname:'John',
- *                      lastname:'Connor',
- *                      position:'Resistance Leader')
- *
- * // write out to XML file
- * new File("john.xml").withOutputStream { out ->
- *     xstream.toXML(john1, out)
- * }
- *
- * // now read back in
- * def john2
- * new File("john.xml").withInputStream { ins ->
- *     john2 = xstream.fromXML(ins)
- * }
- *
- * println john2.dump()
- * </pre>
- * <p>
- * Further information about customising grape behavior can be found on the Grape documentation page:
- * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target({
-        ElementType.CONSTRUCTOR,
-        ElementType.FIELD,
-        ElementType.LOCAL_VARIABLE,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.TYPE})
-public @interface GrabConfig {
-    /**
-     * Set to true if you want to use the system classloader when loading the grape.
-     * This is normally only required when a core Java class needs to reference the grabbed
-     * classes, e.g. for a database driver accessed using DriverManager.
-     */
-    boolean systemClassLoader() default false;
-
-    /**
-     * Define any system properties which must be set before invoking the grab - useful for
-     * declaring SSL certificates or proxy settings. Currently, this only affects the generated
-     * class or script. You may need to also set those same properties for the Groovy compiler.
-     * For convenience, a String with comma separated name=value pairs
-     * can be used in addition to an array (using Groovy's literal list notation) of String name=value items.
-     * The single String shorthand form can't be used if value part of a property contains a comma.
-     *
-     * @since 2.4.5
-     */
-    String[] systemProperties() default "";
-
-    /**
-     * Set to true if you want the context classloader to be initialised to the classloader
-     * of the current class or script. This is useful for libraries or frameworks that assume
-     * that the context classloader has been set. But be careful when using this flag as your
-     * script or class might behave differently when called directly (from the command line or
-     * from an IDE) versus when called from within a container, e.g. a web container or a JEE container.
-     */
-    boolean initContextClassLoader() default false;
-
-    /**
-     * Set to false if you want to disable automatic downloading of locally missing jars.
-     */
-    boolean autoDownload() default true;
-
-    /**
-     * Set to true if you want to disable checksum checking.
-     */
-    boolean disableChecksums() default false;
-}
\ No newline at end of file


[39/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Closure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Closure.java b/src/main/groovy/groovy/lang/Closure.java
new file mode 100644
index 0000000..99d2ea9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Closure.java
@@ -0,0 +1,1054 @@
+/*
+ *  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 groovy.lang;
+
+import org.apache.groovy.internal.util.UncheckedThrow;
+import org.codehaus.groovy.reflection.ReflectionCache;
+import org.codehaus.groovy.reflection.stdclasses.CachedClosureClass;
+import org.codehaus.groovy.runtime.ComposedClosure;
+import org.codehaus.groovy.runtime.CurriedClosure;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
+import org.codehaus.groovy.runtime.memoize.LRUCache;
+import org.codehaus.groovy.runtime.memoize.Memoize;
+import org.codehaus.groovy.runtime.memoize.UnlimitedConcurrentCache;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * Represents any closure object in Groovy.
+ * <p>
+ * Groovy allows instances of Closures to be called in a
+ * short form. For example:
+ * <pre class="groovyTestCase">
+ * def a = 1
+ * def c = { a }
+ * assert c() == 1
+ * </pre>
+ * To be able to use a Closure in this way with your own
+ * subclass, you need to provide a doCall method with any
+ * signature you want to. This ensures that
+ * {@link #getMaximumNumberOfParameters()} and
+ * {@link #getParameterTypes()} will work too without any
+ * additional code. If no doCall method is provided a
+ * closure must be used in its long form like
+ * <pre class="groovyTestCase">
+ * def a = 1
+ * def c = {a}
+ * assert c.call() == 1
+ * </pre>
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author <a href="mailto:tug@wilson.co.uk">John Wilson</a>
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ * @author Graeme Rocher
+ * @author Paul King
+ */
+public abstract class Closure<V> extends GroovyObjectSupport implements Cloneable, Runnable, GroovyCallable<V>, Serializable {
+
+    /**
+     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
+     * owner first, then the delegate (<b>this is the default strategy</b>).
+     *
+     * For example the following code:
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y }
+     *         cl.delegate = data
+     *         cl()
+     *         assert x == 30
+     *         assert y == 70
+     *         assert data == [x:10, y:20]
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     * Will succeed, because the x and y fields declared in the Test class shadow the variables in the delegate.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int OWNER_FIRST = 0;
+
+    /**
+     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
+     * delegate first then the owner.
+     *
+     * For example the following code:
+     * <pre class="groovyTestCase">
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.DELEGATE_FIRST
+     *         cl()
+     *         assert x == 30
+     *         assert y == 40
+     *         assert data == [x:10, y:30]
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     * This will succeed, because the x and y variables declared in the delegate shadow the fields in the owner class.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int DELEGATE_FIRST = 1;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references and methods to the owner only
+     * and not call the delegate at all. For example the following code :
+     *
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20, z: 30 ]
+     *         def cl = { y = x + y + z }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.OWNER_ONLY
+     *         cl()
+     *         println x
+     *         println y
+     *         println data
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     *
+     * will throw "No such property: z" error because even if the z variable is declared in the delegate, no
+     * lookup is made.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int OWNER_ONLY = 2;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references and methods to the delegate
+     * only and entirely bypass the owner. For example the following code :
+     *
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *     def z = 50
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y + z }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.DELEGATE_ONLY
+     *         cl()
+     *         println x
+     *         println y
+     *         println data
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     *
+     * will throw an error because even if the owner declares a "z" field, the resolution strategy will bypass
+     * lookup in the owner.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int DELEGATE_ONLY = 3;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references to itself and go
+     * through the usual MetaClass look-up process. This means that properties and methods are neither resolved
+     * from the owner nor the delegate, but only on the closure object itself. This allows the developer to
+     * override getProperty using ExpandoMetaClass of the closure itself.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int TO_SELF = 4;
+
+    public static final int DONE = 1, SKIP = 2;
+    private static final Object[] EMPTY_OBJECT_ARRAY = {};
+    public static final Closure IDENTITY = new Closure<Object>(null) {
+        public Object doCall(Object args) {
+            return args;
+        }
+    };
+
+    private Object delegate;
+    private Object owner;
+    private Object thisObject;
+    private int resolveStrategy = OWNER_FIRST;
+    private int directive;
+    protected Class[] parameterTypes;
+    protected int maximumNumberOfParameters;
+    private static final long serialVersionUID = 4368710879820278874L;
+    private BooleanClosureWrapper bcw;
+
+    public Closure(Object owner, Object thisObject) {
+        this.owner = owner;
+        this.delegate = owner;
+        this.thisObject = thisObject;
+
+        final CachedClosureClass cachedClass = (CachedClosureClass) ReflectionCache.getCachedClass(getClass());
+        parameterTypes = cachedClass.getParameterTypes();
+        maximumNumberOfParameters = cachedClass.getMaximumNumberOfParameters();
+    }
+
+    /**
+     * Constructor used when the "this" object for the Closure is null.
+     * This is rarely the case in normal Groovy usage.
+     *
+     * @param owner the Closure owner
+     */
+    public Closure(Object owner) {
+        this(owner, null);
+    }
+
+    /**
+     * Sets the strategy which the closure uses to resolve property references and methods.
+     * The default is Closure.OWNER_FIRST
+     *
+     * @param resolveStrategy The resolve strategy to set
+     *
+     * @see groovy.lang.Closure#DELEGATE_FIRST
+     * @see groovy.lang.Closure#DELEGATE_ONLY
+     * @see groovy.lang.Closure#OWNER_FIRST
+     * @see groovy.lang.Closure#OWNER_ONLY
+     * @see groovy.lang.Closure#TO_SELF
+     */
+    public void setResolveStrategy(int resolveStrategy) {
+        this.resolveStrategy = resolveStrategy;
+    }
+
+    /**
+     * Gets the strategy which the closure uses to resolve methods and properties
+     *
+     * @return The resolve strategy
+     *
+     * @see groovy.lang.Closure#DELEGATE_FIRST
+     * @see groovy.lang.Closure#DELEGATE_ONLY
+     * @see groovy.lang.Closure#OWNER_FIRST
+     * @see groovy.lang.Closure#OWNER_ONLY
+     * @see groovy.lang.Closure#TO_SELF
+     */
+    public int getResolveStrategy() {
+        return resolveStrategy;
+    }
+
+    public Object getThisObject(){
+        return thisObject;
+    }
+
+    public Object getProperty(final String property) {
+        if ("delegate".equals(property)) {
+            return getDelegate();
+        } else if ("owner".equals(property)) {
+            return getOwner();
+        } else if ("maximumNumberOfParameters".equals(property)) {
+            return getMaximumNumberOfParameters();
+        } else if ("parameterTypes".equals(property)) {
+            return getParameterTypes();
+        } else if ("metaClass".equals(property)) {
+            return getMetaClass();
+        } else if ("class".equals(property)) {
+            return getClass();
+        } else if ("directive".equals(property)) {
+            return getDirective();
+        } else if ("resolveStrategy".equals(property)) {
+            return getResolveStrategy();
+        } else if ("thisObject".equals(property)) {
+            return getThisObject();
+        } else {
+            switch(resolveStrategy) {
+                case DELEGATE_FIRST:
+                    return getPropertyDelegateFirst(property);
+                case DELEGATE_ONLY:
+                    return InvokerHelper.getProperty(this.delegate, property);
+                case OWNER_ONLY:
+                    return InvokerHelper.getProperty(this.owner, property);
+                case TO_SELF:
+                    return super.getProperty(property);
+                default:
+                    return getPropertyOwnerFirst(property);
+            }
+        }
+    }
+
+    private Object getPropertyDelegateFirst(String property) {
+        if (delegate == null) return getPropertyOwnerFirst(property);
+        return getPropertyTryThese(property, this.delegate, this.owner);
+    }
+
+    private Object getPropertyOwnerFirst(String property) {
+        return getPropertyTryThese(property, this.owner, this.delegate);
+    }
+
+    private Object getPropertyTryThese(String property, Object firstTry, Object secondTry) {
+        try {
+            // let's try getting the property on the first object
+            return InvokerHelper.getProperty(firstTry, property);
+
+        } catch (MissingPropertyException e1) {
+            if (secondTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try getting the property on the second object
+                    return InvokerHelper.getProperty(secondTry, property);
+                } catch (GroovyRuntimeException e2) {
+                    // ignore, we'll throw e1
+                }
+            }
+            throw e1;
+
+        } catch (MissingFieldException e2)  { // see GROOVY-5875
+            if (secondTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try getting the property on the second object
+                    return InvokerHelper.getProperty(secondTry, property);
+                } catch (GroovyRuntimeException e3) {
+                    // ignore, we'll throw e2
+                }
+            }
+            throw e2;
+        }
+    }
+
+    public void setProperty(String property, Object newValue) {
+        if ("delegate".equals(property)) {
+            setDelegate(newValue);
+        } else if ("metaClass".equals(property)) {
+            setMetaClass((MetaClass) newValue);
+        } else if ("resolveStrategy".equals(property)) {
+            setResolveStrategy(((Number) newValue).intValue());
+        } else if ("directive".equals(property)) {
+            setDirective(((Number) newValue).intValue());
+        } else {
+            switch(resolveStrategy) {
+                case DELEGATE_FIRST:
+                    setPropertyDelegateFirst(property, newValue);
+                break;
+                case DELEGATE_ONLY:
+                    InvokerHelper.setProperty(this.delegate, property, newValue);
+                break;
+                case OWNER_ONLY:
+                    InvokerHelper.setProperty(this.owner, property, newValue);
+                break;
+                case TO_SELF:
+                    super.setProperty(property, newValue);
+                break;
+                default:
+                    setPropertyOwnerFirst(property, newValue);
+            }
+        }
+    }
+
+    private void setPropertyDelegateFirst(String property, Object newValue) {
+        if (delegate == null) setPropertyOwnerFirst(property, newValue);
+        else setPropertyTryThese(property, newValue, this.delegate, this.owner);
+    }
+
+    private void setPropertyOwnerFirst(String property, Object newValue) {
+        setPropertyTryThese(property, newValue, this.owner, this.delegate);
+    }
+
+    private void setPropertyTryThese(String property, Object newValue, Object firstTry, Object secondTry) {
+        try {
+            // let's try setting the property on the first object
+            InvokerHelper.setProperty(firstTry, property, newValue);
+        } catch (GroovyRuntimeException e1) {
+            if (firstTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try setting the property on the second object
+                    InvokerHelper.setProperty(secondTry, property, newValue);
+                    return;
+                } catch (GroovyRuntimeException e2) {
+                    // ignore, we'll throw e1
+                }
+            }
+            throw e1;
+        }
+    }
+
+    public boolean isCase(Object candidate){
+        if (bcw==null) {
+            bcw = new BooleanClosureWrapper(this);
+        }
+        return bcw.call(candidate);
+    }
+
+    /**
+     * Invokes the closure without any parameters, returning any value if applicable.
+     *
+     * @return the value if applicable or null if there is no return statement in the closure
+     */
+    public V call() {
+        final Object[] NOARGS = EMPTY_OBJECT_ARRAY;
+        return call(NOARGS);
+    }
+
+    @SuppressWarnings("unchecked")
+    public V call(Object... args) {
+        try {
+            return (V) getMetaClass().invokeMethod(this,"doCall",args);
+        } catch (InvokerInvocationException e) {
+            UncheckedThrow.rethrow(e.getCause());
+            return null; // unreachable statement
+        }  catch (Exception e) {
+            return (V) throwRuntimeException(e);
+        }
+    }
+
+    /**
+     * Invokes the closure, returning any value if applicable.
+     *
+     * @param arguments could be a single value or a List of values
+     * @return the value if applicable or null if there is no return statement in the closure
+     */
+    public V call(final Object arguments) {
+        return call(new Object[]{arguments});
+    }
+
+    protected static Object throwRuntimeException(Throwable throwable) {
+        if (throwable instanceof RuntimeException) {
+            throw (RuntimeException) throwable;
+        } else {
+            throw new GroovyRuntimeException(throwable.getMessage(), throwable);
+        }
+    }
+
+    /**
+     * @return the owner Object to which method calls will go which is
+     *         typically the outer class when the closure is constructed
+     */
+    public Object getOwner() {
+        return this.owner;
+    }
+
+    /**
+     * @return the delegate Object to which method calls will go which is
+     *         typically the outer class when the closure is constructed
+     */
+    public Object getDelegate() {
+        return this.delegate;
+    }
+
+    /**
+     * Allows the delegate to be changed such as when performing markup building
+     *
+     * @param delegate the new delegate
+     */
+    public void setDelegate(Object delegate) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * @return the parameter types of the longest doCall method
+     * of this closure
+     */
+    public Class[] getParameterTypes() {
+        return parameterTypes;
+    }
+
+    /**
+     * @return the maximum number of parameters a doCall method
+     * of this closure can take
+     */
+    public int getMaximumNumberOfParameters() {
+        return maximumNumberOfParameters;
+    }
+
+    /**
+     * @return a version of this closure which implements Writable.  Note that
+     * the returned Writable also overrides {@link #toString()} in order
+     * to allow rendering the result directly to a String.
+     */
+    public Closure asWritable() {
+        return new WritableClosure();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Runnable#run()
+     */
+    public void run() {
+        call();
+    }
+
+    /**
+     * Support for Closure currying.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def multiply = { a, b -> a * b }
+     * def doubler = multiply.curry(2)
+     * assert doubler(4) == 8
+     * </pre>
+     * Note: special treatment is given to Closure vararg-style capability.
+     * If you curry a vararg parameter, you don't consume the entire vararg array
+     * but instead the first parameter of the vararg array as the following example shows:
+     * <pre class="groovyTestCase">
+     * def a = { one, two, Object[] others -> one + two + others.sum() }
+     * assert a.parameterTypes.name == ['java.lang.Object', 'java.lang.Object', '[Ljava.lang.Object;']
+     * assert a(1,2,3,4) == 10
+     * def b = a.curry(1)
+     * assert b.parameterTypes.name == ['java.lang.Object', '[Ljava.lang.Object;']
+     * assert b(2,3,4) == 10
+     * def c = b.curry(2)
+     * assert c.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert c(3,4) == 10
+     * def d = c.curry(3)
+     * assert d.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert d(4) == 10
+     * def e = d.curry(4)
+     * assert e.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert e() == 10
+     * assert e(5) == 15
+     * </pre>
+     *
+     *
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     */
+    public Closure<V> curry(final Object... arguments) {
+        return new CurriedClosure<V>(this, arguments);
+    }
+
+    /**
+     * Support for Closure currying.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> curry(final Object argument) {
+        return curry(new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure "right" currying.
+     * Parameters are supplied on the right rather than left as per the normal curry() method.
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def divide = { a, b -> a / b }
+     * def halver = divide.rcurry(2)
+     * assert halver(8) == 4
+     * </pre>
+     *
+     * The position of the curried parameters will be calculated lazily, for example,
+     * if two overloaded doCall methods are available, the supplied arguments plus the
+     * curried arguments will be concatenated and the result used for method selection.
+     *
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> rcurry(final Object... arguments) {
+        return new CurriedClosure<V>(-arguments.length, this, arguments);
+    }
+
+    /**
+     * Support for Closure "right" currying.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #rcurry(Object...)
+     */
+    public Closure<V> rcurry(final Object argument) {
+        return rcurry(new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure currying at a given index.
+     * Parameters are supplied from index position "n".
+     * Typical usage:
+     * <pre>
+     * def caseInsensitive = { a, b -> a.toLowerCase() <=> b.toLowerCase() } as Comparator
+     * def caseSensitive = { a, b -> a <=> b } as Comparator
+     * def animals1 = ['ant', 'dog', 'BEE']
+     * def animals2 = animals1 + ['Cat']
+     * // curry middle param of this utility method:
+     * // Collections#binarySearch(List list, Object key, Comparator c)
+     * def catSearcher = Collections.&binarySearch.ncurry(1, "cat")
+     * [[animals1, animals2], [caseInsensitive, caseSensitive]].combinations().each{ a, c ->
+     *   def idx = catSearcher(a.sort(c), c)
+     *   print a.sort(c).toString().padRight(22)
+     *   if (idx < 0) println "Not found but would belong in position ${-idx - 1}"
+     *   else println "Found at index $idx"
+     * }
+     * // =>
+     * // [ant, BEE, dog]       Not found but would belong in position 2
+     * // [ant, BEE, Cat, dog]  Found at index 2
+     * // [BEE, ant, dog]       Not found but would belong in position 2
+     * // [BEE, Cat, ant, dog]  Not found but would belong in position 3
+     * </pre>
+     *
+     * The position of the curried parameters will be calculated eagerly
+     * and implies all arguments prior to the specified n index are supplied.
+     * Default parameter values prior to the n index will not be available.
+     *
+     * @param n the index from which to bind parameters (may be -ve in which case it will be normalized)
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> ncurry(int n, final Object... arguments) {
+        return new CurriedClosure<V>(n, this, arguments);
+    }
+
+    /**
+     * Support for Closure currying at a given index.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #ncurry(int, Object...)
+     */
+    public Closure<V> ncurry(int n, final Object argument) {
+        return ncurry(n, new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure forward composition.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a + 3 }
+     * def timesThenAdd = times2 >> add3
+     * // equivalent: timesThenAdd = { a -> add3(times2(a)) }
+     * assert timesThenAdd(3) == 9
+     * </pre>
+     *
+     * @param other the Closure to compose with the current Closure
+     * @return the new composed Closure
+     */
+    public <W> Closure<W> rightShift(final Closure<W> other) {
+        return new ComposedClosure<W>(this, other);
+    }
+
+    /**
+     * Support for Closure reverse composition.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a + 3 }
+     * def addThenTimes = times2 << add3
+     * // equivalent: addThenTimes = { a -> times2(add3(a)) }
+     * assert addThenTimes(3) == 12
+     * </pre>
+     *
+     * @param other the Closure to compose with the current Closure
+     * @return the new composed Closure
+     */
+    public Closure<V> leftShift(final Closure other) {
+        return new ComposedClosure<V>(other, this);
+    }
+
+    /* *
+     * Alias for calling a Closure for non-closure arguments.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a * 3 }
+     * assert add3 << times2 << 3 == 9
+     * </pre>
+     *
+     * @param arg the argument to call the closure with
+     * @return the result of calling the Closure
+     */
+    public V leftShift(final Object arg) {
+        return call(arg);
+    }
+
+    /**
+     * Creates a caching variant of the closure.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant will keep all cached values forever, i.e. till the closure gets garbage-collected.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     *
+     * @return A new closure forwarding to the original one while caching the results
+     */
+    public Closure<V> memoize() {
+        return Memoize.buildMemoizeFunction(new UnlimitedConcurrentCache(), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with upper limit on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant will keep all values until the upper size limit is reached. Then the values in the cache start rotating
+     * using the LRU (Last Recently Used) strategy.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     *
+     * @param maxCacheSize The maximum size the cache can grow to
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeAtMost(final int maxCacheSize) {
+        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeAtMost.");
+
+        return Memoize.buildMemoizeFunction(new LRUCache(maxCacheSize), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with automatic cache size adjustment and lower limit
+     * on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant allows the garbage collector to release entries from the cache and at the same time allows
+     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
+     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
+     * the LRU (Last Recently Used) strategy.
+     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the limits
+     * set by the user if memory is plentiful.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
+     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     * @param protectedCacheSize Number of cached return values to protect from garbage collection
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeAtLeast(final int protectedCacheSize) {
+        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeAtLeast.");
+
+        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new UnlimitedConcurrentCache(), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with automatic cache size adjustment and lower and upper limits
+     * on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant allows the garbage collector to release entries from the cache and at the same time allows
+     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
+     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
+     * the LRU (Last Recently Used) strategy.
+     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the protected
+     * size limits set by the user, if memory is plentiful.
+     * Also, this variant will never exceed in size the upper size limit. Once the upper size limit has been reached,
+     * the values in the cache start rotating using the LRU (Last Recently Used) strategy.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
+     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     * @param protectedCacheSize Number of cached return values to protect from garbage collection
+     * @param maxCacheSize The maximum size the cache can grow to
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeBetween(final int protectedCacheSize, final int maxCacheSize) {
+        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeBetween.");
+        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeBetween.");
+        if (protectedCacheSize > maxCacheSize) throw new IllegalArgumentException("The maxCacheSize parameter to memoizeBetween is required to be greater or equal to the protectedCacheSize parameter.");
+
+        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new LRUCache(maxCacheSize), this);
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
+     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
+     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
+     * which will be executed by the trampoline as the next step.
+     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
+     * Here is an example:
+     * <pre>
+     * def fact
+     * fact = { n, total ->
+     *     n == 0 ? total : fact.trampoline(n - 1, n * total)
+     * }.trampoline()
+     * def factorial = { n -> fact(n, 1G)}
+     * println factorial(20) // => 2432902008176640000
+     * </pre>
+     *
+     * @param args Parameters to the closure, so as the trampoline mechanism can call it
+     * @return A closure, which will execute the original closure on a trampoline.
+     */
+    public Closure<V> trampoline(final Object... args) {
+        return new TrampolineClosure<V>(this.curry(args));
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
+     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
+     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
+     * which will be executed by the trampoline as the next step.
+     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
+     * @return A closure, which will execute the original closure on a trampoline.
+     * @see #trampoline(Object...)
+     */
+    public Closure<V> trampoline() {
+        return new TrampolineClosure<V>(this);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (final CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    /*
+     * Implementation note:
+     *   This has to be an inner class!
+     *
+     * Reason:
+     *   Closure.this.call will call the outer call method, but
+     * with the inner class as executing object. This means any
+     * invokeMethod or getProperty call will be called on this
+     * inner class instead of the outer!
+     */
+    private class WritableClosure extends Closure implements Writable {
+        public WritableClosure() {
+            super(Closure.this);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Writable#writeTo(java.io.Writer)
+         */
+        public Writer writeTo(Writer out) throws IOException {
+            Closure.this.call(new Object[]{out});
+
+            return out;
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
+         */
+        public Object invokeMethod(String method, Object arguments) {
+            if ("clone".equals(method)) {
+                return clone();
+            } else if ("curry".equals(method)) {
+                return curry((Object[]) arguments);
+            } else if ("asWritable".equals(method)) {
+                return asWritable();
+            } else {
+                return Closure.this.invokeMethod(method, arguments);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
+         */
+        public Object getProperty(String property) {
+            return Closure.this.getProperty(property);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
+         */
+        public void setProperty(String property, Object newValue) {
+            Closure.this.setProperty(property, newValue);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#call()
+         */
+        public Object call() {
+            return ((Closure) getOwner()).call();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#call(java.lang.Object)
+         */
+        public Object call(Object arguments) {
+            return ((Closure) getOwner()).call(arguments);
+        }
+
+        public Object call(Object... args) {
+            return ((Closure) getOwner()).call(args);
+        }
+
+        public Object doCall(Object... args) {
+            return call(args);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getDelegate()
+         */
+        public Object getDelegate() {
+            return Closure.this.getDelegate();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#setDelegate(java.lang.Object)
+         */
+        public void setDelegate(Object delegate) {
+            Closure.this.setDelegate(delegate);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getParameterTypes()
+         */
+        public Class[] getParameterTypes() {
+            return Closure.this.getParameterTypes();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getParameterTypes()
+         */
+        public int getMaximumNumberOfParameters() {
+            return Closure.this.getMaximumNumberOfParameters();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#asWritable()
+         */
+        public Closure asWritable() {
+            return this;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        public void run() {
+            Closure.this.run();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#clone()
+         */
+        public Object clone() {
+            return ((Closure) Closure.this.clone()).asWritable();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        public int hashCode() {
+            return Closure.this.hashCode();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        public boolean equals(Object arg0) {
+            return Closure.this.equals(arg0);
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#toString()
+         */
+        public String toString() {
+            final StringWriter writer = new StringWriter();
+
+            try {
+                writeTo(writer);
+            } catch (IOException e) {
+                return null;
+            }
+
+            return writer.toString();
+        }
+
+        public Closure curry(final Object... arguments) {
+            return (new CurriedClosure(this, arguments)).asWritable();
+        }
+
+        public void setResolveStrategy(int resolveStrategy) {
+            Closure.this.setResolveStrategy(resolveStrategy);
+        }
+
+        public int getResolveStrategy() {
+            return Closure.this.getResolveStrategy();
+        }
+    }
+
+    /**
+     * @return Returns the directive.
+     */
+    public int getDirective() {
+        return directive;
+    }
+
+    /**
+     * @param directive The directive to set.
+     */
+    public void setDirective(int directive) {
+        this.directive = directive;
+    }
+
+    /**
+     * Returns a copy of this closure where the "owner", "delegate" and "thisObject"
+     * fields are null, allowing proper serialization when one of them is not serializable.
+     *
+     * @return a serializable closure.
+     *
+     * @since 1.8.5
+     */
+    @SuppressWarnings("unchecked")
+    public Closure<V> dehydrate() {
+        Closure<V> result = (Closure<V>) this.clone();
+        result.delegate = null;
+        result.owner = null;
+        result.thisObject = null;
+        return result;
+    }
+
+    /**
+     * Returns a copy of this closure for which the delegate, owner and thisObject are
+     * replaced with the supplied parameters. Use this when you want to rehydrate a
+     * closure which has been made serializable thanks to the {@link #dehydrate()}
+     * method.
+     * @param delegate the closure delegate
+     * @param owner the closure owner
+     * @param thisObject the closure "this" object
+     * @return a copy of this closure where owner, delegate and thisObject are replaced
+     *
+     * @since 1.8.5
+     */
+    @SuppressWarnings("unchecked")
+    public Closure<V> rehydrate(Object delegate, Object owner, Object thisObject) {
+        Closure<V> result = (Closure<V>) this.clone();
+        result.delegate = delegate;
+        result.owner = owner;
+        result.thisObject = thisObject;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ClosureException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ClosureException.java b/src/main/groovy/groovy/lang/ClosureException.java
new file mode 100644
index 0000000..12986ad
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ClosureException.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 groovy.lang;
+
+/**
+ * An exception thrown by a closure invocation
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ClosureException extends RuntimeException {
+
+    private final Closure closure;
+    
+    public ClosureException(Closure closure, Throwable cause) {
+        super("Exception thrown by call to closure: " + closure + " reason: " + cause, cause);
+        this.closure = closure;
+    }
+
+    public Closure getClosure() {
+        return closure;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ClosureInvokingMethod.java b/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
new file mode 100644
index 0000000..3e54278
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
@@ -0,0 +1,48 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * An interface for MetaMethods that invoke closures to implements. Used by ExpandoMetaClass
+ *
+ * @see groovy.lang.ExpandoMetaClass
+ * 
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public interface ClosureInvokingMethod {
+
+    /**
+     * Returns the original closure that this method invokes
+     * @return The closure
+     */
+    Closure getClosure();
+
+    /**
+     * Is it a static method?
+     * @return True if it is
+     */
+    boolean isStatic();
+
+    /**
+     * The method name
+     * @return The method name
+     */
+    String getName();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Delegate.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Delegate.java b/src/main/groovy/groovy/lang/Delegate.java
new file mode 100644
index 0000000..180dc84
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Delegate.java
@@ -0,0 +1,218 @@
+/*
+ *  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 groovy.lang;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to automatically delegate part of the functionality of an owner class to the
+ * annotated delegation target. The target can be a field (or property) or a method's return value.
+ * <p>
+ * The delegate type is either the type of the annotated field (or property) or the return type of
+ * the annotated method. The method can be thought of as a getter or factory method for the delegate.
+ * All public instance methods present in the delegate type and not present in the owner class
+ * will be added to owner class at compile time. The implementation of such automatically added
+ * methods is code which calls through to the delegate as per the normal delegate pattern.
+ * <p>
+ * As an example, consider this code:
+ * <pre class="groovyTestCase">
+ * class Event {
+ *     {@code @Delegate} Date when
+ *     String title, url
+ * }
+ *
+ * def gr8conf = new Event(title: "GR8 Conference",
+ *                           url: "http://www.gr8conf.org",
+ *                          when: Date.parse("yyyy/MM/dd", "2009/05/18"))
+ *
+ * def javaOne = new Event(title: "JavaOne",
+ *                           url: "http://java.sun.com/javaone/",
+ *                          when: Date.parse("yyyy/MM/dd", "2009/06/02"))
+ *
+ * assert gr8conf.before(javaOne.when)
+ * </pre>
+ *
+ * In this example, the {@code Event} class will have a method called
+ * {@code before(Date otherDate)} as well as other public methods of the
+ * {@code Date} class.
+ * The implementation of the {@code before()} method will look like this:
+ * <pre>
+ *     public boolean before(Date otherDate) {
+ *         return when.before(otherDate);
+ *     }
+ * </pre>
+ *
+ * By default, the owner class will also be modified to implement any interfaces
+ * implemented by the delegate type. So, in the example above, because {@code Date}
+ * implements {@code Cloneable} the following will be true:
+ *
+ * <pre>
+ * assert gr8conf instanceof Cloneable
+ * </pre>
+ *
+ * This behavior can be disabled by setting the
+ * annotation's {@code interfaces} element to false,
+ * i.e. {@code @Delegate(interfaces = false)}, e.g. in the above
+ * example, the delegate definition would become:
+ * <pre>
+ *     {@code @Delegate}(interfaces = false) Date when
+ * </pre>
+ * and the following would be true:
+ * <pre>
+ * assert !(gr8conf instanceof Cloneable)
+ * </pre>
+ *
+ * If multiple delegation targets are used and the same method signature occurs
+ * in more than one of the respective delegate types, then the delegate will be
+ * made to the first defined target having that signature. If this does occur,
+ * it might be regarded as a smell (or at least poor style) and it might be
+ * clearer to do the delegation by long hand.
+ * <p>
+ * By default, methods of the delegate type marked as {@code @Deprecated} are
+ * not automatically added to the owner class (but see the technical note
+ * about interfaces below). You can force these methods to
+ * be added by setting the annotation's {@code deprecated} element to true,
+ * i.e. {@code @Delegate(deprecated = true)}.
+ * <p>
+ * For example, in the example above if we change the delegate definition to:
+ * <pre>
+ *     {@code @Delegate}(deprecated = true) Date when
+ * </pre>
+ * then the following additional lines will execute successfully (during 2009):
+ * <pre>
+ * assert gr8conf.year + 1900 == 2009
+ * assert gr8conf.toGMTString().contains(" 2009 ")
+ * </pre>
+ * Otherwise these lines produce a groovy.lang.MissingPropertyException
+ * or groovy.lang.MissingMethodException respectively as those two methods are
+ * {@code @Deprecated} in {@code Date}.
+ * <p>
+ * <b>Technical notes</b>:
+ * <ul>
+ * <li>Static methods, synthetic methods or methods from the <code>GroovyObject</code> interface
+ * are not candidates for delegation</li>
+ * <li>Non-abstract non-static methods defined in the owner class or its superclasses take
+ * precedence over methods with identical signatures from a {@code @Delegate} target</li>
+ * <li>All methods defined in the owner class (including static, abstract or private etc.)
+ * take precedence over methods with identical signatures from a {@code @Delegate} target</li>
+ * <li>Recursive delegation to your own class is not allowed</li>
+ * <li>Mixing of {@code @Delegate} with default method arguments is known not to work in some cases.
+ * We recommend not using these features together.</li>
+ * <li>When the delegate type is an interface, the {@code deprecated} attribute will be
+ * ignored if the owner class implements that interface (i.e. you must set {@code interfaces=false}
+ * if you want the {@code deprecated} attribute to be used). Otherwise, the resulting class would
+ * not compile anyway without manually adding in any deprecated methods in the interface.</li>
+ * <li>{@code @Delegate} can work in combination with {@code @Lazy} when annotating a field (or property)</li>
+ * </ul>
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.DelegateASTTransformation")
+public @interface Delegate {
+    /**
+     * @return true if owner class should implement interfaces implemented by delegate type
+     */
+    boolean interfaces() default true;
+
+    /**
+     * Whether to apply the delegate pattern to deprecated methods; to avoid compilation
+     * errors, this is ignored if the type of the delegate target is an interface and
+     * {@code interfaces=true}.
+     *
+     * @return true if owner class should delegate to methods annotated with @Deprecated
+     */
+    boolean deprecated() default false;
+
+    /**
+     * Whether to carry over annotations from the methods of the delegate
+     * to your delegating method. Currently Closure annotation members are
+     * not supported.
+     *
+     * @return true if generated delegate methods should keep method annotations
+     */
+    boolean methodAnnotations() default false;
+
+    /**
+     * Whether to carry over annotations from the parameters of delegate
+     * methods to your delegating method. Currently Closure annotation members are
+     * not supported.
+     *
+     * @return true if generated delegate methods should keep parameter annotations
+     */
+    boolean parameterAnnotations() default false;
+
+    /**
+     * List of method and/or property names to exclude when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.2.0
+     */
+    String[] excludes() default {};
+
+
+    /**
+     * List of interfaces containing method signatures to exclude when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.3.0
+     */
+    Class[] excludeTypes() default {};
+
+    /**
+     * List of method and/or property names to include when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields
+     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
+     * If interfaces is true (the default), you will need to manually supply any methods not included
+     * via delegation that are required for the interface.
+     * @since 2.2.0
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * List of interfaces containing method signatures to include when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * The default value is a special marker value indicating that no includeTypes are defined.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.3.0
+     */
+    Class[] includeTypes() default {Undefined.CLASS.class};
+
+    /**
+     * Whether to apply the delegate pattern to all methods, including those with names that are considered internal.
+     *
+     * @return true if owner class should delegate to methods which have internal names
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DelegatesTo.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DelegatesTo.java b/src/main/groovy/groovy/lang/DelegatesTo.java
new file mode 100644
index 0000000..54a5e36
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DelegatesTo.java
@@ -0,0 +1,96 @@
+/*
+ *  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 groovy.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be used by API or DSL writers to document parameters which accept a closure.
+ * In that case, using this annotation, you can specify what the delegate type of the closure will
+ * be. This is important for IDE support.
+ * <p>
+ * This annotation can also be used to help the type checker ({@link groovy.transform.TypeChecked})
+ * which would not report errors then if the delegate is of the documented type. Of course, it is
+ * also compatible with {@link groovy.transform.CompileStatic}.
+ * <p>
+ * Example:
+ * <pre>
+ * // Document the fact that the delegate of the closure will be an ExecSpec
+ * ExecResult exec(@DelegatesTo(ExecSpec) Closure closure) { ... }
+ * </pre>
+ *
+ * @author Cedric Champeau
+ * @author Peter Niderwieser
+ * @since 2.1.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface DelegatesTo {
+    Class value() default Target.class;
+
+    /**
+     * The {@link Closure#resolveStrategy} used by the closure.
+     */
+    int strategy() default Closure.OWNER_FIRST;
+
+    /**
+     * The index of the generic type that will be the type of the closure's delegate.
+     * The generic types are considered with respect to the {@code @DelegatesTo.Target} annotated
+     * parameter for this usage, with the index starting at 0.
+     */
+    int genericTypeIndex() default -1;
+
+    /**
+     * In cases when there are multiple {@code @DelegatesTo.Target} annotated parameters, this
+     * member should be set to the {@link DelegatesTo.Target#value()} of the correct target.
+     */
+    String target() default "";
+
+    /**
+     * The type member should be used when the type of the delegate cannot
+     * be represented with {@link #value()}, {@link #genericTypeIndex()} or
+     * {@link #target()}. In this case, it is possible to use a String to represent
+     * the type, at the cost of potential uncaught errors at compile time if the
+     * type is invalid and increased compile time.
+     *
+     * @return a String representation of a type
+     * @since 2.4.0
+     */
+    String type() default "";
+
+    /**
+     * Parameter annotation used to specify the delegate for a {@code @DelegatesTo} annotated
+     * parameter of the same method.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target({ElementType.PARAMETER})
+    public static @interface Target {
+
+        /**
+         * An identifier that should be used to disambiguate targets when there are
+         * multiple {@code @DelegatesTo.Target} annotated parameters.
+         */
+        String value() default "";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DelegatingMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DelegatingMetaClass.java b/src/main/groovy/groovy/lang/DelegatingMetaClass.java
new file mode 100644
index 0000000..ee2ade9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DelegatingMetaClass.java
@@ -0,0 +1,308 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author John Wilson
+ */
+
+public class DelegatingMetaClass implements MetaClass, MutableMetaClass, GroovyObject {
+    protected MetaClass delegate;
+
+    public DelegatingMetaClass(final MetaClass delegate) {
+        this.delegate = delegate;
+    }
+
+    public DelegatingMetaClass(final Class theClass) {
+        this(GroovySystem.getMetaClassRegistry().getMetaClass(theClass));
+    }
+
+    public boolean isModified() {
+        return this.delegate instanceof MutableMetaClass && ((MutableMetaClass) this.delegate).isModified();
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#addNewInstanceMethod(java.lang.reflect.Method)
+    */
+    public void addNewInstanceMethod(Method method) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addNewInstanceMethod(method);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#addNewStaticMethod(java.lang.reflect.Method)
+    */
+    public void addNewStaticMethod(Method method) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addNewStaticMethod(method);
+    }
+
+    public void addMetaMethod(MetaMethod metaMethod) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addMetaMethod(metaMethod);
+    }
+
+    public void addMetaBeanProperty(MetaBeanProperty metaBeanProperty) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addMetaBeanProperty(metaBeanProperty);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#initialize()
+    */
+    public void initialize() {
+        delegate.initialize();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getAttribute(java.lang.Object, java.lang.String)
+     */
+    public Object getAttribute(Object object, String attribute) {
+        return delegate.getAttribute(object, attribute);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getClassNode()
+     */
+    public ClassNode getClassNode() {
+        return delegate.getClassNode();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getMetaMethods()
+     */
+    public List<MetaMethod> getMetaMethods() {
+        return delegate.getMetaMethods();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getMethods()
+     */
+    public List<MetaMethod> getMethods() {
+        return delegate.getMethods();
+    }
+
+    public List<MetaMethod> respondsTo(Object obj, String name, Object[] argTypes) {
+        return delegate.respondsTo(obj, name, argTypes);
+    }
+
+    public List<MetaMethod> respondsTo(Object obj, String name) {
+        return delegate.respondsTo(obj, name);
+    }
+
+    public MetaProperty hasProperty(Object obj, String name) {
+        return delegate.hasProperty(obj, name);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#getProperties()
+    */
+    public List<MetaProperty> getProperties() {
+        return delegate.getProperties();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getProperty(java.lang.Object, java.lang.String)
+     */
+    public Object getProperty(Object object, String property) {
+        return delegate.getProperty(object, property);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeConstructor(java.lang.Object[])
+     */
+    public Object invokeConstructor(Object[] arguments) {
+        return delegate.invokeConstructor(arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public Object invokeMethod(Object object, String methodName, Object arguments) {
+        return delegate.invokeMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object[])
+     */
+    public Object invokeMethod(Object object, String methodName, Object[] arguments) {
+        return delegate.invokeMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeStaticMethod(java.lang.Object, java.lang.String, java.lang.Object[])
+     */
+    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
+        return delegate.invokeStaticMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#setAttribute(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public void setAttribute(Object object, String attribute, Object newValue) {
+        delegate.setAttribute(object, attribute, newValue);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#setProperty(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public void setProperty(Object object, String property, Object newValue) {
+        delegate.setProperty(object, property, newValue);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        return delegate.equals(obj);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    public String toString() {
+        return super.toString() + "[" + delegate.toString() + "]";
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public MetaMethod pickMethod(String methodName, Class[] arguments) {
+        return delegate.pickMethod(methodName, arguments);
+    }
+
+    public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
+        return this.delegate.getAttribute(sender, receiver, messageName, useSuper);
+    }
+
+    public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
+        return this.delegate.getProperty(sender, receiver, messageName, useSuper, fromInsideClass);
+    }
+
+    public MetaProperty getMetaProperty(String name) {
+        return this.delegate.getMetaProperty(name);
+    }
+
+    public MetaMethod getStaticMetaMethod(String name, Object[] args) {
+        return this.delegate.getStaticMetaMethod(name, args);
+    }
+
+    public MetaMethod getStaticMetaMethod(String name, Class[] argTypes) {
+        return this.delegate.getStaticMetaMethod(name, argTypes);
+    }
+
+    public MetaMethod getMetaMethod(String name, Object[] args) {
+        return this.delegate.getMetaMethod(name, args);
+    }
+
+    public Class getTheClass() {
+        return this.delegate.getTheClass();
+    }
+
+    public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass) {
+        return this.delegate.invokeMethod(sender, receiver, methodName, arguments, isCallToSuper, fromInsideClass);
+    }
+
+    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
+        return this.delegate.invokeMissingMethod(instance, methodName, arguments);
+    }
+
+    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
+        return this.delegate.invokeMissingProperty(instance, propertyName, optionalValue, isGetter);
+    }
+
+    public boolean isGroovyObject() {
+        return GroovyObject.class.isAssignableFrom(this.delegate.getTheClass());
+    }
+
+    public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
+        this.delegate.setAttribute(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
+    }
+
+    public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
+        this.delegate.setProperty(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
+    }
+
+    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
+        return this.delegate.selectConstructorAndTransformArguments(numberOfConstructors, arguments);
+    }
+
+    public void setAdaptee(MetaClass adaptee) {
+        this.delegate = adaptee;
+    }
+
+    public MetaClass getAdaptee() {
+        return this.delegate;
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return getMetaClass().invokeMethod(this, name, args);
+        }
+        catch (MissingMethodException e) {
+            if (delegate instanceof GroovyObject)
+                return ((GroovyObject) delegate).invokeMethod(name, args);
+            else
+                throw e;
+        }
+    }
+
+    public Object getProperty(String property) {
+        try {
+            return getMetaClass().getProperty(this, property);
+        }
+        catch (MissingPropertyException e) {
+            if (delegate instanceof GroovyObject)
+                return ((GroovyObject) delegate).getProperty(property);
+            else
+                throw e;
+        }
+    }
+
+    public void setProperty(String property, Object newValue) {
+        try {
+            getMetaClass().setProperty(this, property, newValue);
+        }
+        catch (MissingPropertyException e) {
+            if (delegate instanceof GroovyObject)
+                ((GroovyObject) delegate).setProperty(property, newValue);
+            else
+                throw e;
+        }
+    }
+
+    public MetaClass getMetaClass() {
+        return InvokerHelper.getMetaClass(getClass());
+    }
+
+    public void setMetaClass(MetaClass metaClass) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DeprecationException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DeprecationException.java b/src/main/groovy/groovy/lang/DeprecationException.java
new file mode 100644
index 0000000..36ad893
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DeprecationException.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 groovy.lang;
+
+/**
+ * Use this exception to mark a method implementation as being deprecated.
+ *
+ * Use the message to indicate the recommended way of calling the desired functionality.
+ * Make throwing this exception the only line in the method implementation, i.e. unlike
+ * the JavaDoc deprecated feature there is no relay to the new implementation but an early
+ * and deliberate halt of execution ("fail early").
+ *
+ * This exception is supposed to be used in the SNAPSHOT releases only. Before release, all
+ * references to this exception should be resolved and the according methods removed.
+ *
+ * @author Dierk Koenig
+ */
+public class DeprecationException extends RuntimeException {
+
+    public DeprecationException(String message) {
+        super(message);
+    }
+
+    public DeprecationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/EmptyRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/EmptyRange.java b/src/main/groovy/groovy/lang/EmptyRange.java
new file mode 100644
index 0000000..b67b32e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/EmptyRange.java
@@ -0,0 +1,214 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Constructing Ranges like 0..&lt;0
+ */
+public class EmptyRange<T extends Comparable> extends AbstractList<T> implements Range<T> {
+
+    /**
+     * The value at which the range originates (may be <code>null</code>).
+     */
+    protected T at;
+
+    /**
+     * Creates a new {@link EmptyRange}.
+     *
+     * @param at the value at which the range starts (may be <code>null</code>).
+     */
+    public EmptyRange(T at) {
+        this.at = at;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public T getFrom() {
+        return at;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public T getTo() {
+        return at;
+    }
+
+    /**
+     * Never true for an empty range.
+     *
+     * @return <code>false</code>
+     */
+    @Override
+    public boolean isReverse() {
+        return false;
+    }
+
+    /**
+     * Never true for an empty range.
+     *
+     * @return <code>false</code>
+     */
+    @Override
+    public boolean containsWithinBounds(Object o) {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String inspect() {
+        return InvokerHelper.inspect(at) + "..<" + InvokerHelper.inspect(at);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return (null == at)
+                ? "null..<null"
+                : at + "..<" + at;
+    }
+
+    /**
+     * Always 0 for an empty range.
+     *
+     * @return 0
+     */
+    @Override
+    public int size() {
+        return 0;
+    }
+
+    /**
+     * Always throws <code>IndexOutOfBoundsException</code> for an empty range.
+     *
+     * @throws IndexOutOfBoundsException always
+     */
+    @Override
+    public T get(int index) {
+        throw new IndexOutOfBoundsException("can't get values from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    @Override
+    public boolean add(T o) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean addAll(int index, Collection<? extends T> c) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean remove(Object o) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public T remove(int index) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("cannot retainAll in Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public T set(int index, T element) {
+        throw new UnsupportedOperationException("cannot set in Empty Ranges");
+    }
+
+    /**
+     * Always does nothing for an empty range.
+     */
+    @Override
+    public void step(int step, Closure closure) {
+    }
+
+    /**
+     * Always returns an empty list for an empty range.
+     */
+    @Override
+    public List<T> step(int step) {
+        return new ArrayList<T>();
+    }
+}


[11/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/tools/GrapeMain.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/tools/GrapeMain.groovy b/src/main/groovy/org/codehaus/groovy/tools/GrapeMain.groovy
new file mode 100644
index 0000000..2f53afa
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/tools/GrapeMain.groovy
@@ -0,0 +1,308 @@
+/*
+ *  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.tools
+
+import groovy.grape.Grape
+import groovy.transform.Field
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Option
+import org.apache.commons.cli.OptionGroup
+import org.apache.commons.cli.Options
+import org.apache.ivy.util.DefaultMessageLogger
+import org.apache.ivy.util.Message
+
+//commands
+
+@Field install = {arg, cmd ->
+    if (arg.size() > 5 || arg.size() < 3) {
+        println 'install requires two to four arguments: <group> <module> [<version> [<classifier>]]'
+        return
+    }
+    def ver = '*'
+    if (arg.size() >= 4) {
+        ver = arg[3]
+    }
+    def classifier = null
+    if (arg.size() >= 5) {
+        classifier = arg[4]
+    }
+
+    // set the instance so we can re-set the logger
+    Grape.getInstance()
+    setupLogging()
+
+    cmd.getOptionValues('r')?.each { String url ->
+        Grape.addResolver(name:url, root:url)
+    }
+
+    try {
+        Grape.grab(autoDownload: true, group: arg[1], module: arg[2], version: ver, classifier: classifier, noExceptions: true)
+    } catch (Exception e) {
+        println "An error occured : $ex"
+    }
+}
+
+@Field uninstall = {arg, cmd ->
+    if (arg.size() != 4) {
+        println 'uninstall requires three arguments: <group> <module> <version>'
+        // TODO make version optional? support classifier?
+//        println 'uninstall requires two to four arguments, <group> <module> [<version>] [<classifier>]'
+        return
+    }
+    String group = arg[1]
+    String module = arg[2]
+    String ver = arg[3]
+//    def classifier = null
+
+    // set the instance so we can re-set the logger
+    Grape.getInstance()
+    setupLogging()
+
+    if (!Grape.enumerateGrapes().find {String groupName, Map g ->
+        g.any {String moduleName, List<String> versions ->
+            group == groupName && module == moduleName && ver in versions
+        }
+    }) {
+        println "uninstall did not find grape matching: $group $module $ver"
+        def fuzzyMatches = Grape.enumerateGrapes().findAll { String groupName, Map g ->
+            g.any {String moduleName, List<String> versions ->
+                groupName.contains(group) || moduleName.contains(module) ||
+                group.contains(groupName) || module.contains(moduleName)
+            }
+        }
+        if (fuzzyMatches) {
+            println 'possible matches:'
+            fuzzyMatches.each { String groupName, Map g -> println "    $groupName: $g" }
+        }
+        return
+    }
+    Grape.instance.uninstallArtifact(group, module, ver)
+}
+
+@Field list = {arg, cmd ->
+    println ""
+
+    int moduleCount = 0
+    int versionCount = 0
+
+    // set the instance so we can re-set the logger
+    Grape.getInstance()
+    setupLogging()
+
+    Grape.enumerateGrapes().each {String groupName, Map group ->
+        group.each {String moduleName, List<String> versions ->
+            println "$groupName $moduleName  $versions"
+            moduleCount++
+            versionCount += versions.size()
+        }
+    }
+    println ""
+    println "$moduleCount Grape modules cached"
+    println "$versionCount Grape module versions cached"
+}
+
+@Field resolve = {arg, cmd ->
+    Options options = new Options();
+    options.addOption(Option.builder("a").hasArg(false).longOpt("ant").build());
+    options.addOption(Option.builder("d").hasArg(false).longOpt("dos").build());
+    options.addOption(Option.builder("s").hasArg(false).longOpt("shell").build());
+    options.addOption(Option.builder("i").hasArg(false).longOpt("ivy").build());
+    CommandLine cmd2 = new DefaultParser().parse(options, arg[1..-1] as String[], true);
+    arg = cmd2.args
+
+    // set the instance so we can re-set the logger
+    Grape.getInstance()
+    setupLogging(Message.MSG_ERR)
+
+    if ((arg.size() % 3) != 0) {
+        println 'There needs to be a multiple of three arguments: (group module version)+'
+        return
+    }
+    if (args.size() < 3) {
+        println 'At least one Grape reference is required'
+        return
+    }
+    def before, between, after
+    def ivyFormatRequested = false
+
+    if (cmd2.hasOption('a')) {
+        before = '<pathelement location="'
+        between = '">\n<pathelement location="'
+        after = '">'
+    } else if (cmd2.hasOption('d')) {
+        before = 'set CLASSPATH='
+        between = ';'
+        after = ''
+    } else if (cmd2.hasOption('s')) {
+        before = 'export CLASSPATH='
+        between = ':'
+        after = ''
+    } else if (cmd2.hasOption('i')) {
+        ivyFormatRequested = true
+        before = '<dependency '
+        between = '">\n<dependency '
+        after = '">'
+    } else {
+        before = ''
+        between = '\n'
+        after = '\n'
+    }
+
+    iter = arg.iterator()
+    def params = [[:]]
+    def depsInfo = [] // this list will contain the module/group/version info of all resolved dependencies
+    if(ivyFormatRequested) {
+        params << depsInfo
+    }
+    while (iter.hasNext()) {
+        params.add([group: iter.next(), module: iter.next(), version: iter.next()])
+    }
+    try {
+        def results = []
+        def uris = Grape.resolve(* params)
+        if(!ivyFormatRequested) {
+            for (URI uri: uris) {
+                if (uri.scheme == 'file') {
+                    results += new File(uri).path
+                } else {
+                    results += uri.toASCIIString()
+                }
+            }
+        } else {
+            depsInfo.each { dep ->
+                results += ('org="' + dep.group + '" name="' + dep.module + '" revision="' + dep.revision)
+            }
+        }
+
+        if (results) {
+            println "${before}${results.join(between)}${after}"
+        } else {
+            println 'Nothing was resolved'
+        }
+    } catch (Exception e) {
+        println "Error in resolve:\n\t$e.message"
+        if (e.message =~ /unresolved dependency/) println "Perhaps the grape is not installed?"
+    }
+}
+
+@Field help = { arg, cmd -> grapeHelp() }
+
+@Field commands = [
+    'install': [closure: install,
+        shortHelp: 'Installs a particular grape'],
+    'uninstall': [closure: uninstall,
+        shortHelp: 'Uninstalls a particular grape (non-transitively removes the respective jar file from the grape cache)'],
+    'list': [closure: list,
+        shortHelp: 'Lists all installed grapes'],
+    'resolve': [closure: resolve,
+        shortHelp: 'Enumerates the jars used by a grape'],
+    'help': [closure: help,
+        shortHelp: 'Usage information']
+]
+
+@Field grapeHelp = {
+    int spacesLen = commands.keySet().max {it.length()}.length() + 3
+    String spaces = ' ' * spacesLen
+
+    PrintWriter pw = new PrintWriter(binding.variables.out ?: System.out)
+    new HelpFormatter().printHelp(
+            pw,
+            80,
+            "grape [options] <command> [args]\n",
+            "options:",
+            options,
+            2,
+            4,
+            null, // footer
+            true);
+    pw.flush()
+
+    println ""
+    println "commands:"
+    commands.each {String k, v ->
+        println "  ${(k + spaces).substring(0, spacesLen)} $v.shortHelp"
+    }
+    println ""
+}
+
+@Field setupLogging = {int defaultLevel = 2 -> // = Message.MSG_INFO -> some parsing error :(
+    if (cmd.hasOption('q')) {
+        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_ERR))
+    } else if (cmd.hasOption('w')) {
+        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_WARN))
+    } else if (cmd.hasOption('i')) {
+        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_INFO))
+    } else if (cmd.hasOption('V')) {
+        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_VERBOSE))
+    } else if (cmd.hasOption('d')) {
+        Message.setDefaultLogger(new DefaultMessageLogger(Message.MSG_DEBUG))
+    } else {
+        Message.setDefaultLogger(new DefaultMessageLogger(defaultLevel))
+    }
+}
+
+// command line parsing
+@Field Options options = new Options();
+
+options.addOption(Option.builder("D").longOpt("define").desc("define a system property").numberOfArgs(2).valueSeparator().argName("name=value").build());
+options.addOption(Option.builder("r").longOpt("resolver").desc("define a grab resolver (for install)").hasArg(true).argName("url").build());
+options.addOption(Option.builder("h").hasArg(false).desc("usage information").longOpt("help").build());
+
+// Logging Level Options
+options.addOptionGroup(
+        new OptionGroup()
+                .addOption(Option.builder("q").hasArg(false).desc("Log level 0 - only errors").longOpt("quiet").build())
+                .addOption(Option.builder("w").hasArg(false).desc("Log level 1 - errors and warnings").longOpt("warn").build())
+                .addOption(Option.builder("i").hasArg(false).desc("Log level 2 - info").longOpt("info").build())
+                .addOption(Option.builder("V").hasArg(false).desc("Log level 3 - verbose").longOpt("verbose").build())
+                .addOption(Option.builder("d").hasArg(false).desc("Log level 4 - debug").longOpt("debug").build())
+)
+options.addOption(Option.builder("v").hasArg(false).desc("display the Groovy and JVM versions").longOpt("version").build());
+
+@Field CommandLine cmd
+
+cmd = new DefaultParser().parse(options, args, true);
+
+if (cmd.hasOption('h')) {
+    grapeHelp()
+    return
+}
+
+if (cmd.hasOption('v')) {
+    String version = GroovySystem.getVersion();
+    println "Groovy Version: $version JVM: ${System.getProperty('java.version')}"
+    return
+}
+
+if (options.hasOption('D')) {
+    options.getOptionProperties('D')?.each { k, v ->
+        System.setProperty(k, v)
+    }
+}
+
+String[] arg = cmd.args
+if (arg?.length == 0) {
+    grapeHelp()
+} else if (commands.containsKey(arg[0])) {
+    commands[arg[0]].closure(arg, cmd)
+} else {
+    println "grape: '${arg[0]}' is not a grape command. See 'grape --help'"
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/tools/ast/TransformTestHelper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/tools/ast/TransformTestHelper.groovy b/src/main/groovy/org/codehaus/groovy/tools/ast/TransformTestHelper.groovy
new file mode 100644
index 0000000..ce98d58
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/tools/ast/TransformTestHelper.groovy
@@ -0,0 +1,123 @@
+/*
+ *  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.tools.ast
+
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.classgen.GeneratorContext
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.transform.ASTTransformation
+
+import java.security.CodeSource
+
+/*
+* This TestHarness exists so that a global transform can be run without
+* using the Jar services mechanism, which requires building a jar.
+* 
+* To use this simply create an instance of TransformTestHelper with
+* an ASTTransformation and CompilePhase, then invoke parse(File) or
+* parse(String). 
+* 
+* This test harness is not exactly the same as executing a global transformation
+* but can greatly aide in debugging and testing a transform. You should still
+* test your global transformation when packaged as a jar service before
+* releasing it. 
+* 
+* @author Hamlet D'Arcy
+*/
+class TransformTestHelper {
+
+    private final ASTTransformation transform
+    private final CompilePhase phase
+
+    /**
+     * Creates the test helper.
+     * @param transform
+     *      the transform to run when compiling the file later
+     * @param phase
+     *      the phase to run the transform in 
+     */
+    def TransformTestHelper(ASTTransformation transform, CompilePhase phase) {
+        this.transform = transform
+        this.phase = phase
+    }
+
+    /**
+     * Compiles the File into a Class applying the transform specified in the constructor.
+     * @input input
+     *      must be a groovy source file
+     */
+    public Class parse(File input) {
+        TestHarnessClassLoader loader = new TestHarnessClassLoader(transform, phase)
+        return loader.parseClass(input)
+    }
+
+    /**
+     * Compiles the String into a Class applying the transform specified in the constructor.
+     * @input input
+     *      must be a valid groovy source string
+     */
+    public Class parse(String input) {
+        TestHarnessClassLoader loader = new TestHarnessClassLoader(transform, phase)
+        return loader.parseClass(input)
+    }
+}
+
+/**
+* ClassLoader exists so that TestHarnessOperation can be wired into the compile. 
+*
+* @author Hamlet D'Arcy
+*/
+@groovy.transform.PackageScope class TestHarnessClassLoader extends GroovyClassLoader {
+
+    private final ASTTransformation transform
+    private final CompilePhase phase
+
+    TestHarnessClassLoader(ASTTransformation transform, CompilePhase phase) {
+        this.transform = transform
+        this.phase = phase
+    }
+
+    protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource codeSource) {
+        CompilationUnit cu = super.createCompilationUnit(config, codeSource)
+        cu.addPhaseOperation(new TestHarnessOperation(transform), phase.getPhaseNumber())
+        return cu
+    }
+}
+
+/**
+* Operation exists so that an AstTransformation can be run against the SourceUnit.
+*
+* @author Hamlet D'Arcy
+*/
+@groovy.transform.PackageScope class TestHarnessOperation extends PrimaryClassNodeOperation {
+
+    private final ASTTransformation transform
+
+    def TestHarnessOperation(transform) {
+        this.transform = transform;
+    }
+
+    public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
+        transform.visit(null, source)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
new file mode 100644
index 0000000..dcfe314
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
@@ -0,0 +1,233 @@
+/*
+ *  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.transform
+
+import groovy.transform.CompilationUnitAware
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.PropertyExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.ErrorCollector
+import org.codehaus.groovy.control.Janitor
+import org.codehaus.groovy.control.ProcessingUnit
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.codehaus.groovy.control.io.ReaderSource
+import org.codehaus.groovy.runtime.MethodClosure
+import org.codehaus.groovy.syntax.SyntaxException
+import org.codehaus.groovy.tools.Utilities
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
+
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+class ASTTestTransformation extends AbstractASTTransformation implements CompilationUnitAware {
+    private CompilationUnit compilationUnit
+
+    void visit(final ASTNode[] nodes, final SourceUnit source) {
+        AnnotationNode annotationNode = nodes[0]
+        def member = annotationNode.getMember('phase')
+        def phase = null
+        if (member) {
+            if (member instanceof VariableExpression) {
+                phase = CompilePhase.valueOf(member.text)
+            } else if (member instanceof PropertyExpression) {
+                phase = CompilePhase.valueOf(member.propertyAsString)
+            }
+            annotationNode.setMember('phase', propX(classX(ClassHelper.make(CompilePhase)), phase.toString()))
+        }
+        member = annotationNode.getMember('value')
+        if (member && !(member instanceof ClosureExpression)) {
+            throw new SyntaxException("ASTTest value must be a closure", member.getLineNumber(), member.getColumnNumber())
+        }
+        if (!member && !annotationNode.getNodeMetaData(ASTTestTransformation)) {
+            throw new SyntaxException("Missing test expression", annotationNode.getLineNumber(), annotationNode.getColumnNumber())
+        }
+        // convert value into node metadata so that the expression doesn't mix up with other AST xforms like type checking
+        annotationNode.putNodeMetaData(ASTTestTransformation, member)
+        annotationNode.getMembers().remove('value')
+
+        def pcallback = compilationUnit.progressCallback
+        def callback = new CompilationUnit.ProgressCallback() {
+            Binding binding = new Binding([:].withDefault {null})
+
+            @Override
+            void call(final ProcessingUnit context, final int phaseRef) {
+                if (phase==null ||  phaseRef == phase.phaseNumber) {
+                    ClosureExpression testClosure = nodes[0].getNodeMetaData(ASTTestTransformation)
+                    StringBuilder sb = new StringBuilder()
+                    for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i++) {
+                        sb.append(source.source.getLine(i, new Janitor())).append('\n')
+                    }
+                    def testSource = sb.substring(testClosure.columnNumber + 1, sb.length())
+                    testSource = testSource.substring(0, testSource.lastIndexOf('}'))
+                    CompilerConfiguration config = new CompilerConfiguration()
+                    def customizer = new ImportCustomizer()
+                    config.addCompilationCustomizers(customizer)
+                    binding['sourceUnit'] = source
+                    binding['node'] = nodes[1]
+                    binding['lookup'] = new MethodClosure(LabelFinder, "lookup").curry(nodes[1])
+                    binding['compilationUnit'] = compilationUnit
+                    binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseRef)
+
+                    GroovyShell shell = new GroovyShell(binding, config)
+
+                    source.AST.imports.each {
+                        customizer.addImport(it.alias, it.type.name)
+                    }
+                    source.AST.starImports.each {
+                        customizer.addStarImports(it.packageName)
+                    }
+                    source.AST.staticImports.each {
+                        customizer.addStaticImport(it.value.alias, it.value.type.name, it.value.fieldName)
+                    }
+                    source.AST.staticStarImports.each {
+                        customizer.addStaticStars(it.value.className)
+                    }
+                    shell.evaluate(testSource)
+                }
+            }
+        }
+        
+        if (pcallback!=null) {
+            if (pcallback instanceof ProgressCallbackChain) {
+                pcallback.addCallback(callback)                
+            } else {
+                pcallback = new ProgressCallbackChain(pcallback, callback)
+            }
+            callback = pcallback
+        }
+        
+        compilationUnit.setProgressCallback(callback)
+
+    }
+
+    void setCompilationUnit(final CompilationUnit unit) {
+        this.compilationUnit = unit
+    }
+
+    private static class AssertionSourceDelegatingSourceUnit extends SourceUnit {
+        private final ReaderSource delegate
+
+        AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration flags, final GroovyClassLoader loader, final ErrorCollector er) {
+            super(name, '', flags, loader, er)
+            delegate = source
+        }
+
+        @Override
+        String getSample(final int line, final int column, final Janitor janitor) {
+            String sample = null;
+            String text = delegate.getLine(line, janitor);
+
+            if (text != null) {
+                if (column > 0) {
+                    String marker = Utilities.repeatString(" ", column - 1) + "^";
+
+                    if (column > 40) {
+                        int start = column - 30 - 1;
+                        int end = (column + 10 > text.length() ? text.length() : column + 10 - 1);
+                        sample = "   " + text.substring(start, end) + Utilities.eol() + "   " +
+                                marker.substring(start, marker.length());
+                    } else {
+                        sample = "   " + text + Utilities.eol() + "   " + marker;
+                    }
+                } else {
+                    sample = text;
+                }
+            }
+
+            return sample;
+
+        }
+
+    }
+    
+    private static class ProgressCallbackChain extends CompilationUnit.ProgressCallback {
+
+        private final List<CompilationUnit.ProgressCallback> chain = new LinkedList<CompilationUnit.ProgressCallback>()
+
+        ProgressCallbackChain(CompilationUnit.ProgressCallback... callbacks) {
+            if (callbacks!=null) {
+                callbacks.each { addCallback(it) }
+            }
+        }
+
+        public void addCallback(CompilationUnit.ProgressCallback callback) {
+            chain << callback
+        }
+        
+        @Override
+        void call(final ProcessingUnit context, final int phase) {
+            chain*.call(context, phase)
+        }
+    }
+
+    public static class LabelFinder extends ClassCodeVisitorSupport {
+
+        public static List<Statement> lookup(MethodNode node, String label) {
+            LabelFinder finder = new LabelFinder(label, null)
+            node.code.visit(finder)
+
+            finder.targets
+        }
+
+        public static List<Statement> lookup(ClassNode node, String label) {
+            LabelFinder finder = new LabelFinder(label, null)
+            node.methods*.code*.visit(finder)
+            node.declaredConstructors*.code*.visit(finder)
+
+            finder.targets
+        }
+
+        private final String label
+        private final SourceUnit unit
+
+        private final List<Statement> targets = new LinkedList<Statement>();
+
+        LabelFinder(final String label, final SourceUnit unit) {
+            this.label = label
+            this.unit = unit;
+        }
+
+        @Override
+        protected SourceUnit getSourceUnit() {
+            unit
+        }
+
+        @Override
+        protected void visitStatement(final Statement statement) {
+            super.visitStatement(statement)
+            if (statement.statementLabel==label) targets << statement
+        }
+
+        List<Statement> getTargets() {
+            return Collections.unmodifiableList(targets)
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
new file mode 100644
index 0000000..2cda121
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
@@ -0,0 +1,145 @@
+/*
+ *  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.transform
+
+import groovy.transform.ConditionalInterrupt
+import org.codehaus.groovy.ast.AnnotatedNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.PropertyNode
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.tools.ClosureUtils
+import org.codehaus.groovy.control.CompilePhase
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding a custom conditional
+ * check on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
+ * statement on the beginning of method calls.
+ *
+ * @see groovy.transform.ConditionalInterrupt
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ * @author Paul King
+ * @since 1.8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+public class ConditionalInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
+
+  private static final ClassNode MY_TYPE = ClassHelper.make(ConditionalInterrupt)
+
+  private ClosureExpression conditionNode
+  private String conditionMethod
+  private MethodCallExpression conditionCallExpression
+  private ClassNode currentClass
+
+  protected ClassNode type() {
+    return MY_TYPE
+  }
+
+  protected void setupTransform(AnnotationNode node) {
+    super.setupTransform(node)
+    def member = node.getMember("value")
+    if (!member || !(member instanceof ClosureExpression)) internalError("Expected closure value for annotation parameter 'value'. Found $member")
+    conditionNode = member;
+    conditionMethod = 'conditionalTransform' + node.hashCode() + '$condition'
+    conditionCallExpression = new MethodCallExpression(new VariableExpression('this'), conditionMethod, new ArgumentListExpression())
+  }
+
+  protected String getErrorMessage() {
+    'Execution interrupted. The following condition failed: ' + convertClosureToSource(conditionNode)
+  }
+
+  void visitClass(ClassNode type) {
+    currentClass = type
+    def method = type.addMethod(conditionMethod, ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, conditionNode.code)
+    method.synthetic = true
+    if (applyToAllMembers) {
+      super.visitClass(type)
+    }
+  }
+
+  protected Expression createCondition() {
+    conditionCallExpression
+  }
+
+  @Override
+  void visitAnnotations(AnnotatedNode node) {
+    // this transformation does not apply on annotation nodes
+    // visiting could lead to stack overflows
+  }
+
+  @Override
+  void visitField(FieldNode node) {
+    if (!node.isStatic() && !node.isSynthetic()) {
+      super.visitField node
+    }
+  }
+
+  @Override
+  void visitProperty(PropertyNode node) {
+    if (!node.isStatic() && !node.isSynthetic()) {
+      super.visitProperty node
+    }
+  }
+
+  @Override
+  void visitClosureExpression(ClosureExpression closureExpr) {
+    if (closureExpr == conditionNode) return // do not visit the closure from the annotation itself
+    def code = closureExpr.code
+    closureExpr.code = wrapBlock(code)
+    super.visitClosureExpression closureExpr
+  }
+
+  @Override
+  void visitMethod(MethodNode node) {
+    if (node.name == conditionMethod && !node.isSynthetic()) return // do not visit the generated method
+    if (node.name == 'run' && currentClass.isScript() && node.parameters.length == 0) {
+      // the run() method should not have the statement added, otherwise the script binding won't be set before
+      // the condition is actually tested
+      super.visitMethod(node)
+    } else {
+      if (checkOnMethodStart && !node.isSynthetic() && !node.isStatic() && !node.isAbstract()) {
+        def code = node.code
+        node.code = wrapBlock(code);
+      }
+      if (!node.isSynthetic() && !node.isStatic()) super.visitMethod(node)
+    }
+  }
+
+  /**
+   * Converts a ClosureExpression into the String source.
+   * @param expression a closure
+   * @return the source the closure was created from
+   */
+  private String convertClosureToSource(ClosureExpression expression) {
+    try {
+        return ClosureUtils.convertClosureToSource(this.source.source, expression);
+    } catch(Exception e) {
+        return e.message
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
new file mode 100644
index 0000000..a4fb4c3
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
@@ -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.transform
+
+import groovy.transform.CompileStatic
+import groovy.transform.ThreadInterrupt
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.ClassExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.control.CompilePhase
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding Thread.currentThread().isInterrupted()
+ * checks on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
+ * statement on the beginning of method calls.
+ *
+ * @see groovy.transform.ThreadInterrupt
+ *
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ *
+ * @since 1.8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+@CompileStatic
+public class ThreadInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
+
+    private static final ClassNode MY_TYPE = ClassHelper.make(ThreadInterrupt)
+    private static final ClassNode THREAD_TYPE = ClassHelper.make(Thread)
+    private static final MethodNode CURRENTTHREAD_METHOD
+    private static final MethodNode ISINTERRUPTED_METHOD
+
+    static {
+        CURRENTTHREAD_METHOD = THREAD_TYPE.getMethod('currentThread', Parameter.EMPTY_ARRAY)
+        ISINTERRUPTED_METHOD = THREAD_TYPE.getMethod('isInterrupted', Parameter.EMPTY_ARRAY)
+    }
+
+    protected ClassNode type() {
+        return MY_TYPE;
+    }
+
+    protected String getErrorMessage() {
+        'Execution interrupted. The current thread has been interrupted.'
+    }
+
+    protected Expression createCondition() {
+        def currentThread = new MethodCallExpression(new ClassExpression(THREAD_TYPE),
+                'currentThread',
+                ArgumentListExpression.EMPTY_ARGUMENTS)
+        currentThread.methodTarget = CURRENTTHREAD_METHOD
+        def isInterrupted = new MethodCallExpression(
+                currentThread,
+                'isInterrupted', ArgumentListExpression.EMPTY_ARGUMENTS)
+        isInterrupted.methodTarget = ISINTERRUPTED_METHOD
+        [currentThread, isInterrupted]*.implicitThis = false
+
+        isInterrupted
+    }
+
+
+    @Override
+    public void visitClosureExpression(ClosureExpression closureExpr) {
+        def code = closureExpr.code
+        closureExpr.code = wrapBlock(code)
+        super.visitClosureExpression closureExpr
+    }
+
+    @Override
+    public void visitMethod(MethodNode node) {
+        if (checkOnMethodStart && !node.isSynthetic() && !node.isAbstract()) {
+            def code = node.code
+            node.code = wrapBlock(code);
+        }
+        super.visitMethod(node)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
new file mode 100644
index 0000000..fbc923b
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
@@ -0,0 +1,321 @@
+/*
+ *  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.transform
+
+import groovy.transform.TimedInterrupt
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotatedNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.PropertyNode
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.DeclarationExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.DoWhileStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+import static org.codehaus.groovy.ast.ClassHelper.make
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ltX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.plusX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding timer expiration
+ * checks on loops (for, while, do) and first statement of closures. By default,
+ * also adds an interrupt check statement on the beginning of method calls.
+ *
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ * @author Paul King
+ * @see groovy.transform.ThreadInterrupt
+ * @since 1.8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+public class TimedInterruptibleASTTransformation extends AbstractASTTransformation {
+
+    private static final ClassNode MY_TYPE = make(TimedInterrupt)
+    private static final String CHECK_METHOD_START_MEMBER = 'checkOnMethodStart'
+    private static final String APPLY_TO_ALL_CLASSES = 'applyToAllClasses'
+    private static final String APPLY_TO_ALL_MEMBERS = 'applyToAllMembers'
+    private static final String THROWN_EXCEPTION_TYPE = "thrown"
+
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        init(nodes, source);
+        AnnotationNode node = nodes[0]
+        AnnotatedNode annotatedNode = nodes[1]
+        if (!MY_TYPE.equals(node.getClassNode())) {
+            internalError("Transformation called from wrong annotation: $node.classNode.name")
+        }
+
+        def checkOnMethodStart = getConstantAnnotationParameter(node, CHECK_METHOD_START_MEMBER, Boolean.TYPE, true)
+        def applyToAllMembers = getConstantAnnotationParameter(node, APPLY_TO_ALL_MEMBERS, Boolean.TYPE, true)
+        def applyToAllClasses = applyToAllMembers ? getConstantAnnotationParameter(node, APPLY_TO_ALL_CLASSES, Boolean.TYPE, true) : false
+        def maximum = getConstantAnnotationParameter(node, 'value', Long.TYPE, Long.MAX_VALUE)
+        def thrown = AbstractInterruptibleASTTransformation.getClassAnnotationParameter(node, THROWN_EXCEPTION_TYPE, make(TimeoutException))
+
+        Expression unit = node.getMember('unit') ?: propX(classX(TimeUnit), "SECONDS")
+
+        // should be limited to the current SourceUnit or propagated to the whole CompilationUnit
+        // DO NOT inline visitor creation in code below. It has state that must not persist between calls
+        if (applyToAllClasses) {
+            // guard every class and method defined in this script
+            source.getAST()?.classes?.each { ClassNode it ->
+                def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+                visitor.visitClass(it)
+            }
+        } else if (annotatedNode instanceof ClassNode) {
+            // only guard this particular class
+            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+            visitor.visitClass annotatedNode
+        } else if (!applyToAllMembers && annotatedNode instanceof MethodNode) {
+            // only guard this particular method (plus initCode for class)
+            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+            visitor.visitMethod annotatedNode
+            visitor.visitClass annotatedNode.declaringClass
+        } else if (!applyToAllMembers && annotatedNode instanceof FieldNode) {
+            // only guard this particular field (plus initCode for class)
+            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+            visitor.visitField annotatedNode
+            visitor.visitClass annotatedNode.declaringClass
+        } else if (!applyToAllMembers && annotatedNode instanceof DeclarationExpression) {
+            // only guard this particular declaration (plus initCode for class)
+            def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+            visitor.visitDeclarationExpression annotatedNode
+            visitor.visitClass annotatedNode.declaringClass
+        } else {
+            // only guard the script class
+            source.getAST()?.classes?.each { ClassNode it ->
+                if (it.isScript()) {
+                    def visitor = new TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, node.hashCode())
+                    visitor.visitClass(it)
+                }
+            }
+        }
+    }
+
+    static def getConstantAnnotationParameter(AnnotationNode node, String parameterName, Class type, defaultValue) {
+        def member = node.getMember(parameterName)
+        if (member) {
+            if (member instanceof ConstantExpression) {
+                // TODO not sure this try offers value - testing Groovy annotation type handing - throw GroovyBugError or remove?
+                try {
+                    return member.value.asType(type)
+                } catch (ignore) {
+                    internalError("Expecting boolean value for ${parameterName} annotation parameter. Found $member")
+                }
+            } else {
+                internalError("Expecting boolean value for ${parameterName} annotation parameter. Found $member")
+            }
+        }
+        return defaultValue
+    }
+
+    private static void internalError(String message) {
+        throw new RuntimeException("Internal error: $message")
+    }
+
+    private static class TimedInterruptionVisitor extends ClassCodeVisitorSupport {
+        final private SourceUnit source
+        final private boolean checkOnMethodStart
+        final private boolean applyToAllClasses
+        final private boolean applyToAllMembers
+        private FieldNode expireTimeField = null
+        private FieldNode startTimeField = null
+        private final Expression unit
+        private final maximum
+        private final ClassNode thrown
+        private final String basename
+
+        TimedInterruptionVisitor(source, checkOnMethodStart, applyToAllClasses, applyToAllMembers, maximum, unit, thrown, hash) {
+            this.source = source
+            this.checkOnMethodStart = checkOnMethodStart
+            this.applyToAllClasses = applyToAllClasses
+            this.applyToAllMembers = applyToAllMembers
+            this.unit = unit
+            this.maximum = maximum
+            this.thrown = thrown
+            this.basename = 'timedInterrupt' + hash
+        }
+
+        /**
+         * @return Returns the interruption check statement.
+         */
+        final createInterruptStatement() {
+            ifS(
+
+                    ltX(
+                            propX(varX("this"), basename + '$expireTime'),
+                            callX(make(System), 'nanoTime')
+                    ),
+                    throwS(
+                            ctorX(thrown,
+                                    args(
+                                            plusX(
+                                                    plusX(
+                                                            constX('Execution timed out after ' + maximum + ' '),
+                                                            callX(callX(unit, 'name'), 'toLowerCase', propX(classX(Locale), 'US'))
+                                                    ),
+                                                    plusX(
+                                                            constX('. Start time: '),
+                                                            propX(varX("this"), basename + '$startTime')
+                                                    )
+                                            )
+
+                                    )
+                            )
+                    )
+            )
+        }
+
+        /**
+         * Takes a statement and wraps it into a block statement which first element is the interruption check statement.
+         * @param statement the statement to be wrapped
+         * @return a {@link BlockStatement block statement}    which first element is for checking interruption, and the
+         * second one the statement to be wrapped.
+         */
+        private wrapBlock(statement) {
+            def stmt = new BlockStatement();
+            stmt.addStatement(createInterruptStatement());
+            stmt.addStatement(statement);
+            stmt
+        }
+
+        @Override
+        void visitClass(ClassNode node) {
+            if (node.getDeclaredField(basename + '$expireTime')) {
+                return
+            }
+            expireTimeField = node.addField(basename + '$expireTime',
+                    ACC_FINAL | ACC_PRIVATE,
+                    ClassHelper.long_TYPE,
+                    plusX(
+                            callX(make(System), 'nanoTime'),
+                            callX(
+                                    propX(classX(TimeUnit), 'NANOSECONDS'),
+                                    'convert',
+                                    args(constX(maximum, true), unit)
+                            )
+                    )
+            );
+            expireTimeField.synthetic = true
+            startTimeField = node.addField(basename + '$startTime',
+                    ACC_FINAL | ACC_PRIVATE,
+                    make(Date),
+                    ctorX(make(Date))
+            )
+            startTimeField.synthetic = true
+
+            // force these fields to be initialized first
+            node.fields.remove(expireTimeField)
+            node.fields.remove(startTimeField)
+            node.fields.add(0, startTimeField)
+            node.fields.add(0, expireTimeField)
+            if (applyToAllMembers) {
+                super.visitClass node
+            }
+        }
+
+        @Override
+        void visitClosureExpression(ClosureExpression closureExpr) {
+            def code = closureExpr.code
+            if (code instanceof BlockStatement) {
+                code.statements.add(0, createInterruptStatement())
+            } else {
+                closureExpr.code = wrapBlock(code)
+            }
+            super.visitClosureExpression closureExpr
+        }
+
+        @Override
+        void visitField(FieldNode node) {
+            if (!node.isStatic() && !node.isSynthetic()) {
+                super.visitField node
+            }
+        }
+
+        @Override
+        void visitProperty(PropertyNode node) {
+            if (!node.isStatic() && !node.isSynthetic()) {
+                super.visitProperty node
+            }
+        }
+
+        /**
+         * Shortcut method which avoids duplicating code for every type of loop.
+         * Actually wraps the loopBlock of different types of loop statements.
+         */
+        private visitLoop(loopStatement) {
+            def statement = loopStatement.loopBlock
+            loopStatement.loopBlock = wrapBlock(statement)
+        }
+
+        @Override
+        void visitForLoop(ForStatement forStatement) {
+            visitLoop(forStatement)
+            super.visitForLoop(forStatement)
+        }
+
+        @Override
+        void visitDoWhileLoop(final DoWhileStatement doWhileStatement) {
+            visitLoop(doWhileStatement)
+            super.visitDoWhileLoop(doWhileStatement)
+        }
+
+        @Override
+        void visitWhileLoop(final WhileStatement whileStatement) {
+            visitLoop(whileStatement)
+            super.visitWhileLoop(whileStatement)
+        }
+
+        @Override
+        void visitMethod(MethodNode node) {
+            if (checkOnMethodStart && !node.isSynthetic() && !node.isStatic() && !node.isAbstract()) {
+                def code = node.code
+                node.code = wrapBlock(code);
+            }
+            if (!node.isSynthetic() && !node.isStatic()) {
+                super.visitMethod(node)
+            }
+        }
+
+        protected SourceUnit getSourceUnit() {
+            return source;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/AstHelper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/AstHelper.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/AstHelper.groovy
new file mode 100644
index 0000000..cad5858
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/AstHelper.groovy
@@ -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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.ContinueStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.ast.stmt.ThrowStatement
+
+import java.lang.reflect.Modifier
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
+
+/**
+ * Helping to create a few standard AST constructs
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class AstHelper {
+	static ExpressionStatement createVariableDefinition(String variableName, ClassNode variableType, Expression value, boolean variableShouldBeFinal = false ) {
+        def newVariable = varX(variableName, variableType)
+        if (variableShouldBeFinal)
+            newVariable.setModifiers(Modifier.FINAL)
+        (ExpressionStatement) declS(newVariable, value)
+	}
+
+	static ExpressionStatement createVariableAlias(String aliasName, ClassNode variableType, String variableName ) {
+		createVariableDefinition(aliasName, variableType, varX(variableName, variableType))
+	}
+
+    static VariableExpression createVariableReference(Map variableSpec) {
+        varX((String) variableSpec.name, (ClassNode) variableSpec.type)
+    }
+
+    /**
+     * This statement should make the code jump to surrounding while loop's start label
+     * Does not work from within Closures
+     */
+    static Statement recurStatement() {
+        //continue _RECUR_HERE_
+        new ContinueStatement(org.codehaus.groovy.transform.tailrec.InWhileLoopWrapper.LOOP_LABEL)
+    }
+
+    /**
+     * This statement will throw exception which will be caught and redirected to jump to surrounding while loop's start label
+     * Also works from within Closures but is a tiny bit slower
+     */
+    static Statement recurByThrowStatement() {
+        // throw InWhileLoopWrapper.LOOP_EXCEPTION
+        new ThrowStatement(propX(classX(InWhileLoopWrapper), 'LOOP_EXCEPTION'))
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/CollectRecursiveCalls.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/CollectRecursiveCalls.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/CollectRecursiveCalls.groovy
new file mode 100644
index 0000000..2c7e6de
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/CollectRecursiveCalls.groovy
@@ -0,0 +1,62 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
+
+/**
+ * Collect all recursive calls within method
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class CollectRecursiveCalls extends CodeVisitorSupport {
+	MethodNode method
+	List<Expression> recursiveCalls = []
+
+	public void visitMethodCallExpression(MethodCallExpression call) {
+		if (isRecursive(call)) {
+			recursiveCalls << call
+		}
+        super.visitMethodCallExpression(call)
+    }
+
+	public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
+		if (isRecursive(call)) {
+            recursiveCalls << call
+        }
+		super.visitStaticMethodCallExpression(call)
+	}
+	
+	private boolean isRecursive(call) {
+		new RecursivenessTester().isRecursive(method: method, call: call)
+	}
+	
+	synchronized List<Expression> collect(MethodNode method) {
+		recursiveCalls.clear()
+		this.method = method
+		this.method.code.visit(this)
+		recursiveCalls
+	}
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/HasRecursiveCalls.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/HasRecursiveCalls.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/HasRecursiveCalls.groovy
new file mode 100644
index 0000000..695781b
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/HasRecursiveCalls.groovy
@@ -0,0 +1,64 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+
+/**
+ *
+ * Check if there are any recursive calls in a method
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class HasRecursiveCalls extends CodeVisitorSupport {
+    MethodNode method
+    boolean hasRecursiveCalls = false
+
+    public void visitMethodCallExpression(MethodCallExpression call) {
+        if (isRecursive(call)) {
+            hasRecursiveCalls = true
+        } else {
+            super.visitMethodCallExpression(call)
+        }
+    }
+
+    public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
+        if (isRecursive(call)) {
+            hasRecursiveCalls = true
+        } else {
+            super.visitStaticMethodCallExpression(call)
+        }
+    }
+
+    private boolean isRecursive(call) {
+        new org.codehaus.groovy.transform.tailrec.RecursivenessTester().isRecursive(method: method, call: call)
+    }
+
+    synchronized boolean test(MethodNode method) {
+        hasRecursiveCalls = false
+        this.method = method
+        this.method.code.visit(this)
+        hasRecursiveCalls
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.groovy
new file mode 100644
index 0000000..0fe2baa
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/InWhileLoopWrapper.groovy
@@ -0,0 +1,81 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.VariableScope
+import org.codehaus.groovy.ast.expr.BooleanExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.CatchStatement
+import org.codehaus.groovy.ast.stmt.ContinueStatement
+import org.codehaus.groovy.ast.stmt.EmptyStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.ast.stmt.TryCatchStatement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+
+/**
+ * Wrap the body of a method in a while loop, nested in a try-catch.
+ * This is the first step in making a tail recursive method iterative.
+ *
+ * There are two ways to invoke the next iteration step:
+ * 1. "continue _RECURE_HERE_" is used by recursive calls outside of closures
+ * 2. "throw LOOP_EXCEPTION" is used by recursive calls within closures b/c you cannot invoke "continue" from there
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class InWhileLoopWrapper {
+	
+	static final String LOOP_LABEL = '_RECUR_HERE_'
+    static final GotoRecurHereException  LOOP_EXCEPTION = new GotoRecurHereException()
+
+	void wrap(MethodNode method) {
+		BlockStatement oldBody = method.code as BlockStatement
+        TryCatchStatement tryCatchStatement = new TryCatchStatement(
+                oldBody,
+                new EmptyStatement()
+        )
+        tryCatchStatement.addCatch(new CatchStatement(
+                new Parameter(ClassHelper.make(GotoRecurHereException), 'ignore'),
+                new ContinueStatement(InWhileLoopWrapper.LOOP_LABEL)
+        ))
+
+        WhileStatement whileLoop = new WhileStatement(
+                new BooleanExpression(new ConstantExpression(true)),
+                new BlockStatement([tryCatchStatement] as List<Statement>, new VariableScope(method.variableScope))
+        )
+        List<Statement> whileLoopStatements = ((BlockStatement) whileLoop.loopBlock).statements
+        if (whileLoopStatements.size() > 0)
+            whileLoopStatements[0].statementLabel = LOOP_LABEL
+		BlockStatement newBody = new BlockStatement([] as List<Statement>, new VariableScope(method.variableScope))
+		newBody.addStatement(whileLoop)
+		method.code = newBody
+	}
+}
+
+/**
+ * Exception will be thrown by recursive calls in closures and caught in while loop to continue to LOOP_LABEL
+ */
+class GotoRecurHereException extends Throwable {
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/RecursivenessTester.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/RecursivenessTester.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/RecursivenessTester.groovy
new file mode 100644
index 0000000..7c9545a
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/RecursivenessTester.groovy
@@ -0,0 +1,100 @@
+/*
+ *  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.transform.tailrec
+
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+
+/**
+ *
+ * Test if a method call is recursive if called within a given method node.
+ * Handles static calls as well.
+ * 
+ * Currently known simplifications:
+ * - Does not check for method overloading or overridden methods.
+ * - Does not check for matching return types; even void and any object type are considered to be compatible.
+ * - Argument type matching could be more specific in case of static compilation.
+ * - Method names via a GString are never considered to be recursive
+ * 
+ * @author Johannes Link
+ */
+class RecursivenessTester {
+	public boolean isRecursive(params) {
+		assert params.method.class == MethodNode
+		assert params.call.class == MethodCallExpression || StaticMethodCallExpression
+
+		isRecursive(params.method, params.call)
+	}
+
+	public boolean isRecursive(MethodNode method, MethodCallExpression call) {
+		if (!isCallToThis(call))
+			return false
+        // Could be a GStringExpression
+        if (! (call.method instanceof ConstantExpression))
+            return false
+		if (call.method.value != method.name)
+			return false
+		methodParamsMatchCallArgs(method, call)
+	}
+
+    public boolean isRecursive(MethodNode method, StaticMethodCallExpression call) {
+        if (!method.isStatic())
+            return false
+        if (method.declaringClass != call.ownerType)
+            return false
+        if (call.method != method.name)
+            return false
+        methodParamsMatchCallArgs(method, call)
+    }
+
+	private boolean isCallToThis(MethodCallExpression call) {
+		if (call.objectExpression == null)
+			return call.isImplicitThis()
+        if (! (call.objectExpression instanceof VariableExpression)) {
+            return false
+        }
+		return call.objectExpression.isThisExpression()
+	}
+	
+	private boolean methodParamsMatchCallArgs(method, call) {
+        if (method.parameters.size() != call.arguments.expressions.size())
+            return false
+        def classNodePairs = [method.parameters*.type, call.arguments*.type].transpose()
+        return classNodePairs.every { ClassNode paramType, ClassNode argType  ->
+            return areTypesCallCompatible(argType, paramType)
+        }
+	}
+
+    /**
+     * Parameter type and calling argument type can both be derived from the other since typing information is
+     * optional in Groovy.
+     * Since int is not derived from Integer (nor the other way around) we compare the boxed types
+     */
+    private areTypesCallCompatible(ClassNode argType, ClassNode paramType) {
+        ClassNode boxedArg = ClassHelper.getWrapper(argType)
+        ClassNode boxedParam = ClassHelper.getWrapper(paramType)
+        return boxedArg.isDerivedFrom(boxedParam) || boxedParam.isDerivedFrom(boxedArg)
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnAdderForClosures.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnAdderForClosures.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnAdderForClosures.groovy
new file mode 100644
index 0000000..64ebce7
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnAdderForClosures.groovy
@@ -0,0 +1,48 @@
+/*
+ *  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.transform.tailrec
+
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.classgen.ReturnAdder
+
+/**
+ * Adds explicit return statements to implicit return points in a closure. This is necessary since
+ * tail-recursion is detected by having the recursive call within the return statement.
+ *
+ * @author Johannes Link
+ */
+class ReturnAdderForClosures extends CodeVisitorSupport {
+
+    synchronized void visitMethod(MethodNode method) {
+        method.code.visit(this)
+    }
+
+    public void visitClosureExpression(ClosureExpression expression) {
+        //Create a dummy method with the closure's code as the method's code. Then user ReturnAdder, which only works for methods.
+        MethodNode node = new MethodNode("dummy", 0, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, expression.code);
+        new ReturnAdder().visitMethod(node);
+        super.visitClosureExpression(expression)
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.groovy
new file mode 100644
index 0000000..d489ff0
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/ReturnStatementToIterationConverter.groovy
@@ -0,0 +1,148 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.expr.BinaryExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.TupleExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
+
+/**
+ * Translates all return statements into an invocation of the next iteration. This can be either
+ * - "continue LOOP_LABEL": Outside closures
+ * - "throw LOOP_EXCEPTION": Inside closures
+ *
+ * Moreover, before adding the recur statement the iteration parameters (originally the method args)
+ * are set to their new value. To prevent variable aliasing parameters will be copied into temp vars
+ * before they are changes so that their current iteration value can be used when setting other params.
+ *
+ * There's probably place for optimizing the amount of variable copying being done, e.g.
+ * parameters that are only handed through must not be copied at all.
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class ReturnStatementToIterationConverter {
+
+    Statement recurStatement = AstHelper.recurStatement()
+
+    Statement convert(ReturnStatement statement, Map<Integer, Map> positionMapping) {
+        Expression recursiveCall = statement.expression
+        if (!isAMethodCalls(recursiveCall))
+            return statement
+
+        Map<String, Map> tempMapping = [:]
+        Map tempDeclarations = [:]
+        List<ExpressionStatement> argAssignments = []
+
+        BlockStatement result = new BlockStatement()
+        result.statementLabel = statement.statementLabel
+
+        /* Create temp declarations for all method arguments.
+         * Add the declarations and var mapping to tempMapping and tempDeclarations for further reference.
+         */
+        getArguments(recursiveCall).eachWithIndex { Expression expression, int index ->
+            ExpressionStatement tempDeclaration = createTempDeclaration(index, positionMapping, tempMapping, tempDeclarations)
+            result.addStatement(tempDeclaration)
+        }
+
+        /*
+         * Assign the iteration variables their new value before recuring
+         */
+        getArguments(recursiveCall).eachWithIndex { Expression expression, int index ->
+            ExpressionStatement argAssignment = createAssignmentToIterationVariable(expression, index, positionMapping)
+            argAssignments.add(argAssignment)
+            result.addStatement(argAssignment)
+        }
+
+        Set<String> unusedTemps = replaceAllArgUsages(argAssignments, tempMapping)
+        for (String temp : unusedTemps) {
+            result.statements.remove(tempDeclarations[temp])
+        }
+        result.addStatement(recurStatement)
+
+        return result
+    }
+
+    private ExpressionStatement createAssignmentToIterationVariable(Expression expression, int index, Map<Integer, Map> positionMapping) {
+        String argName = positionMapping[index]['name']
+        ClassNode argAndTempType = positionMapping[index]['type'] as ClassNode
+        ExpressionStatement argAssignment = (ExpressionStatement) assignS(varX(argName, argAndTempType), expression)
+        argAssignment
+    }
+
+    private ExpressionStatement createTempDeclaration(int index,  Map<Integer, Map> positionMapping, Map<String, Map> tempMapping, Map tempDeclarations) {
+        String argName = positionMapping[index]['name']
+        String tempName = "_${argName}_"
+        ClassNode argAndTempType = positionMapping[index]['type'] as ClassNode
+        ExpressionStatement tempDeclaration = AstHelper.createVariableAlias(tempName, argAndTempType, argName)
+        tempMapping[argName] = [name: tempName, type: argAndTempType]
+        tempDeclarations[tempName] = tempDeclaration
+        return tempDeclaration
+    }
+
+    private List<Expression> getArguments(Expression recursiveCall) {
+        if (recursiveCall instanceof MethodCallExpression)
+            return ((TupleExpression) ((MethodCallExpression) recursiveCall).arguments).expressions
+        if (recursiveCall instanceof StaticMethodCallExpression)
+            return ((TupleExpression) ((StaticMethodCallExpression) recursiveCall).arguments).expressions
+    }
+
+    private boolean isAMethodCalls(Expression expression) {
+        expression.class in [MethodCallExpression, StaticMethodCallExpression]
+    }
+
+    private Set<String> replaceAllArgUsages(List<ExpressionStatement> iterationVariablesAssignmentNodes, Map<String, Map> tempMapping) {
+        Set<String> unusedTempNames = tempMapping.values().collect {Map nameAndType -> (String) nameAndType['name']} as Set<String>
+        VariableReplacedListener tracker = new UsedVariableTracker()
+        for (ExpressionStatement statement : iterationVariablesAssignmentNodes) {
+            replaceArgUsageByTempUsage((BinaryExpression) statement.expression, tempMapping, tracker)
+        }
+        unusedTempNames = unusedTempNames - tracker.usedVariableNames
+        return unusedTempNames
+    }
+
+    private void replaceArgUsageByTempUsage(BinaryExpression binary, Map tempMapping, UsedVariableTracker tracker) {
+        VariableAccessReplacer replacer = new VariableAccessReplacer(nameAndTypeMapping: tempMapping, listener: tracker)
+        // Replacement must only happen in binary.rightExpression. It's a hack in VariableExpressionReplacer which takes care of that.
+        replacer.replaceIn(binary)
+    }
+}
+
+@CompileStatic
+class UsedVariableTracker implements org.codehaus.groovy.transform.tailrec.VariableReplacedListener {
+
+    final Set<String> usedVariableNames = [] as Set
+
+    @Override
+    void variableReplaced(VariableExpression oldVar, VariableExpression newVar) {
+        usedVariableNames.add(newVar.name)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/org/codehaus/groovy/transform/tailrec/StatementReplacer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/StatementReplacer.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/StatementReplacer.groovy
new file mode 100644
index 0000000..3a9dab3
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/StatementReplacer.groovy
@@ -0,0 +1,109 @@
+/*
+ *  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.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.DoWhileStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+
+/**
+ * Tool for replacing Statement objects in an AST by other Statement instances.
+ *
+ * Within @TailRecursive it is used to swap ReturnStatements with looping back to RECUR label
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class StatementReplacer extends CodeVisitorSupport {
+
+    Closure<Boolean> when = { Statement node -> false }
+    Closure<Statement> replaceWith = { Statement statement -> statement }
+    int closureLevel = 0
+
+    void replaceIn(ASTNode root) {
+        root.visit(this)
+    }
+
+    public void visitClosureExpression(ClosureExpression expression) {
+        closureLevel++
+        try {
+            super.visitClosureExpression(expression)
+        } finally {
+            closureLevel--
+        }
+    }
+
+    public void visitBlockStatement(BlockStatement block) {
+        List<Statement> copyOfStatements = new ArrayList<Statement>(block.statements)
+        copyOfStatements.eachWithIndex { Statement statement, int index ->
+            replaceIfNecessary(statement) { Statement node -> block.statements[index] = node }
+        }
+        super.visitBlockStatement(block);
+    }
+
+    public void visitIfElse(IfStatement ifElse) {
+        replaceIfNecessary(ifElse.ifBlock) { Statement s -> ifElse.ifBlock = s }
+        replaceIfNecessary(ifElse.elseBlock) { Statement s -> ifElse.elseBlock = s }
+        super.visitIfElse(ifElse);
+    }
+
+    public void visitForLoop(ForStatement forLoop) {
+        replaceIfNecessary(forLoop.loopBlock) { Statement s -> forLoop.loopBlock = s }
+        super.visitForLoop(forLoop);
+    }
+
+    public void visitWhileLoop(WhileStatement loop) {
+        replaceIfNecessary(loop.loopBlock) { Statement s -> loop.loopBlock = s }
+        super.visitWhileLoop(loop);
+    }
+
+    public void visitDoWhileLoop(DoWhileStatement loop) {
+        replaceIfNecessary(loop.loopBlock) { Statement s -> loop.loopBlock = s }
+        super.visitDoWhileLoop(loop);
+    }
+
+
+    private void replaceIfNecessary(Statement nodeToCheck, Closure replacementCode) {
+        if (conditionFulfilled(nodeToCheck)) {
+            ASTNode replacement = replaceWith(nodeToCheck)
+            replacement.setSourcePosition(nodeToCheck);
+            replacement.copyNodeMetaData(nodeToCheck);
+            replacementCode(replacement)
+        }
+    }
+
+    private boolean conditionFulfilled(ASTNode nodeToCheck) {
+        if (when.maximumNumberOfParameters < 2)
+            return when(nodeToCheck)
+        else
+            return when(nodeToCheck, isInClosure())
+    }
+
+    private boolean isInClosure() {
+        closureLevel > 0
+    }
+
+}


[02/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/NodePrinter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/NodePrinter.java b/src/main/groovy/util/NodePrinter.java
deleted file mode 100644
index ca93bc7..0000000
--- a/src/main/groovy/util/NodePrinter.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- *  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 groovy.util;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A helper class for creating nested trees of data
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Christian Stein
- */
-public class NodePrinter {
-
-    protected final IndentPrinter out;
-
-    public NodePrinter() {
-        this(new IndentPrinter(new PrintWriter(new OutputStreamWriter(System.out))));
-    }
-
-    public NodePrinter(PrintWriter out) {
-        this(new IndentPrinter(out));
-    }
-
-    public NodePrinter(IndentPrinter out) {
-        if (out == null) {
-            throw new NullPointerException("IndentPrinter 'out' must not be null!");
-        }
-        this.out = out;
-    }
-
-    public void print(Node node) {
-        out.printIndent();
-        printName(node);
-        Map attributes = node.attributes();
-        boolean hasAttributes = attributes != null && !attributes.isEmpty();
-        if (hasAttributes) {
-            printAttributes(attributes);
-        }
-        Object value = node.value();
-        if (value instanceof List) {
-            if (!hasAttributes) {
-                out.print("()");
-            }
-            printList((List) value);
-        } else {
-            if (value instanceof String) {
-                out.print("('");
-                out.print((String) value);
-                out.println("')");
-            } else {
-                out.println("()");
-            }
-        }
-        out.flush();
-    }
-
-    protected void printName(Node node) {
-        Object name = node.name();
-        if (name != null) {
-            out.print(name.toString());
-        } else {
-            out.print("null");
-        }
-    }
-
-    protected void printList(List list) {
-        if (list.isEmpty()) {
-            out.println("");
-        } else {
-            out.println(" {");
-            out.incrementIndent();
-            for (Object value : list) {
-                if (value instanceof Node) {
-                    print((Node) value);
-                } else {
-                    out.printIndent();
-                    out.println(InvokerHelper.toString(value));
-                }
-            }
-            out.decrementIndent();
-            out.printIndent();
-            out.println("}");
-        }
-    }
-
-
-    protected void printAttributes(Map attributes) {
-        out.print("(");
-        boolean first = true;
-        for (Object o : attributes.entrySet()) {
-            Map.Entry entry = (Map.Entry) o;
-            if (first) {
-                first = false;
-            } else {
-                out.print(", ");
-            }
-            out.print(entry.getKey().toString());
-            out.print(":");
-            if (entry.getValue() instanceof String) {
-                out.print("'" + entry.getValue() + "'");
-            } else {
-                out.print(InvokerHelper.toString(entry.getValue()));
-            }
-        }
-        out.print(")");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ObjectGraphBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ObjectGraphBuilder.java b/src/main/groovy/util/ObjectGraphBuilder.java
deleted file mode 100644
index 7ba0089..0000000
--- a/src/main/groovy/util/ObjectGraphBuilder.java
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.GString;
-import groovy.lang.MetaProperty;
-import groovy.lang.MissingPropertyException;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-/**
- * A builder for creating object graphs.<br>
- * Each node defines the class to be created and the property on its parent (if
- * any) at the same time.
- *
- * @author Scott Vlaminck (http://refactr.com)
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- */
-public class ObjectGraphBuilder extends FactoryBuilderSupport {
-    public static final String NODE_CLASS = "_NODE_CLASS_";
-    public static final String NODE_NAME = "_NODE_NAME_";
-    public static final String OBJECT_ID = "_OBJECT_ID_";
-    public static final String LAZY_REF = "_LAZY_REF_";
-
-    public static final String CLASSNAME_RESOLVER_KEY = "name";
-    public static final String CLASSNAME_RESOLVER_REFLECTION = "reflection";
-    public static final String CLASSNAME_RESOLVER_REFLECTION_ROOT = "root";
-
-    // Regular expression pattern used to identify words ending in 'y' preceded by a consonant
-    private static final Pattern PLURAL_IES_PATTERN = Pattern.compile(".*[^aeiouy]y", Pattern.CASE_INSENSITIVE);
-
-    private ChildPropertySetter childPropertySetter;
-    private ClassNameResolver classNameResolver;
-    private IdentifierResolver identifierResolver;
-    private NewInstanceResolver newInstanceResolver;
-    private final ObjectFactory objectFactory = new ObjectFactory();
-    private final ObjectBeanFactory objectBeanFactory = new ObjectBeanFactory();
-    private final ObjectRefFactory objectRefFactory = new ObjectRefFactory();
-    private ReferenceResolver referenceResolver;
-    private RelationNameResolver relationNameResolver;
-    private final Map<String, Class> resolvedClasses = new HashMap<String, Class>();
-    private ClassLoader classLoader;
-    private boolean lazyReferencesAllowed = true;
-    private final List<NodeReference> lazyReferences = new ArrayList<NodeReference>();
-    private String beanFactoryName = "bean";
-
-    public ObjectGraphBuilder() {
-        classNameResolver = new DefaultClassNameResolver();
-        newInstanceResolver = new DefaultNewInstanceResolver();
-        relationNameResolver = new DefaultRelationNameResolver();
-        childPropertySetter = new DefaultChildPropertySetter();
-        identifierResolver = new DefaultIdentifierResolver();
-        referenceResolver = new DefaultReferenceResolver();
-
-        addPostNodeCompletionDelegate(new Closure(this, this) {
-            public void doCall(ObjectGraphBuilder builder, Object parent, Object node) {
-                if (parent == null) {
-                    builder.resolveLazyReferences();
-                    builder.dispose();
-                }
-            }
-        });
-    }
-
-    /**
-     * Returns the current name of the 'bean' node.
-     */
-    public String getBeanFactoryName() {
-        return beanFactoryName; 
-    }
-
-    /**
-     * Returns the current ChildPropertySetter.
-     */
-    public ChildPropertySetter getChildPropertySetter() {
-        return childPropertySetter;
-    }
-
-    /**
-     * Returns the classLoader used to load a node's class.
-     */
-    public ClassLoader getClassLoader() {
-        return classLoader;
-    }
-
-    /**
-     * Returns the current ClassNameResolver.
-     */
-    public ClassNameResolver getClassNameResolver() {
-        return classNameResolver;
-    }
-
-    /**
-     * Returns the current NewInstanceResolver.
-     */
-    public NewInstanceResolver getNewInstanceResolver() {
-        return newInstanceResolver;
-    }
-
-    /**
-     * Returns the current RelationNameResolver.
-     */
-    public RelationNameResolver getRelationNameResolver() {
-        return relationNameResolver;
-    }
-
-    /**
-     * Returns true if references can be resolved lazily
-     */
-    public boolean isLazyReferencesAllowed() {
-        return lazyReferencesAllowed;
-    }
-
-    /**
-     * Sets the name for the 'bean' node.
-     */
-    public void setBeanFactoryName(String beanFactoryName) {
-        this.beanFactoryName = beanFactoryName;
-    }
-
-    /**
-     * Sets the current ChildPropertySetter.<br>
-     * It will assign DefaultChildPropertySetter if null.<br>
-     * It accepts a ChildPropertySetter instance or a Closure.
-     */
-    public void setChildPropertySetter(final Object childPropertySetter) {
-        if (childPropertySetter instanceof ChildPropertySetter) {
-            this.childPropertySetter = (ChildPropertySetter) childPropertySetter;
-        } else if (childPropertySetter instanceof Closure) {
-            final ObjectGraphBuilder self = this;
-            this.childPropertySetter = new ChildPropertySetter() {
-                public void setChild(Object parent, Object child, String parentName,
-                                     String propertyName) {
-                    Closure cls = (Closure) childPropertySetter;
-                    cls.setDelegate(self);
-                    cls.call(new Object[]{parent, child, parentName, propertyName});
-                }
-            };
-        } else {
-            this.childPropertySetter = new DefaultChildPropertySetter();
-        }
-    }
-
-    /**
-     * Sets the classLoader used to load a node's class.
-     */
-    public void setClassLoader(ClassLoader classLoader) {
-        this.classLoader = classLoader;
-    }
-
-    /**
-     * Sets the current ClassNameResolver.<br>
-     * It will assign DefaultClassNameResolver if null.<br>
-     * It accepts a ClassNameResolver instance, a String, a Closure or a Map.
-     */
-    public void setClassNameResolver(final Object classNameResolver) {
-        if (classNameResolver instanceof ClassNameResolver) {
-            this.classNameResolver = (ClassNameResolver) classNameResolver;
-        } else if (classNameResolver instanceof String) {
-            this.classNameResolver = new ClassNameResolver() {
-                public String resolveClassname(String classname) {
-                    return makeClassName((String) classNameResolver, classname);
-                }
-            };
-        } else if (classNameResolver instanceof Closure) {
-            final ObjectGraphBuilder self = this;
-            this.classNameResolver = new ClassNameResolver() {
-                public String resolveClassname(String classname) {
-                    Closure cls = (Closure) classNameResolver;
-                    cls.setDelegate(self);
-                    return (String) cls.call(new Object[]{classname});
-                }
-            };
-        } else if (classNameResolver instanceof Map) {
-            Map classNameResolverOptions = (Map) classNameResolver;
-
-            String resolverName = (String) classNameResolverOptions.get(CLASSNAME_RESOLVER_KEY);
-
-            if (resolverName == null) {
-                throw new RuntimeException("key '" + CLASSNAME_RESOLVER_KEY + "' not defined");
-            }
-
-            if (CLASSNAME_RESOLVER_REFLECTION.equals(resolverName)) {
-                String root = (String) classNameResolverOptions.get(CLASSNAME_RESOLVER_REFLECTION_ROOT);
-
-                if (root == null) {
-                    throw new RuntimeException("key '" + CLASSNAME_RESOLVER_REFLECTION_ROOT + "' not defined");
-                }
-
-                this.classNameResolver = new ReflectionClassNameResolver(root);
-            } else {
-                throw new RuntimeException("unknown class name resolver " + resolverName);
-            }
-        } else {
-            this.classNameResolver = new DefaultClassNameResolver();
-        }
-    }
-
-    /**
-     * Sets the current IdentifierResolver.<br>
-     * It will assign DefaultIdentifierResolver if null.<br>
-     * It accepts a IdentifierResolver instance, a String or a Closure.
-     */
-    public void setIdentifierResolver(final Object identifierResolver) {
-        if (identifierResolver instanceof IdentifierResolver) {
-            this.identifierResolver = (IdentifierResolver) identifierResolver;
-        } else if (identifierResolver instanceof String) {
-            this.identifierResolver = new IdentifierResolver() {
-                public String getIdentifierFor(String nodeName) {
-                    return (String) identifierResolver;
-                }
-            };
-        } else if (identifierResolver instanceof Closure) {
-            final ObjectGraphBuilder self = this;
-            this.identifierResolver = new IdentifierResolver() {
-                public String getIdentifierFor(String nodeName) {
-                    Closure cls = (Closure) identifierResolver;
-                    cls.setDelegate(self);
-                    return (String) cls.call(new Object[]{nodeName});
-                }
-            };
-        } else {
-            this.identifierResolver = new DefaultIdentifierResolver();
-        }
-    }
-
-    /**
-     * Sets whether references can be resolved lazily or not.
-     */
-    public void setLazyReferencesAllowed(boolean lazyReferencesAllowed) {
-        this.lazyReferencesAllowed = lazyReferencesAllowed;
-    }
-
-    /**
-     * Sets the current NewInstanceResolver.<br>
-     * It will assign DefaultNewInstanceResolver if null.<br>
-     * It accepts a NewInstanceResolver instance or a Closure.
-     */
-    public void setNewInstanceResolver(final Object newInstanceResolver) {
-        if (newInstanceResolver instanceof NewInstanceResolver) {
-            this.newInstanceResolver = (NewInstanceResolver) newInstanceResolver;
-        } else if (newInstanceResolver instanceof Closure) {
-            final ObjectGraphBuilder self = this;
-            this.newInstanceResolver = new NewInstanceResolver() {
-                public Object newInstance(Class klass, Map attributes)
-                        throws InstantiationException, IllegalAccessException {
-                    Closure cls = (Closure) newInstanceResolver;
-                    cls.setDelegate(self);
-                    return cls.call(new Object[]{klass, attributes});
-                }
-            };
-        } else {
-            this.newInstanceResolver = new DefaultNewInstanceResolver();
-        }
-    }
-
-    /**
-     * Sets the current ReferenceResolver.<br>
-     * It will assign DefaultReferenceResolver if null.<br>
-     * It accepts a ReferenceResolver instance, a String or a Closure.
-     */
-    public void setReferenceResolver(final Object referenceResolver) {
-        if (referenceResolver instanceof ReferenceResolver) {
-            this.referenceResolver = (ReferenceResolver) referenceResolver;
-        } else if (referenceResolver instanceof String) {
-            this.referenceResolver = new ReferenceResolver() {
-                public String getReferenceFor(String nodeName) {
-                    return (String) referenceResolver;
-                }
-            };
-        } else if (referenceResolver instanceof Closure) {
-            final ObjectGraphBuilder self = this;
-            this.referenceResolver = new ReferenceResolver() {
-                public String getReferenceFor(String nodeName) {
-                    Closure cls = (Closure) referenceResolver;
-                    cls.setDelegate(self);
-                    return (String) cls.call(new Object[]{nodeName});
-                }
-            };
-        } else {
-            this.referenceResolver = new DefaultReferenceResolver();
-        }
-    }
-
-    /**
-     * Sets the current RelationNameResolver.<br>
-     * It will assign DefaultRelationNameResolver if null.
-     */
-    public void setRelationNameResolver(RelationNameResolver relationNameResolver) {
-        this.relationNameResolver = relationNameResolver != null ? relationNameResolver
-                : new DefaultRelationNameResolver();
-    }
-
-    protected void postInstantiate(Object name, Map attributes, Object node) {
-        super.postInstantiate(name, attributes, node);
-        Map context = getContext();
-        String objectId = (String) context.get(OBJECT_ID);
-        if (objectId != null && node != null) {
-            setVariable(objectId, node);
-        }
-    }
-
-    protected void preInstantiate(Object name, Map attributes, Object value) {
-        super.preInstantiate(name, attributes, value);
-        Map context = getContext();
-        context.put(OBJECT_ID,
-                attributes.remove(identifierResolver.getIdentifierFor((String) name)));
-    }
-
-    protected Factory resolveFactory(Object name, Map attributes, Object value) {
-        // let custom factories be resolved first
-        Factory factory = super.resolveFactory(name, attributes, value);
-        if (factory != null) {
-            return factory;
-        }
-        if (attributes.get(referenceResolver.getReferenceFor((String) name)) != null) {
-            return objectRefFactory;
-        }
-        if (beanFactoryName != null && beanFactoryName.equals((String) name)) {
-            return objectBeanFactory;
-        }
-        return objectFactory;
-    }
-
-    /**
-     * Strategy for setting a child node on its parent.<br>
-     * Useful for handling Lists/Arrays vs normal properties.
-     */
-    public interface ChildPropertySetter {
-        /**
-         * @param parent       the parent's node value
-         * @param child        the child's node value
-         * @param parentName   the name of the parent node
-         * @param propertyName the resolved relation name of the child
-         */
-        void setChild(Object parent, Object child, String parentName, String propertyName);
-    }
-
-    /**
-     * Strategy for resolving a classname.
-     */
-    public interface ClassNameResolver {
-        /**
-         * @param classname the node name as written on the building code
-         */
-        String resolveClassname(String classname);
-    }
-
-    /**
-     * Default impl that calls parent.propertyName = child<br>
-     * If parent.propertyName is a Collection it will try to add child to the
-     * collection.
-     */
-    public static class DefaultChildPropertySetter implements ChildPropertySetter {
-        public void setChild(Object parent, Object child, String parentName, String propertyName) {
-            try {
-                Object property = InvokerHelper.getProperty(parent, propertyName);
-                if (property != null && Collection.class.isAssignableFrom(property.getClass())) {
-                    ((Collection) property).add(child);
-                } else {
-                    InvokerHelper.setProperty(parent, propertyName, child);
-                }
-            } catch (MissingPropertyException mpe) {
-                // ignore
-            }
-        }
-    }
-
-    /**
-     * Default impl that capitalizes the classname.
-     */
-    public static class DefaultClassNameResolver implements ClassNameResolver {
-        public String resolveClassname(String classname) {
-            if (classname.length() == 1) {
-                return classname.toUpperCase();
-            }
-            return classname.substring(0, 1)
-                    .toUpperCase() + classname.substring(1);
-        }
-    }
-
-    /**
-     * Build objects using reflection to resolve class names.
-     */
-    public class ReflectionClassNameResolver implements ClassNameResolver {
-        private final String root;
-
-        /**
-         * @param root package where the graph root class is located
-         */
-        public ReflectionClassNameResolver(String root) {
-            this.root = root;
-        }
-
-        public String resolveClassname(String classname) {
-            Object currentNode = getContext().get(CURRENT_NODE);
-
-            if (currentNode == null) {
-                return makeClassName(root, classname);
-            } else {
-                try {
-                    Class klass = currentNode.getClass().getDeclaredField(classname).getType();
-
-                    if (Collection.class.isAssignableFrom(klass)) {
-                        Type type = currentNode.getClass().getDeclaredField(classname).getGenericType();
-                        if (type instanceof ParameterizedType) {
-                            ParameterizedType ptype = (ParameterizedType) type;
-                            Type[] actualTypeArguments = ptype.getActualTypeArguments();
-                            if (actualTypeArguments.length != 1) {
-                                throw new RuntimeException("can't determine class name for collection field " + classname + " with multiple generics");
-                            }
-
-                            Type typeArgument = actualTypeArguments[0];
-                            if (typeArgument instanceof Class) {
-                                klass = (Class) actualTypeArguments[0];
-                            } else {
-                                throw new RuntimeException("can't instantiate collection field " + classname + " elements as they aren't a class");
-                            }
-                        } else {
-                            throw new RuntimeException("collection field " + classname + " must be genericised");
-                        }
-                    }
-
-                    return klass.getName();
-                } catch (NoSuchFieldException e) {
-                    throw new RuntimeException("can't find field " + classname + " for node class " + currentNode.getClass().getName(), e);
-                }
-            }
-        }
-    }
-
-    /**
-     * Default impl, always returns 'id'
-     */
-    public static class DefaultIdentifierResolver implements IdentifierResolver {
-        public String getIdentifierFor(String nodeName) {
-            return "id";
-        }
-    }
-
-    /**
-     * Default impl that calls Class.newInstance()
-     */
-    public static class DefaultNewInstanceResolver implements NewInstanceResolver {
-        public Object newInstance(Class klass, Map attributes) throws InstantiationException,
-                IllegalAccessException {
-            return klass.newInstance();
-        }
-    }
-
-    /**
-     * Default impl, always returns 'refId'
-     */
-    public static class DefaultReferenceResolver implements ReferenceResolver {
-        public String getReferenceFor(String nodeName) {
-            return "refId";
-        }
-    }
-
-    /**
-     * Default impl that returns parentName and childName accordingly.
-     */
-    public static class DefaultRelationNameResolver implements RelationNameResolver {
-        /**
-         * Handles the common English regular plurals with the following rules.
-         * <ul>
-         * <li>If childName ends in {consonant}y, replace 'y' with "ies". For example, allergy to allergies.</li>
-         * <li>Otherwise, append 's'. For example, monkey to monkeys; employee to employees.</li>
-         * </ul>
-         * If the property does not exist then it will return childName unchanged.
-         *
-         * @see <a href="http://en.wikipedia.org/wiki/English_plural">English_plural</a>
-         */
-        public String resolveChildRelationName(String parentName, Object parent, String childName,
-                                               Object child) {
-            boolean matchesIESRule = PLURAL_IES_PATTERN.matcher(childName).matches();
-            String childNamePlural = matchesIESRule ? childName.substring(0, childName.length() - 1) + "ies" : childName + "s";
-
-            MetaProperty metaProperty = InvokerHelper.getMetaClass(parent)
-                    .hasProperty(parent, childNamePlural);
-
-            return metaProperty != null ? childNamePlural : childName;
-        }
-
-        /**
-         * Follow the most conventional pattern, returns the parentName
-         * unchanged.
-         */
-        public String resolveParentRelationName(String parentName, Object parent,
-                                                String childName, Object child) {
-            return parentName;
-        }
-    }
-
-    /**
-     * Strategy for picking the correct synthetic identifier.
-     */
-    public interface IdentifierResolver {
-        /**
-         * Returns the name of the property that will identify the node.<br>
-         *
-         * @param nodeName the name of the node
-         */
-        String getIdentifierFor(String nodeName);
-    }
-
-    /**
-     * Strategy for creating new instances of a class.<br>
-     * Useful for plug-in calls to non-default constructors.
-     */
-    public interface NewInstanceResolver {
-        /**
-         * Create a new instance of Class klass.
-         *
-         * @param klass      the resolved class name
-         * @param attributes the attribute Map available for the node
-         */
-        Object newInstance(Class klass, Map attributes) throws InstantiationException,
-                IllegalAccessException;
-    }
-
-    /**
-     * Strategy for picking the correct synthetic reference identifier.
-     */
-    public interface ReferenceResolver {
-        /**
-         * Returns the name of the property that references another node.<br>
-         *
-         * @param nodeName the name of the node
-         */
-        String getReferenceFor(String nodeName);
-    }
-
-    /**
-     * Strategy for resolving a relationship property name.
-     */
-    public interface RelationNameResolver {
-        /**
-         * Returns the mapping name of child -&gt; parent
-         *
-         * @param parentName the name of the parent node
-         * @param parent     the parent node
-         * @param childName  the name of the child node
-         * @param child      the child node
-         */
-        String resolveChildRelationName(String parentName, Object parent, String childName,
-                                        Object child);
-
-        /**
-         * Returns the mapping name of parent -&gt; child
-         *
-         * @param parentName the name of the parent node
-         * @param parent     the parent node
-         * @param childName  the name of the child node
-         * @param child      the child node
-         */
-        String resolveParentRelationName(String parentName, Object parent, String childName,
-                                         Object child);
-    }
-
-    private void resolveLazyReferences() {
-        if (!lazyReferencesAllowed) return;
-        for (NodeReference ref : lazyReferences) {
-            if (ref.parent == null) continue;
-
-            Object child = null;
-            try {
-                child = getProperty(ref.refId);
-            } catch (MissingPropertyException mpe) {
-                // ignore
-            }
-            if (child == null) {
-                throw new IllegalArgumentException("There is no valid node for reference "
-                        + ref.parentName + "." + ref.childName + "=" + ref.refId);
-            }
-
-            // set child first
-            childPropertySetter.setChild(ref.parent, child, ref.parentName,
-                    relationNameResolver.resolveChildRelationName(ref.parentName,
-                            ref.parent, ref.childName, child));
-
-            // set parent afterwards
-            String propertyName = relationNameResolver.resolveParentRelationName(ref.parentName,
-                    ref.parent, ref.childName, child);
-            MetaProperty metaProperty = InvokerHelper.getMetaClass(child)
-                    .hasProperty(child, propertyName);
-            if (metaProperty != null) {
-                metaProperty.setProperty(child, ref.parent);
-            }
-        }
-    }
-
-    private static String makeClassName(String root, String name) {
-        return root + "." + name.substring(0, 1).toUpperCase() + name.substring(1);
-    }
-
-    private static class ObjectFactory extends AbstractFactory {
-        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
-                                  Map properties) throws InstantiationException, IllegalAccessException {
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            String classname = ogbuilder.classNameResolver.resolveClassname((String) name);
-            Class klass = resolveClass(builder, classname, name, value, properties);
-            Map context = builder.getContext();
-            context.put(ObjectGraphBuilder.NODE_NAME, name);
-            context.put(ObjectGraphBuilder.NODE_CLASS, klass);
-            return resolveInstance(builder, name, value, klass, properties);
-        }
-
-        protected Class resolveClass(FactoryBuilderSupport builder, String classname, Object name, Object value,
-                                  Map properties) {
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            Class klass = ogbuilder.resolvedClasses.get(classname);
-            if (klass == null) {
-                klass = loadClass(ogbuilder.classLoader, classname);
-                if (klass == null) {
-                    klass = loadClass(ogbuilder.getClass().getClassLoader(), classname);
-                }
-                if (klass == null) {
-                    try {
-                        klass = Class.forName(classname);
-                    } catch (ClassNotFoundException e) {
-                        // ignore
-                    }
-                }
-                if (klass == null) {
-                    klass = loadClass(Thread.currentThread().getContextClassLoader(), classname);
-                }
-                if (klass == null) {
-                    throw new RuntimeException(new ClassNotFoundException(classname));
-                }
-                ogbuilder.resolvedClasses.put(classname, klass);
-            }
-
-            return klass;
-        }
-
-        protected Object resolveInstance(FactoryBuilderSupport builder, Object name, Object value, Class klass,
-                                  Map properties) throws InstantiationException, IllegalAccessException {
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            if (value != null && klass.isAssignableFrom(value.getClass())) {
-                return value;
-            }
-
-            return ogbuilder.newInstanceResolver.newInstance(klass, properties);
-        }
-
-        public void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
-            if (child == null) return;
-
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            if (parent != null) {
-                Map context = ogbuilder.getContext();
-                Map parentContext = ogbuilder.getParentContext();
-
-                String parentName = null;
-                String childName = (String) context.get(NODE_NAME);
-                if (parentContext != null) {
-                    parentName = (String) parentContext.get(NODE_NAME);
-                }
-
-                String propertyName = ogbuilder.relationNameResolver.resolveParentRelationName(
-                        parentName, parent, childName, child);
-                MetaProperty metaProperty = InvokerHelper.getMetaClass(child)
-                        .hasProperty(child, propertyName);
-                if (metaProperty != null) {
-                    metaProperty.setProperty(child, parent);
-                }
-            }
-        }
-
-        public void setParent(FactoryBuilderSupport builder, Object parent, Object child) {
-            if (child == null) return;
-
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            if (parent != null) {
-                Map context = ogbuilder.getContext();
-                Map parentContext = ogbuilder.getParentContext();
-
-                String parentName = null;
-                String childName = (String) context.get(NODE_NAME);
-                if (parentContext != null) {
-                    parentName = (String) parentContext.get(NODE_NAME);
-                }
-
-                ogbuilder.childPropertySetter.setChild(parent, child, parentName,
-                        ogbuilder.relationNameResolver.resolveChildRelationName(parentName,
-                                parent, childName, child));
-            }
-        }
-
-        protected Class loadClass(ClassLoader classLoader, String classname) {
-            if (classLoader == null || classname == null) {
-                return null;
-            }
-            try {
-                return classLoader.loadClass(classname);
-            } catch (ClassNotFoundException e) {
-                return null;
-            }
-        }
-    }
-
-    private static class ObjectBeanFactory extends ObjectFactory {
-        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
-                                  Map properties) throws InstantiationException, IllegalAccessException {
-            if(value == null) return super.newInstance(builder, name, value, properties);
-
-            Object bean = null;
-            Class klass = null;
-            Map context = builder.getContext();
-            if(value instanceof String || value instanceof GString) {
-                /*
-                String classname = value.toString();
-                klass = resolveClass(builder, classname, name, value, properties);
-                bean = resolveInstance(builder, name, value, klass, properties);
-                */
-                throw new IllegalArgumentException("ObjectGraphBuilder."+((ObjectGraphBuilder)builder).getBeanFactoryName()+"() does not accept String nor GString as value.");
-            } else if(value instanceof Class) {
-                klass = (Class) value;
-                bean = resolveInstance(builder, name, value, klass, properties);
-            } else {
-                klass = value.getClass();
-                bean = value;
-            }
-
-            String nodename = klass.getSimpleName();
-            if(nodename.length() > 1) {
-                nodename = nodename.substring(0, 1).toLowerCase() + nodename.substring(1);
-            } else {
-                nodename = nodename.toLowerCase();
-            }
-            context.put(ObjectGraphBuilder.NODE_NAME, nodename);
-            context.put(ObjectGraphBuilder.NODE_CLASS, klass);
-            return bean;
-        }
-    }
-
-    private static class ObjectRefFactory extends ObjectFactory {
-        public boolean isLeaf() {
-            return true;
-        }
-
-        public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
-                                  Map properties) throws InstantiationException, IllegalAccessException {
-            ObjectGraphBuilder ogbuilder = (ObjectGraphBuilder) builder;
-            String refProperty = ogbuilder.referenceResolver.getReferenceFor((String) name);
-            Object refId = properties.remove(refProperty);
-
-            Object object = null;
-            Boolean lazy = Boolean.FALSE;
-            if (refId instanceof String) {
-                try {
-                    object = ogbuilder.getProperty((String) refId);
-                } catch (MissingPropertyException mpe) {
-                    // ignore, will try lazy reference
-                }
-                if (object == null) {
-                    if (ogbuilder.isLazyReferencesAllowed()) {
-                        lazy = Boolean.TRUE;
-                    } else {
-                        throw new IllegalArgumentException("There is no previous node with "
-                                + ogbuilder.identifierResolver.getIdentifierFor((String) name) + "="
-                                + refId);
-                    }
-                }
-            } else {
-                // assume we got a true reference to the object
-                object = refId;
-            }
-
-            if (!properties.isEmpty()) {
-                throw new IllegalArgumentException(
-                        "You can not modify the properties of a referenced object.");
-            }
-
-            Map context = ogbuilder.getContext();
-            context.put(ObjectGraphBuilder.NODE_NAME, name);
-            context.put(ObjectGraphBuilder.LAZY_REF, lazy);
-
-            if (lazy.booleanValue()) {
-                Map parentContext = ogbuilder.getParentContext();
-
-                Object parent = null;
-                String parentName = null;
-                String childName = (String) name;
-                if (parentContext != null) {
-                    parent = context.get(CURRENT_NODE);
-                    parentName = (String) parentContext.get(NODE_NAME);
-                }
-                ogbuilder.lazyReferences.add(new NodeReference(parent,
-                        parentName,
-                        childName,
-                        (String) refId));
-            } else {
-                context.put(ObjectGraphBuilder.NODE_CLASS, object.getClass());
-            }
-
-            return object;
-        }
-
-        public void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
-            Boolean lazy = (Boolean) builder.getContext().get(ObjectGraphBuilder.LAZY_REF);
-            if (!lazy.booleanValue()) super.setChild(builder, parent, child);
-        }
-
-        public void setParent(FactoryBuilderSupport builder, Object parent, Object child) {
-            Boolean lazy = (Boolean) builder.getContext().get(ObjectGraphBuilder.LAZY_REF);
-            if (!lazy.booleanValue()) super.setParent(builder, parent, child);
-        }
-    }
-
-    private static final class NodeReference {
-        private final Object parent;
-        private final String parentName;
-        private final String childName;
-        private final String refId;
-
-        private NodeReference(Object parent, String parentName, String childName, String refId) {
-            this.parent = parent;
-            this.parentName = parentName;
-            this.childName = childName;
-            this.refId = refId;
-        }
-
-        public String toString() {
-            return new StringBuilder().append("[parentName=").append(parentName)
-                    .append(", childName=").append(childName)
-                    .append(", refId=").append(refId)
-                    .append("]").toString();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ObservableList.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ObservableList.java b/src/main/groovy/util/ObservableList.java
deleted file mode 100644
index 31b5745..0000000
--- a/src/main/groovy/util/ObservableList.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-
-/**
- * List decorator that will trigger PropertyChangeEvents when a value changes.<br>
- * An optional Closure may be specified and will work as a filter, if it returns true the property
- * will trigger an event (if the value indeed changed), otherwise it won't. The Closure may receive
- * 1 or 2 parameters, the single one being the value, the other one both the key and value, for
- * example:
- * <pre>
- * // skip all properties whose value is a closure
- * def map = new ObservableList( {!(it instanceof Closure)} )
- *
- * // skip all properties whose name matches a regex
- * def map = new ObservableList( { name, value -&gt; !(name =&tilde; /[A-Z+]/) } )
- * </pre>
- * The current implementation will trigger specialized events in the following scenarios, you need
- * not register a different listener as those events extend from PropertyChangeEvent
- * <ul>
- * <li>ObservableList.ElementAddedEvent - a new element is added to the list</li>
- * <li>ObservableList.ElementRemovedEvent - an element is removed from the list</li>
- * <li>ObservableList.ElementUpdatedEvent - an element changes value (same as regular
- * PropertyChangeEvent)</li>
- * <li>ObservableList.ElementClearedEvent - all elements have been removed from the list</li>
- * <li>ObservableList.MultiElementAddedEvent - triggered by calling list.addAll()</li>
- * <li>ObservableList.MultiElementRemovedEvent - triggered by calling
- * list.removeAll()/list.retainAll()</li>
- * </ul>
- * <p>
- * <strong>Bound properties</strong>
- * <ul>
- * <li><tt>content</tt> - read-only.</li>
- * <li><tt>size</tt> - read-only.</li>
- * </ul>
- *
- * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
- */
-public class ObservableList implements List {
-    private final List delegate;
-    private final PropertyChangeSupport pcs;
-    private final Closure test;
-
-    public static final String SIZE_PROPERTY = "size";
-    public static final String CONTENT_PROPERTY = "content";
-
-    public ObservableList() {
-        this(new ArrayList(), null);
-    }
-
-    public ObservableList(List delegate) {
-        this(delegate, null);
-    }
-
-    public ObservableList(Closure test) {
-        this(new ArrayList(), test);
-    }
-
-    public ObservableList(List delegate, Closure test) {
-        this.delegate = delegate;
-        this.test = test;
-        pcs = new PropertyChangeSupport(this);
-    }
-
-    public List getContent() {
-        return Collections.unmodifiableList(delegate);
-    }
-
-    protected List getDelegateList() {
-        return delegate;
-    }
-
-    protected Closure getTest() {
-        return test;
-    }
-
-    protected void fireElementAddedEvent(int index, Object element) {
-        fireElementEvent(new ElementAddedEvent(this, element, index));
-    }
-
-    protected void fireMultiElementAddedEvent(int index, List values) {
-        fireElementEvent(new MultiElementAddedEvent(this, index, values));
-    }
-
-    protected void fireElementClearedEvent(List values) {
-        fireElementEvent(new ElementClearedEvent(this, values));
-    }
-
-    protected void fireElementRemovedEvent(int index, Object element) {
-        fireElementEvent(new ElementRemovedEvent(this, element, index));
-    }
-
-    protected void fireMultiElementRemovedEvent(List values) {
-        fireElementEvent(new MultiElementRemovedEvent(this, values));
-    }
-
-    protected void fireElementUpdatedEvent(int index, Object oldValue, Object newValue) {
-        fireElementEvent(new ElementUpdatedEvent(this, oldValue, newValue, index));
-    }
-
-    protected void fireElementEvent(ElementEvent event) {
-        pcs.firePropertyChange(event);
-    }
-
-    protected void fireSizeChangedEvent(int oldValue, int newValue) {
-        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
-    }
-
-    public void add(int index, Object element) {
-        int oldSize = size();
-        delegate.add(index, element);
-        fireAddWithTest(element, index, oldSize);
-    }
-
-    public boolean add(Object o) {
-        int oldSize = size();
-        boolean success = delegate.add(o);
-        if (success) {
-            fireAddWithTest(o, oldSize, oldSize);
-        }
-        return success;
-    }
-
-    private void fireAddWithTest(Object element, int index, int oldSize) {
-        if (test != null) {
-            Object result = test.call(element);
-            if (result != null && result instanceof Boolean && (Boolean) result) {
-                fireElementAddedEvent(index, element);
-                fireSizeChangedEvent(oldSize, size());
-            }
-        } else {
-            fireElementAddedEvent(index, element);
-            fireSizeChangedEvent(oldSize, size());
-        }
-    }
-
-    public boolean addAll(Collection c) {
-        return addAll(size(), c);
-    }
-
-    public boolean addAll(int index, Collection c) {
-        int oldSize = size();
-        boolean success = delegate.addAll(index, c);
-
-        if (success && c != null) {
-            List values = new ArrayList();
-            for (Object element : c) {
-                if (test != null) {
-                    Object result = test.call(element);
-                    if (result != null && result instanceof Boolean && (Boolean) result) {
-                        values.add(element);
-                    }
-                } else {
-                    values.add(element);
-                }
-            }
-            if (!values.isEmpty()) {
-                fireMultiElementAddedEvent(index, values);
-                fireSizeChangedEvent(oldSize, size());
-            }
-        }
-
-        return success;
-    }
-
-    public void clear() {
-        int oldSize = size();
-        List values = new ArrayList();
-        values.addAll(delegate);
-        delegate.clear();
-        if (!values.isEmpty()) {
-            fireElementClearedEvent(values);
-        }
-        fireSizeChangedEvent(oldSize, size());
-    }
-
-    public boolean contains(Object o) {
-        return delegate.contains(o);
-    }
-
-    public boolean containsAll(Collection c) {
-        return delegate.containsAll(c);
-    }
-
-    public boolean equals(Object o) {
-        return delegate.equals(o);
-    }
-
-    public Object get(int index) {
-        return delegate.get(index);
-    }
-
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    public int indexOf(Object o) {
-        return delegate.indexOf(o);
-    }
-
-    public boolean isEmpty() {
-        return delegate.isEmpty();
-    }
-
-    public Iterator iterator() {
-        return new ObservableIterator(delegate.iterator());
-    }
-
-    public int lastIndexOf(Object o) {
-        return delegate.lastIndexOf(o);
-    }
-
-    public ListIterator listIterator() {
-        return new ObservableListIterator(delegate.listIterator(), 0);
-    }
-
-    public ListIterator listIterator(int index) {
-        return new ObservableListIterator(delegate.listIterator(index), index);
-    }
-
-    public Object remove(int index) {
-        int oldSize = size();
-        Object element = delegate.remove(index);
-        fireElementRemovedEvent(index, element);
-        fireSizeChangedEvent(oldSize, size());
-        return element;
-    }
-
-    public boolean remove(Object o) {
-        int oldSize = size();
-        int index = delegate.indexOf(o);
-        boolean success = delegate.remove(o);
-        if (success) {
-            fireElementRemovedEvent(index, o);
-            fireSizeChangedEvent(oldSize, size());
-        }
-        return success;
-    }
-
-    public boolean removeAll(Collection c) {
-        if (c == null) {
-            return false;
-        }
-
-        List values = new ArrayList();
-        // GROOVY-7783 use Sets for O(1) performance for contains
-        Set delegateSet = new HashSet<Object>(delegate);
-        if (!(c instanceof Set)) {
-            c = new HashSet<Object>(c);
-        }
-        for (Object element : c) {
-            if (delegateSet.contains(element)) {
-                values.add(element);
-            }
-        }
-
-        int oldSize = size();
-        boolean success = delegate.removeAll(c);
-        if (success && !values.isEmpty()) {
-            fireMultiElementRemovedEvent(values);
-            fireSizeChangedEvent(oldSize, size());
-        }
-
-        return success;
-    }
-
-    public boolean retainAll(Collection c) {
-        if (c == null) {
-            return false;
-        }
-
-        List values = new ArrayList();
-        // GROOVY-7783 use Set for O(1) performance for contains
-        if (!(c instanceof Set)) {
-            c = new HashSet<Object>(c);
-        }
-        for (Object element : delegate) {
-            if (!c.contains(element)) {
-                values.add(element);
-            }
-        }
-
-        int oldSize = size();
-        boolean success = delegate.retainAll(c);
-        if (success && !values.isEmpty()) {
-            fireMultiElementRemovedEvent(values);
-            fireSizeChangedEvent(oldSize, size());
-        }
-
-        return success;
-    }
-
-    public Object set(int index, Object element) {
-        Object oldValue = delegate.set(index, element);
-        if (test != null) {
-            Object result = test.call(element);
-            if (result != null && result instanceof Boolean && ((Boolean) result).booleanValue()) {
-                fireElementUpdatedEvent(index, oldValue, element);
-            }
-        } else {
-            fireElementUpdatedEvent(index, oldValue, element);
-        }
-        return oldValue;
-    }
-
-    public int size() {
-        return delegate.size();
-    }
-
-    public int getSize() {
-        return size();
-    }
-
-    public List subList(int fromIndex, int toIndex) {
-        return delegate.subList(fromIndex, toIndex);
-    }
-
-    public Object[] toArray() {
-        return delegate.toArray();
-    }
-
-    public Object[] toArray(Object[] a) {
-        return delegate.toArray(a);
-    }
-
-    protected class ObservableIterator implements Iterator {
-        private final Iterator iterDelegate;
-        protected int cursor = -1 ;
-
-        public ObservableIterator(Iterator iterDelegate) {
-            this.iterDelegate = iterDelegate;
-        }
-
-        public Iterator getDelegate() {
-            return iterDelegate;
-        }
-
-        public boolean hasNext() {
-            return iterDelegate.hasNext();
-        }
-
-        public Object next() {
-            cursor++;
-            return iterDelegate.next();
-        }
-
-        public void remove() {
-            int oldSize = ObservableList.this.size();
-            Object element = ObservableList.this.get(cursor);
-            iterDelegate.remove();
-            fireElementRemovedEvent(cursor, element);
-            fireSizeChangedEvent(oldSize, size());
-            cursor--;
-        }
-    }
-
-    protected class ObservableListIterator extends ObservableIterator implements ListIterator {
-        public ObservableListIterator(ListIterator iterDelegate, int index) {
-            super(iterDelegate);
-            cursor = index - 1;
-        }
-
-        public ListIterator getListIterator() {
-            return (ListIterator) getDelegate();
-        }
-
-        public void add(Object o) {
-            ObservableList.this.add(o);
-            cursor++;
-        }
-
-        public boolean hasPrevious() {
-            return getListIterator().hasPrevious();
-        }
-
-        public int nextIndex() {
-            return getListIterator().nextIndex();
-        }
-
-        public Object previous() {
-            return getListIterator().previous();
-        }
-
-        public int previousIndex() {
-            return getListIterator().previousIndex();
-        }
-
-        public void set(Object o) {
-            ObservableList.this.set(cursor, o);
-        }
-    }
-
-    // observable interface
-
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(listener);
-    }
-
-    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(propertyName, listener);
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners() {
-        return pcs.getPropertyChangeListeners();
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
-        return pcs.getPropertyChangeListeners(propertyName);
-    }
-
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(listener);
-    }
-
-    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(propertyName, listener);
-    }
-
-    public boolean hasListeners(String propertyName) {
-        return pcs.hasListeners(propertyName);
-    }
-
-    public enum ChangeType {
-        ADDED, UPDATED, REMOVED, CLEARED, MULTI_ADD, MULTI_REMOVE, NONE;
-
-        public static final Object oldValue = new Object();
-        public static final Object newValue = new Object();
-
-        public static ChangeType resolve(int ordinal) {
-            switch (ordinal) {
-                case 0:
-                    return ADDED;
-                case 2:
-                    return REMOVED;
-                case 3:
-                    return CLEARED;
-                case 4:
-                    return MULTI_ADD;
-                case 5:
-                    return MULTI_REMOVE;
-                case 6:
-                    return NONE;
-                case 1:
-                default:
-                    return UPDATED;
-            }
-        }
-    }
-
-    public abstract static class ElementEvent extends PropertyChangeEvent {
-
-        private final ChangeType type;
-        private final int index;
-
-        public ElementEvent(Object source, Object oldValue, Object newValue, int index, ChangeType type) {
-            super(source, ObservableList.CONTENT_PROPERTY, oldValue, newValue);
-            this.type = type;
-            this.index = index;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        public int getType() {
-            return type.ordinal();
-        }
-
-        public ChangeType getChangeType() {
-            return type;
-        }
-
-        public String getTypeAsString() {
-            return type.name().toUpperCase();
-        }
-    }
-
-    public static class ElementAddedEvent extends ElementEvent {
-        public ElementAddedEvent(Object source, Object newValue, int index) {
-            super(source, null, newValue, index, ChangeType.ADDED);
-        }
-    }
-
-    public static class ElementUpdatedEvent extends ElementEvent {
-        public ElementUpdatedEvent(Object source, Object oldValue, Object newValue, int index) {
-            super(source, oldValue, newValue, index, ChangeType.UPDATED);
-        }
-    }
-
-    public static class ElementRemovedEvent extends ElementEvent {
-        public ElementRemovedEvent(Object source, Object value, int index) {
-            super(source, value, null, index, ChangeType.REMOVED);
-        }
-    }
-
-    public static class ElementClearedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public ElementClearedEvent(Object source, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, 0, ChangeType.CLEARED);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-
-    public static class MultiElementAddedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public MultiElementAddedEvent(Object source, int index, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, index, ChangeType.MULTI_ADD);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-
-    public static class MultiElementRemovedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public MultiElementRemovedEvent(Object source, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, 0, ChangeType.MULTI_REMOVE);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ObservableMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ObservableMap.java b/src/main/groovy/util/ObservableMap.java
deleted file mode 100644
index 43dc7a0..0000000
--- a/src/main/groovy/util/ObservableMap.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Map decorator that will trigger PropertyChangeEvents when a value changes.<br>
- * An optional Closure may be specified and will work as a filter, if it returns
- * true the property will trigger an event (if the value indeed changed),
- * otherwise it won't. The Closure may receive 1 or 2 parameters, the single one
- * being the value, the other one both the key and value, for example:
- * <pre>
- * // skip all properties whose value is a closure
- * def map = new ObservableMap( {!(it instanceof Closure)} )
- *
- * // skip all properties whose name matches a regex
- * def map = new ObservableMap( { name, value -&gt; !(name =~ /[A-Z+]/) } )
- * </pre>
- * The current implementation will trigger specialized events in the following scenarios,
- * you need not register a different listener as those events extend from PropertyChangeEvent
- * <ul>
- * <li>ObservableMap.PropertyAddedEvent - a new property is added to the map</li>
- * <li>ObservableMap.PropertyRemovedEvent - a property is removed from the map</li>
- * <li>ObservableMap.PropertyUpdatedEvent - a property changes value (same as regular PropertyChangeEvent)</li>
- * <li>ObservableMap.PropertyClearedEvent - all properties have been removed from the map</li>
- * <li>ObservableMap.MultiPropertyEvent - triggered by calling map.putAll(), contains Added|Updated events</li>
- * </ul>
- * <p>
- * <strong>Bound properties</strong>
- * <ul>
- * <li><tt>content</tt> - read-only.</li>
- * <li><tt>size</tt> - read-only.</li>
- * </ul>
- *
- * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
- */
-public class ObservableMap implements Map {
-    private final Map delegate;
-    private final PropertyChangeSupport pcs;
-    private final Closure test;
-
-    public static final String SIZE_PROPERTY = "size";
-    public static final String CONTENT_PROPERTY = "content";
-    public static final String CLEARED_PROPERTY = "cleared";
-
-    public ObservableMap() {
-        this(new LinkedHashMap(), null);
-    }
-
-    public ObservableMap(Closure test) {
-        this(new LinkedHashMap(), test);
-    }
-
-    public ObservableMap(Map delegate) {
-        this(delegate, null);
-    }
-
-    public ObservableMap(Map delegate, Closure test) {
-        this.delegate = delegate;
-        this.test = test;
-        pcs = new PropertyChangeSupport(this);
-    }
-
-    protected Map getMapDelegate() {
-        return delegate;
-    }
-
-    protected Closure getTest() {
-        return test;
-    }
-
-    public Map getContent() {
-        return Collections.unmodifiableMap(delegate);
-    }
-
-    protected void firePropertyClearedEvent(Map values) {
-        firePropertyEvent(new PropertyClearedEvent(this, values));
-    }
-
-    protected void firePropertyAddedEvent(Object key, Object value) {
-        firePropertyEvent(new PropertyAddedEvent(this, String.valueOf(key), value));
-    }
-
-    protected void firePropertyUpdatedEvent(Object key, Object oldValue, Object newValue) {
-        firePropertyEvent(new PropertyUpdatedEvent(this, String.valueOf(key), oldValue, newValue));
-    }
-
-    protected void fireMultiPropertyEvent(List<PropertyEvent> events) {
-        firePropertyEvent(new MultiPropertyEvent(this, (PropertyEvent[]) events.toArray(new PropertyEvent[events.size()])));
-    }
-
-    protected void fireMultiPropertyEvent(PropertyEvent[] events) {
-        firePropertyEvent(new MultiPropertyEvent(this, events));
-    }
-
-    protected void firePropertyRemovedEvent(Object key, Object value) {
-        firePropertyEvent(new PropertyRemovedEvent(this, String.valueOf(key), value));
-    }
-
-    protected void firePropertyEvent(PropertyEvent event) {
-        pcs.firePropertyChange(event);
-    }
-
-    protected void fireSizeChangedEvent(int oldValue, int newValue) {
-        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
-    }
-
-    // Map interface
-
-    public void clear() {
-        int oldSize = size();
-        Map values = new HashMap();
-        if (!delegate.isEmpty()) {
-            values.putAll(delegate);
-        }
-        delegate.clear();
-        firePropertyClearedEvent(values);
-        fireSizeChangedEvent(oldSize, size());
-    }
-
-    public boolean containsKey(Object key) {
-        return delegate.containsKey(key);
-    }
-
-    public boolean containsValue(Object value) {
-        return delegate.containsValue(value);
-    }
-
-    public Set entrySet() {
-        return delegate.entrySet();
-    }
-
-    public boolean equals(Object o) {
-        return delegate.equals(o);
-    }
-
-    public Object get(Object key) {
-        return delegate.get(key);
-    }
-
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    public boolean isEmpty() {
-        return delegate.isEmpty();
-    }
-
-    public Set keySet() {
-        return delegate.keySet();
-    }
-
-    public Object put(Object key, Object value) {
-        int oldSize = size();
-        Object oldValue = null;
-        boolean newKey = !delegate.containsKey(key);
-        if (test != null) {
-            oldValue = delegate.put(key, value);
-            Object result = null;
-            if (test.getMaximumNumberOfParameters() == 2) {
-                result = test.call(new Object[]{key, value});
-            } else {
-                result = test.call(value);
-            }
-            if (result != null && result instanceof Boolean && (Boolean) result) {
-                if (newKey) {
-                    firePropertyAddedEvent(key, value);
-                    fireSizeChangedEvent(oldSize, size());
-                } else if (oldValue != value) {
-                    firePropertyUpdatedEvent(key, oldValue, value);
-                }
-            }
-        } else {
-            oldValue = delegate.put(key, value);
-            if (newKey) {
-                firePropertyAddedEvent(key, value);
-                fireSizeChangedEvent(oldSize, size());
-            } else if (oldValue != value) {
-                firePropertyUpdatedEvent(key, oldValue, value);
-            }
-        }
-        return oldValue;
-    }
-
-    public void putAll(Map map) {
-        int oldSize = size();
-        if (map != null) {
-            List<PropertyEvent> events = new ArrayList<PropertyEvent>();
-            for (Object o : map.entrySet()) {
-                Entry entry = (Entry) o;
-
-                String key = String.valueOf(entry.getKey());
-                Object newValue = entry.getValue();
-                Object oldValue = null;
-
-                boolean newKey = !delegate.containsKey(key);
-                if (test != null) {
-                    oldValue = delegate.put(key, newValue);
-                    Object result = null;
-                    if (test.getMaximumNumberOfParameters() == 2) {
-                        result = test.call(new Object[]{key, newValue});
-                    } else {
-                        result = test.call(newValue);
-                    }
-                    if (result != null && result instanceof Boolean && (Boolean) result) {
-                        if (newKey) {
-                            events.add(new PropertyAddedEvent(this, key, newValue));
-                        } else if (oldValue != newValue) {
-                            events.add(new PropertyUpdatedEvent(this, key, oldValue, newValue));
-                        }
-                    }
-                } else {
-                    oldValue = delegate.put(key, newValue);
-                    if (newKey) {
-                        events.add(new PropertyAddedEvent(this, key, newValue));
-                    } else if (oldValue != newValue) {
-                        events.add(new PropertyUpdatedEvent(this, key, oldValue, newValue));
-                    }
-                }
-            }
-            if (!events.isEmpty()) {
-                fireMultiPropertyEvent(events);
-                fireSizeChangedEvent(oldSize, size());
-            }
-        }
-    }
-
-    public Object remove(Object key) {
-        int oldSize = size();
-        Object result = delegate.remove(key);
-        if (key != null) {
-            firePropertyRemovedEvent(key, result);
-            fireSizeChangedEvent(oldSize, size());
-        }
-        return result;
-    }
-
-    public int size() {
-        return delegate.size();
-    }
-
-    public int getSize() {
-        return size();
-    }
-
-    public Collection values() {
-        return delegate.values();
-    }
-
-    // observable interface
-
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(listener);
-    }
-
-    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(propertyName, listener);
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners() {
-        return pcs.getPropertyChangeListeners();
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
-        return pcs.getPropertyChangeListeners(propertyName);
-    }
-
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(listener);
-    }
-
-    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(propertyName, listener);
-    }
-
-    public boolean hasListeners(String propertyName) {
-        return pcs.hasListeners(propertyName);
-    }
-
-    public enum ChangeType {
-        ADDED, UPDATED, REMOVED, CLEARED, MULTI, NONE;
-
-        public static final Object oldValue = new Object();
-        public static final Object newValue = new Object();
-
-        public static ChangeType resolve(int ordinal) {
-            switch (ordinal) {
-                case 0:
-                    return ADDED;
-                case 2:
-                    return REMOVED;
-                case 3:
-                    return CLEARED;
-                case 4:
-                    return MULTI;
-                case 5:
-                    return NONE;
-                case 1:
-                default:
-                    return UPDATED;
-            }
-        }
-    }
-
-    public abstract static class PropertyEvent extends PropertyChangeEvent {
-        private final ChangeType type;
-
-        public PropertyEvent(Object source, String propertyName, Object oldValue, Object newValue, ChangeType type) {
-            super(source, propertyName, oldValue, newValue);
-            this.type = type;
-        }
-
-        public int getType() {
-            return type.ordinal();
-        }
-
-        public ChangeType getChangeType() {
-            return type;
-        }
-
-        public String getTypeAsString() {
-            return type.name().toUpperCase();
-        }
-    }
-
-    public static class PropertyAddedEvent extends PropertyEvent {
-        public PropertyAddedEvent(Object source, String propertyName, Object newValue) {
-            super(source, propertyName, null, newValue, ChangeType.ADDED);
-        }
-    }
-
-    public static class PropertyUpdatedEvent extends PropertyEvent {
-        public PropertyUpdatedEvent(Object source, String propertyName, Object oldValue, Object newValue) {
-            super(source, propertyName, oldValue, newValue, ChangeType.UPDATED);
-        }
-    }
-
-    public static class PropertyRemovedEvent extends PropertyEvent {
-        public PropertyRemovedEvent(Object source, String propertyName, Object oldValue) {
-            super(source, propertyName, oldValue, null, ChangeType.REMOVED);
-        }
-    }
-
-    public static class PropertyClearedEvent extends PropertyEvent {
-        private final Map values = new HashMap();
-
-        public PropertyClearedEvent(Object source, Map values) {
-            super(source, ObservableMap.CLEARED_PROPERTY, values, null, ChangeType.CLEARED);
-            if (values != null) {
-                this.values.putAll(values);
-            }
-        }
-
-        public Map getValues() {
-            return Collections.unmodifiableMap(values);
-        }
-    }
-
-    public static class MultiPropertyEvent extends PropertyEvent {
-        public static final String MULTI_PROPERTY = "groovy_util_ObservableMap_MultiPropertyEvent_MULTI";
-        private static final PropertyEvent[] EMPTY_PROPERTY_EVENTS = new PropertyEvent[0];
-
-        private final PropertyEvent[] events;
-
-        public MultiPropertyEvent(Object source, PropertyEvent[] events) {
-            super(source, MULTI_PROPERTY, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI);
-            if (events != null && events.length > 0) {
-                this.events = new PropertyEvent[events.length];
-                System.arraycopy(events, 0, this.events, 0, events.length);
-            } else {
-            	this.events = EMPTY_PROPERTY_EVENTS;
-            }
-        }
-
-        public PropertyEvent[] getEvents() {
-            PropertyEvent[] copy = new PropertyEvent[events.length];
-            System.arraycopy(events, 0, copy, 0, events.length);
-            return copy;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/ObservableSet.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/ObservableSet.java b/src/main/groovy/util/ObservableSet.java
deleted file mode 100644
index b794436..0000000
--- a/src/main/groovy/util/ObservableSet.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.Stack;
-
-/**
- * Set decorator that will trigger PropertyChangeEvents when a value changes.<br>
- * An optional Closure may be specified and will work as a filter, if it returns true the property
- * will trigger an event (if the value indeed changed), otherwise it won't. The Closure may receive
- * 1 or 2 parameters, the single one being the value, the other one both the key and value, for
- * example:
- * <pre>
- * // skip all properties whose value is a closure
- * def set = new ObservableSet( {!(it instanceof Closure)} )
- * &lt;p/&gt;
- * // skip all properties whose name matches a regex
- * def set = new ObservableSet( { name, value -&gt; !(name =&tilde; /[A-Z+]/) } )
- * </pre>
- * The current implementation will trigger specialized events in the following scenarios, you need
- * not register a different listener as those events extend from PropertyChangeEvent
- * <ul>
- * <li>ObservableSet.ElementAddedEvent - a new element is added to the set</li>
- * <li>ObservableSet.ElementRemovedEvent - an element is removed from the set</li>
- * <li>ObservableSet.ElementUpdatedEvent - an element changes value (same as regular
- * PropertyChangeEvent)</li>
- * <li>ObservableSet.ElementClearedEvent - all elements have been removed from the list</li>
- * <li>ObservableSet.MultiElementAddedEvent - triggered by calling set.addAll()</li>
- * <li>ObservableSet.MultiElementRemovedEvent - triggered by calling
- * set.removeAll()/set.retainAll()</li>
- * </ul>
- *
- * <p>
- * <strong>Bound properties</strong>
- * <ul>
- * <li><tt>content</tt> - read-only.</li>
- * <li><tt>size</tt> - read-only.</li>
- * </ul>
- *
- * @author <a href="mailto:aalmiray@users.sourceforge.net">Andres Almiray</a>
- */
-public class ObservableSet<E> implements Set<E> {
-    private final Set<E> delegate;
-    private final PropertyChangeSupport pcs;
-    private final Closure test;
-
-    public static final String SIZE_PROPERTY = "size";
-    public static final String CONTENT_PROPERTY = "content";
-
-    public ObservableSet() {
-        this(new HashSet<E>(), null);
-    }
-
-    public ObservableSet(Set<E> delegate) {
-        this(delegate, null);
-    }
-
-    public ObservableSet(Closure test) {
-        this(new HashSet<E>(), test);
-    }
-
-    public ObservableSet(Set<E> delegate, Closure test) {
-        this.delegate = delegate;
-        this.test = test;
-        this.pcs = new PropertyChangeSupport(this);
-    }
-
-    public Set<E> getContent() {
-        return Collections.unmodifiableSet(delegate);
-    }
-
-    protected Set<E> getDelegateSet() {
-        return delegate;
-    }
-
-    protected Closure getTest() {
-        return test;
-    }
-
-    protected void fireElementAddedEvent(Object element) {
-        fireElementEvent(new ElementAddedEvent(this, element));
-    }
-
-    protected void fireMultiElementAddedEvent(List values) {
-        fireElementEvent(new MultiElementAddedEvent(this, values));
-    }
-
-    protected void fireElementClearedEvent(List values) {
-        fireElementEvent(new ElementClearedEvent(this, values));
-    }
-
-    protected void fireElementRemovedEvent(Object element) {
-        fireElementEvent(new ElementRemovedEvent(this, element));
-    }
-
-    protected void fireMultiElementRemovedEvent(List values) {
-        fireElementEvent(new MultiElementRemovedEvent(this, values));
-    }
-
-    protected void fireElementEvent(ElementEvent event) {
-        pcs.firePropertyChange(event);
-    }
-
-    protected void fireSizeChangedEvent(int oldValue, int newValue) {
-        pcs.firePropertyChange(new PropertyChangeEvent(this, SIZE_PROPERTY, oldValue, newValue));
-    }
-
-    // observable interface
-
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(listener);
-    }
-
-    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.addPropertyChangeListener(propertyName, listener);
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners() {
-        return pcs.getPropertyChangeListeners();
-    }
-
-    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
-        return pcs.getPropertyChangeListeners(propertyName);
-    }
-
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(listener);
-    }
-
-    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
-        pcs.removePropertyChangeListener(propertyName, listener);
-    }
-
-    public boolean hasListeners(String propertyName) {
-        return pcs.hasListeners(propertyName);
-    }
-
-    public int size() {
-        return delegate.size();
-    }
-
-    public boolean isEmpty() {
-        return delegate.isEmpty();
-    }
-
-    public boolean contains(Object o) {
-        return delegate.contains(o);
-    }
-
-    public Iterator<E> iterator() {
-        return new ObservableIterator<E>(delegate.iterator());
-    }
-
-    public Object[] toArray() {
-        return delegate.toArray();
-    }
-
-    public <T> T[] toArray(T[] ts) {
-        return (T[]) delegate.toArray(ts);
-    }
-
-    public boolean add(E e) {
-        int oldSize = size();
-        boolean success = delegate.add(e);
-        if (success) {
-            if (test != null) {
-                Object result = test.call(e);
-                if (result != null && result instanceof Boolean && (Boolean) result) {
-                    fireElementAddedEvent(e);
-                    fireSizeChangedEvent(oldSize, size());
-                }
-            } else {
-                fireElementAddedEvent(e);
-                fireSizeChangedEvent(oldSize, size());
-            }
-        }
-        return success;
-    }
-
-    public boolean remove(Object o) {
-        int oldSize = size();
-        boolean success = delegate.remove(o);
-        if (success) {
-            fireElementRemovedEvent(o);
-            fireSizeChangedEvent(oldSize, size());
-        }
-        return success;
-    }
-
-    public boolean containsAll(Collection<?> objects) {
-        return delegate.containsAll(objects);
-    }
-
-    public boolean addAll(Collection<? extends E> c) {
-        Set<E> duplicates = new HashSet<E>();
-        if (null != c) {
-            for (E e : c) {
-                if (!delegate.contains(e)) continue;
-                duplicates.add(e);
-            }
-        }
-
-        int oldSize = size();
-        boolean success = delegate.addAll(c);
-
-        if (success && c != null) {
-            List<E> values = new ArrayList<E>();
-            for (E element : c) {
-                if (test != null) {
-                    Object result = test.call(element);
-                    if (result != null && result instanceof Boolean && (Boolean) result && !duplicates.contains(element)) {
-                        values.add(element);
-                    }
-                } else if (!duplicates.contains(element)) {
-                    values.add(element);
-                }
-            }
-            if (!values.isEmpty()) {
-                fireMultiElementAddedEvent(values);
-                fireSizeChangedEvent(oldSize, size());
-            }
-        }
-
-        return success;
-    }
-
-    public boolean retainAll(Collection<?> c) {
-        if (c == null) {
-            return false;
-        }
-
-        List values = new ArrayList();
-        // GROOVY-7822 use Set for O(1) performance for contains
-        if (!(c instanceof Set)) {
-            c = new HashSet<Object>(c);
-        }
-        for (Object element : delegate) {
-            if (!c.contains(element)) {
-                values.add(element);
-            }
-        }
-
-        int oldSize = size();
-        boolean success = delegate.retainAll(c);
-        if (success && !values.isEmpty()) {
-            fireMultiElementRemovedEvent(values);
-            fireSizeChangedEvent(oldSize, size());
-        }
-
-        return success;
-    }
-
-    public boolean removeAll(Collection<?> c) {
-        if (c == null) {
-            return false;
-        }
-
-        List values = new ArrayList();
-        for (Object element : c) {
-            if (delegate.contains(element)) {
-                values.add(element);
-            }
-        }
-
-        int oldSize = size();
-        boolean success = delegate.removeAll(c);
-        if (success && !values.isEmpty()) {
-            fireMultiElementRemovedEvent(values);
-            fireSizeChangedEvent(oldSize, size());
-        }
-
-        return success;
-    }
-
-    public void clear() {
-        int oldSize = size();
-        List<E> values = new ArrayList<E>();
-        values.addAll(delegate);
-        delegate.clear();
-        if (!values.isEmpty()) {
-            fireElementClearedEvent(values);
-        }
-        fireSizeChangedEvent(oldSize, size());
-    }
-
-    protected class ObservableIterator<E> implements Iterator<E> {
-        private final Iterator<E> iterDelegate;
-        private final Stack<E> stack = new Stack<E>();
-
-        public ObservableIterator(Iterator<E> iterDelegate) {
-            this.iterDelegate = iterDelegate;
-        }
-
-        public Iterator<E> getDelegate() {
-            return iterDelegate;
-        }
-
-        public boolean hasNext() {
-            return iterDelegate.hasNext();
-        }
-
-        public E next() {
-            stack.push(iterDelegate.next());
-            return stack.peek();
-        }
-
-        public void remove() {
-            int oldSize = ObservableSet.this.size();
-            iterDelegate.remove();
-            fireElementRemovedEvent(stack.pop());
-            fireSizeChangedEvent(oldSize, size());
-        }
-    }
-
-    public enum ChangeType {
-        ADDED, REMOVED, CLEARED, MULTI_ADD, MULTI_REMOVE, NONE;
-
-        public static final Object oldValue = new Object();
-        public static final Object newValue = new Object();
-    }
-
-    public abstract static class ElementEvent extends PropertyChangeEvent {
-        private final ChangeType type;
-
-        public ElementEvent(Object source, Object oldValue, Object newValue, ChangeType type) {
-            super(source, ObservableSet.CONTENT_PROPERTY, oldValue, newValue);
-            this.type = type;
-        }
-
-        public int getType() {
-            return type.ordinal();
-        }
-
-        public ChangeType getChangeType() {
-            return type;
-        }
-
-        public String getTypeAsString() {
-            return type.name().toUpperCase();
-        }
-    }
-
-    public static class ElementAddedEvent extends ElementEvent {
-        public ElementAddedEvent(Object source, Object newValue) {
-            super(source, null, newValue, ChangeType.ADDED);
-        }
-    }
-
-    public static class ElementRemovedEvent extends ElementEvent {
-        public ElementRemovedEvent(Object source, Object value) {
-            super(source, value, null, ChangeType.REMOVED);
-        }
-    }
-
-    public static class ElementClearedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public ElementClearedEvent(Object source, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.CLEARED);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-
-    public static class MultiElementAddedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public MultiElementAddedEvent(Object source, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI_ADD);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-
-    public static class MultiElementRemovedEvent extends ElementEvent {
-        private final List values = new ArrayList();
-
-        public MultiElementRemovedEvent(Object source, List values) {
-            super(source, ChangeType.oldValue, ChangeType.newValue, ChangeType.MULTI_REMOVE);
-            if (values != null) {
-                this.values.addAll(values);
-            }
-        }
-
-        public List getValues() {
-            return Collections.unmodifiableList(values);
-        }
-    }
-}


[42/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/BindableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/BindableASTTransformation.java b/src/main/groovy/groovy/beans/BindableASTTransformation.java
new file mode 100644
index 0000000..6208a2b
--- /dev/null
+++ b/src/main/groovy/groovy/beans/BindableASTTransformation.java
@@ -0,0 +1,428 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.PropertyNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.ast.tools.PropertyNodeUtils;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.messages.SimpleMessage;
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.syntax.SyntaxException;
+import org.codehaus.groovy.transform.ASTTransformation;
+import org.codehaus.groovy.transform.GroovyASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+
+/**
+ * Handles generation of code for the {@code @Bindable} annotation when {@code @Vetoable}
+ * is not present.
+ * <p>
+ * Generally, it adds (if needed) a PropertyChangeSupport field and
+ * the needed add/removePropertyChangeListener methods to support the
+ * listeners.
+ * <p>
+ * It also generates the setter and wires the setter through the
+ * PropertyChangeSupport.
+ * <p>
+ * If a {@link Vetoable} annotation is detected it does nothing and
+ * lets the {@link VetoableASTTransformation} handle all the changes.
+ *
+ * @author Danno Ferrin (shemnon)
+ * @author Chris Reeves
+ */
+@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION)
+public class BindableASTTransformation implements ASTTransformation, Opcodes {
+
+    protected static ClassNode boundClassNode = ClassHelper.make(Bindable.class);
+
+    /**
+     * Convenience method to see if an annotated node is {@code @Bindable}.
+     *
+     * @param node the node to check
+     * @return true if the node is bindable
+     */
+    public static boolean hasBindableAnnotation(AnnotatedNode node) {
+        for (AnnotationNode annotation : node.getAnnotations()) {
+            if (boundClassNode.equals(annotation.getClassNode())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Handles the bulk of the processing, mostly delegating to other methods.
+     *
+     * @param nodes   the ast nodes
+     * @param source  the source unit for the nodes
+     */
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
+            throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
+        }
+        AnnotationNode node = (AnnotationNode) nodes[0];
+        AnnotatedNode parent = (AnnotatedNode) nodes[1];
+
+        if (VetoableASTTransformation.hasVetoableAnnotation(parent)) {
+            // VetoableASTTransformation will handle both @Bindable and @Vetoable
+            return;
+        }
+
+        ClassNode declaringClass = parent.getDeclaringClass();
+        if (parent instanceof FieldNode) {
+            if ((((FieldNode) parent).getModifiers() & Opcodes.ACC_FINAL) != 0) {
+                source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                        new SyntaxException("@groovy.beans.Bindable cannot annotate a final property.",
+                                node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                        source));
+            }
+
+            if (VetoableASTTransformation.hasVetoableAnnotation(parent.getDeclaringClass())) {
+                // VetoableASTTransformation will handle both @Bindable and @Vetoable
+                return;
+            }
+            addListenerToProperty(source, node, declaringClass, (FieldNode) parent);
+        } else if (parent instanceof ClassNode) {
+            addListenerToClass(source, (ClassNode) parent);
+        }
+    }
+
+    private void addListenerToProperty(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field) {
+        String fieldName = field.getName();
+        for (PropertyNode propertyNode : declaringClass.getProperties()) {
+            if (propertyNode.getName().equals(fieldName)) {
+                if (field.isStatic()) {
+                    //noinspection ThrowableInstanceNeverThrown
+                    source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                            new SyntaxException("@groovy.beans.Bindable cannot annotate a static property.",
+                                    node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                            source));
+                } else {
+                    if (needsPropertyChangeSupport(declaringClass, source)) {
+                        addPropertyChangeSupport(declaringClass);
+                    }
+                    createListenerSetter(declaringClass, propertyNode);
+                }
+                return;
+            }
+        }
+        //noinspection ThrowableInstanceNeverThrown
+        source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                new SyntaxException("@groovy.beans.Bindable must be on a property, not a field.  Try removing the private, protected, or public modifier.",
+                        node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                source));
+    }
+
+    private void addListenerToClass(SourceUnit source, ClassNode classNode) {
+        if (needsPropertyChangeSupport(classNode, source)) {
+            addPropertyChangeSupport(classNode);
+        }
+        for (PropertyNode propertyNode : classNode.getProperties()) {
+            FieldNode field = propertyNode.getField();
+            // look to see if per-field handlers will catch this one...
+            if (hasBindableAnnotation(field)
+                || ((field.getModifiers() & Opcodes.ACC_FINAL) != 0)
+                || field.isStatic()
+                || VetoableASTTransformation.hasVetoableAnnotation(field))
+            {
+                // explicitly labeled properties are already handled,
+                // don't transform final properties
+                // don't transform static properties
+                // VetoableASTTransformation will handle both @Bindable and @Vetoable
+                continue;
+            }
+            createListenerSetter(classNode, propertyNode);
+        }
+    }
+
+    /*
+     * Wrap an existing setter.
+     */
+    private static void wrapSetterMethod(ClassNode classNode, String propertyName) {
+        String getterName = "get" + MetaClassHelper.capitalize(propertyName);
+        MethodNode setter = classNode.getSetterMethod("set" + MetaClassHelper.capitalize(propertyName));
+
+        if (setter != null) {
+            // Get the existing code block
+            Statement code = setter.getCode();
+
+            Expression oldValue = varX("$oldValue");
+            Expression newValue = varX("$newValue");
+            BlockStatement block = new BlockStatement();
+
+            // create a local variable to hold the old value from the getter
+            block.addStatement(declS(oldValue, callThisX(getterName)));
+
+            // call the existing block, which will presumably set the value properly
+            block.addStatement(code);
+
+            // get the new value to emit in the event
+            block.addStatement(declS(newValue, callThisX(getterName)));
+
+            // add the firePropertyChange method call
+            block.addStatement(stmt(callThisX("firePropertyChange", args(constX(propertyName), oldValue, newValue))));
+
+            // replace the existing code block with our new one
+            setter.setCode(block);
+        }
+    }
+
+    private void createListenerSetter(ClassNode classNode, PropertyNode propertyNode) {
+        String setterName = "set" + MetaClassHelper.capitalize(propertyNode.getName());
+        if (classNode.getMethods(setterName).isEmpty()) {
+            Statement setterBlock = createBindableStatement(propertyNode, fieldX(propertyNode.getField()));
+
+            // create method void <setter>(<type> fieldName)
+            createSetterMethod(classNode, propertyNode, setterName, setterBlock);
+        } else {
+            wrapSetterMethod(classNode, propertyNode.getName());
+        }
+    }
+
+    /**
+     * Creates a statement body similar to:
+     * <code>this.firePropertyChange("field", field, field = value)</code>
+     *
+     * @param propertyNode           the field node for the property
+     * @param fieldExpression a field expression for setting the property value
+     * @return the created statement
+     */
+    protected Statement createBindableStatement(PropertyNode propertyNode, Expression fieldExpression) {
+        // create statementBody
+        return stmt(callThisX("firePropertyChange", args(constX(propertyNode.getName()), fieldExpression, assignX(fieldExpression, varX("value")))));
+    }
+
+    /**
+     * Creates a setter method with the given body.
+     *
+     * @param declaringClass the class to which we will add the setter
+     * @param propertyNode          the field to back the setter
+     * @param setterName     the name of the setter
+     * @param setterBlock    the statement representing the setter block
+     */
+    protected void createSetterMethod(ClassNode declaringClass, PropertyNode propertyNode, String setterName, Statement setterBlock) {
+        MethodNode setter = new MethodNode(
+                setterName,
+                PropertyNodeUtils.adjustPropertyModifiersForMethod(propertyNode),
+                ClassHelper.VOID_TYPE,
+                params(param(propertyNode.getType(), "value")),
+                ClassNode.EMPTY_ARRAY,
+                setterBlock);
+        setter.setSynthetic(true);
+        // add it to the class
+        declaringClass.addMethod(setter);
+    }
+
+    /**
+     * Snoops through the declaring class and all parents looking for methods
+     * <code>void addPropertyChangeListener(PropertyChangeListener)</code>,
+     * <code>void removePropertyChangeListener(PropertyChangeListener)</code>, and
+     * <code>void firePropertyChange(String, Object, Object)</code>. If any are defined all
+     * must be defined or a compilation error results.
+     *
+     * @param declaringClass the class to search
+     * @param sourceUnit the source unit, for error reporting. {@code @NotNull}.
+     * @return true if property change support should be added
+     */
+    protected boolean needsPropertyChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) {
+        boolean foundAdd = false, foundRemove = false, foundFire = false;
+        ClassNode consideredClass = declaringClass;
+        while (consideredClass!= null) {
+            for (MethodNode method : consideredClass.getMethods()) {
+                // just check length, MOP will match it up
+                foundAdd = foundAdd || method.getName().equals("addPropertyChangeListener") && method.getParameters().length == 1;
+                foundRemove = foundRemove || method.getName().equals("removePropertyChangeListener") && method.getParameters().length == 1;
+                foundFire = foundFire || method.getName().equals("firePropertyChange") && method.getParameters().length == 3;
+                if (foundAdd && foundRemove && foundFire) {
+                    return false;
+                }
+            }
+            consideredClass = consideredClass.getSuperClass();
+        }
+        // check if a super class has @Bindable annotations
+        consideredClass = declaringClass.getSuperClass();
+        while (consideredClass!=null) {
+            if (hasBindableAnnotation(consideredClass)) return false;
+            for (FieldNode field : consideredClass.getFields()) {
+                if (hasBindableAnnotation(field)) return false;
+            }
+            consideredClass = consideredClass.getSuperClass();
+        }
+        if (foundAdd || foundRemove || foundFire) {
+            sourceUnit.getErrorCollector().addErrorAndContinue(
+                new SimpleMessage("@Bindable cannot be processed on "
+                    + declaringClass.getName()
+                    + " because some but not all of addPropertyChangeListener, removePropertyChange, and firePropertyChange were declared in the current or super classes.",
+                sourceUnit)
+            );
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Adds the necessary field and methods to support property change support.
+     * <p>
+     * Adds a new field:
+     * <pre>
+     * <code>protected final java.beans.PropertyChangeSupport this$PropertyChangeSupport = new java.beans.PropertyChangeSupport(this)</code>"
+     * </pre>
+     * <p>
+     * Also adds support methods:
+     * <pre>
+     * <code>public void addPropertyChangeListener(java.beans.PropertyChangeListener)</code>
+     * <code>public void addPropertyChangeListener(String, java.beans.PropertyChangeListener)</code>
+     * <code>public void removePropertyChangeListener(java.beans.PropertyChangeListener)</code>
+     * <code>public void removePropertyChangeListener(String, java.beans.PropertyChangeListener)</code>
+     * <code>public java.beans.PropertyChangeListener[] getPropertyChangeListeners()</code>
+     * </pre>
+     *
+     * @param declaringClass the class to which we add the support field and methods
+     */
+    protected void addPropertyChangeSupport(ClassNode declaringClass) {
+        ClassNode pcsClassNode = ClassHelper.make(PropertyChangeSupport.class);
+        ClassNode pclClassNode = ClassHelper.make(PropertyChangeListener.class);
+        //String pcsFieldName = "this$propertyChangeSupport";
+
+        // add field:
+        // protected final PropertyChangeSupport this$propertyChangeSupport = new java.beans.PropertyChangeSupport(this)
+        FieldNode pcsField = declaringClass.addField(
+                "this$propertyChangeSupport",
+                ACC_FINAL | ACC_PRIVATE | ACC_SYNTHETIC,
+                pcsClassNode,
+                ctorX(pcsClassNode, args(varX("this"))));
+
+        // add method:
+        // void addPropertyChangeListener(listener) {
+        //     this$propertyChangeSupport.addPropertyChangeListener(listener)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "addPropertyChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(pclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(pcsField), "addPropertyChangeListener", args(varX("listener", pclClassNode))))));
+
+        // add method:
+        // void addPropertyChangeListener(name, listener) {
+        //     this$propertyChangeSupport.addPropertyChangeListener(name, listener)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "addPropertyChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(pclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(pcsField), "addPropertyChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", pclClassNode))))));
+
+        // add method:
+        // boolean removePropertyChangeListener(listener) {
+        //    return this$propertyChangeSupport.removePropertyChangeListener(listener);
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "removePropertyChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(pclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(pcsField), "removePropertyChangeListener", args(varX("listener", pclClassNode))))));
+
+        // add method: void removePropertyChangeListener(name, listener)
+        declaringClass.addMethod(
+                new MethodNode(
+                        "removePropertyChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(pclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(pcsField), "removePropertyChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", pclClassNode))))));
+
+        // add method:
+        // void firePropertyChange(String name, Object oldValue, Object newValue) {
+        //     this$propertyChangeSupport.firePropertyChange(name, oldValue, newValue)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "firePropertyChange",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(ClassHelper.OBJECT_TYPE, "oldValue"), param(ClassHelper.OBJECT_TYPE, "newValue")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(pcsField), "firePropertyChange", args(varX("name", ClassHelper.STRING_TYPE), varX("oldValue"), varX("newValue"))))));
+
+        // add method:
+        // PropertyChangeListener[] getPropertyChangeListeners() {
+        //   return this$propertyChangeSupport.getPropertyChangeListeners
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "getPropertyChangeListeners",
+                        ACC_PUBLIC,
+                        pclClassNode.makeArray(),
+                        Parameter.EMPTY_ARRAY,
+                        ClassNode.EMPTY_ARRAY,
+                        returnS(callX(fieldX(pcsField), "getPropertyChangeListeners"))));
+
+        // add method:
+        // PropertyChangeListener[] getPropertyChangeListeners(String name) {
+        //   return this$propertyChangeSupport.getPropertyChangeListeners(name)
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "getPropertyChangeListeners",
+                        ACC_PUBLIC,
+                        pclClassNode.makeArray(),
+                        params(param(ClassHelper.STRING_TYPE, "name")),
+                        ClassNode.EMPTY_ARRAY,
+                        returnS(callX(fieldX(pcsField), "getPropertyChangeListeners", args(varX("name", ClassHelper.STRING_TYPE))))));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/DefaultPropertyAccessor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/DefaultPropertyAccessor.java b/src/main/groovy/groovy/beans/DefaultPropertyAccessor.java
new file mode 100644
index 0000000..47dae41
--- /dev/null
+++ b/src/main/groovy/groovy/beans/DefaultPropertyAccessor.java
@@ -0,0 +1,34 @@
+/*
+ *  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 groovy.beans;
+
+/**
+ * @author Andres Almiray
+ */
+public class DefaultPropertyAccessor implements PropertyAccessor {
+    public static final PropertyAccessor INSTANCE = new DefaultPropertyAccessor();
+
+    public Object read(Object owner, String propertyName) {
+        return DefaultPropertyReader.INSTANCE.read(owner, propertyName);
+    }
+
+    public void write(Object owner, String propertyName, Object value) {
+        DefaultPropertyWriter.INSTANCE.write(owner, propertyName, value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/DefaultPropertyReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/DefaultPropertyReader.java b/src/main/groovy/groovy/beans/DefaultPropertyReader.java
new file mode 100644
index 0000000..a03b9a3
--- /dev/null
+++ b/src/main/groovy/groovy/beans/DefaultPropertyReader.java
@@ -0,0 +1,32 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * @author Andres Almiray
+ */
+public class DefaultPropertyReader implements PropertyReader {
+    public static final PropertyReader INSTANCE = new DefaultPropertyReader();
+
+    public Object read(Object owner, String propertyName) {
+        return InvokerHelper.getPropertySafe(owner, propertyName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/DefaultPropertyWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/DefaultPropertyWriter.java b/src/main/groovy/groovy/beans/DefaultPropertyWriter.java
new file mode 100644
index 0000000..12ac7db
--- /dev/null
+++ b/src/main/groovy/groovy/beans/DefaultPropertyWriter.java
@@ -0,0 +1,32 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * @author Andres Almiray
+ */
+public class DefaultPropertyWriter implements PropertyWriter {
+    public static final PropertyWriter INSTANCE = new DefaultPropertyWriter();
+
+    public void write(Object owner, String propertyName, Object value) {
+        InvokerHelper.setProperty(owner, propertyName, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/ListenerList.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/ListenerList.groovy b/src/main/groovy/groovy/beans/ListenerList.groovy
new file mode 100644
index 0000000..b8119f1
--- /dev/null
+++ b/src/main/groovy/groovy/beans/ListenerList.groovy
@@ -0,0 +1,131 @@
+/*
+ *  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 groovy.beans
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass
+
+import java.lang.annotation.Documented
+import java.lang.annotation.ElementType
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+import java.lang.annotation.Target
+
+/**
+ * This annotation adds Java-style listener support to a class based on an annotated Collection-property.
+ * <p>
+ * For any given Collection property, several methods will be written into the enclosing class during the compile phase. These
+ * changes are visible from Java or other languages. The List is intended to hold listeners of some sort, and the methods
+ * addListener, removeListener, and getListeners are all added to the class. The actual methods names depend on the generic
+ * type of the collection.
+ * <p>
+ * Given the following example:<br>
+ * <pre>
+ * class MyClass {
+ *     &#064;groovy.beans.ListenerList
+ *     List&lt;java.awt.event.ActionListener&gt; listeners
+ * }
+ * </pre>
+ * The following code is generated:
+ * <pre>
+ * public class MyClass extends java.lang.Object {
+ *     &#064;groovy.beans.ListenerList
+ *     private java.util.List&lt;java.awt.event.ActionListener&gt; listeners
+ *
+ *     public void addActionListener(java.awt.event.ActionListener listener) {
+ *         if ( listener == null) {
+ *             return null
+ *         }
+ *         if ( listeners == null) {
+ *             listeners = []
+ *         }
+ *         listeners.add(listener)
+ *     }
+ *
+ *     public void removeActionListener(java.awt.event.ActionListener listener) {
+ *         if ( listener == null) {
+ *             return null
+ *         }
+ *         if ( listeners == null) {
+ *             listeners = []
+ *         }
+ *         listeners.remove(listener)
+ *     }
+ *
+ *     public java.awt.event.ActionListener[] getActionListeners() {
+ *         java.lang.Object __result = []
+ *         if ( listeners != null) {
+ *             __result.addAll(listeners)
+ *         }
+ *         return (( __result ) as java.awt.event.ActionListener[])
+ *     }
+ *
+ *     public void fireActionPerformed(java.awt.event.ActionEvent param0) {
+ *         if ( listeners != null) {
+ *             def __list = new java.util.ArrayList(listeners)
+ *             for (java.lang.Object listener : __list ) {
+ *                 listener.actionPerformed(param0)
+ *             }
+ *         }
+ *     }
+ * }
+ * </pre>
+ * A fire method is created for each public method in the target class. In this case, ActionListener only has one
+ * method. For a four method interface, four fire methods would be created.
+ * <p>
+ * The annotation can take the following parameters:
+ * <pre>
+ * name        = a suffix for creating the add, remove, and get methods.
+ *               Default: Name of the listener type
+ *               In the above example, if name is set to MyListener, then the class will have an addMyListener,
+ *               removeMyListener, and getMyListeners methods. 
+ *
+ * synchronize = Whether or not the methods created should be synchronized at the method level. 
+ *               Default: false
+ * </pre>
+ * <p>
+ * <strong>Compilation Errors</strong> - Using this annotation incorrectly results in compilation errors rather
+ * than runtime errors. A list of potential problems includes:
+ * <ul>
+ * <li>This annotation can only be applied to a field of type Collection</li>
+ * <li>The annotated Collection field must have a generic type</li>
+ * <li>The annotated Collection field must not have a generic wildcard declared</li>
+ * <li>The generated methods must not already exist</li>
+ * </ul>
+ *
+ * @see ListenerListASTTransformation
+ * @author Alexander Klein
+ * @author Hamlet D'Arcy
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.FIELD)
+@GroovyASTTransformationClass('groovy.beans.ListenerListASTTransformation')
+@interface ListenerList {
+    /**
+     * A suffix for creating the add, remove, and get methods
+     * defaulting to the name of the listener type, e.g. if name is set to MyListener,
+     * then the class will have addMyListener, removeMyListener, and getMyListeners methods.
+     */
+    String name() default ""
+
+    /**
+     * Whether or not the methods created should be synchronized at the method level.
+     */
+    boolean synchronize() default false
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/ListenerListASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/ListenerListASTTransformation.groovy b/src/main/groovy/groovy/beans/ListenerListASTTransformation.groovy
new file mode 100644
index 0000000..1d7fbf7
--- /dev/null
+++ b/src/main/groovy/groovy/beans/ListenerListASTTransformation.groovy
@@ -0,0 +1,384 @@
+/*
+ *  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 groovy.beans
+
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotatedNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.GenericsType
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.VariableScope
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.BinaryExpression
+import org.codehaus.groovy.ast.expr.BooleanExpression
+import org.codehaus.groovy.ast.expr.CastExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression
+import org.codehaus.groovy.ast.expr.DeclarationExpression
+import org.codehaus.groovy.ast.expr.ListExpression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.EmptyStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage
+import org.codehaus.groovy.syntax.SyntaxException
+import org.codehaus.groovy.syntax.Token
+import org.codehaus.groovy.syntax.Types
+import org.codehaus.groovy.transform.ASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformation
+import org.objectweb.asm.Opcodes
+
+/**
+ * Handles generation of code for the {@code @ListenerList} annotation.
+ * <p>
+ * Generally, it adds the needed add&lt;Listener&gt;, remove&lt;Listener&gt; and
+ * get&lt;Listener&gt;s methods to support the Java Beans API.
+ * <p>
+ * Additionally it adds corresponding fire&lt;Event&gt; methods.
+ * <p>
+ *
+ * @author Alexander Klein
+ * @author Hamlet D'Arcy
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+class ListenerListASTTransformation implements ASTTransformation, Opcodes {
+    private static final Class MY_CLASS = groovy.beans.ListenerList.class
+    private static final ClassNode COLLECTION_TYPE = ClassHelper.make(Collection)
+
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
+            throw new RuntimeException("Internal error: wrong types: ${node.class} / ${parent.class}")
+        }
+        AnnotationNode node = nodes[0]
+        FieldNode field = nodes[1]
+        ClassNode declaringClass = nodes[1].declaringClass
+        ClassNode parentClass = field.type
+
+        boolean isCollection = parentClass.isDerivedFrom(COLLECTION_TYPE) || parentClass.implementsInterface(COLLECTION_TYPE)
+
+        if (!isCollection) {
+            addError(node, source, '@' + MY_CLASS.name + ' can only annotate collection properties.')
+            return
+        }
+
+        def types = field.type.genericsTypes
+        if (!types) {
+            addError(node, source, '@' + MY_CLASS.name + ' fields must have a generic type.')
+            return
+        }
+
+        if (types[0].wildcard) {
+            addError(node, source, '@' + MY_CLASS.name + ' fields with generic wildcards not yet supported.')
+            return
+        }
+
+        def listener = types[0].type
+
+        if (!field.initialValueExpression) {
+            field.initialValueExpression = new ListExpression()
+        }
+
+        def name = node.getMember('name')?.value ?: listener.nameWithoutPackage
+
+        def fireList = listener.methods.findAll { MethodNode m ->
+            m.isPublic() && !m.isSynthetic() && !m.isStatic()
+        }
+
+        def synchronize = node.getMember('synchronize')?.value ?: false
+        addAddListener(source, node, declaringClass, field, listener, name, synchronize)
+        addRemoveListener(source, node, declaringClass, field, listener, name, synchronize)
+        addGetListeners(source, node, declaringClass, field, listener, name, synchronize)
+
+        fireList.each { MethodNode method ->
+            addFireMethods(source, node, declaringClass, field, types, synchronize, method)
+        }
+    }
+
+    private static def addError(AnnotationNode node, SourceUnit source, String message) {
+        source.errorCollector.addError(
+                new SyntaxErrorMessage(new SyntaxException(
+                        message,
+                        node.lineNumber,
+                        node.columnNumber),
+                        source))
+    }
+
+    /**
+     * Adds the add&lt;Listener&gt; method like:
+     * <pre>
+     * synchronized void add${name.capitalize}(${listener.name} listener) {
+     *     if (listener == null)
+     *         return
+     *     if (${field.name} == null)
+     *        ${field.name} = []
+     *     ${field.name}.add(listener)
+     * }
+     * </pre>
+     */
+    void addAddListener(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
+
+        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
+        def methodReturnType = ClassHelper.make(Void.TYPE)
+        def methodName = "add${name.capitalize()}"
+        def cn = ClassHelper.makeWithoutCaching(listener.name)
+        cn.redirect = listener
+        def methodParameter = [new Parameter(cn,'listener')] as Parameter[]
+
+        if (declaringClass.hasMethod(methodName, methodParameter)) {
+            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
+            return
+        }
+
+        BlockStatement block = new BlockStatement()
+        block.addStatements([
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression('listener'),
+                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new ReturnStatement(ConstantExpression.NULL),
+                        EmptyStatement.INSTANCE
+                ),
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new ExpressionStatement(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.EQUAL, 0, 0),
+                                        new ListExpression()
+                                )
+                        ),
+                        EmptyStatement.INSTANCE
+                ),
+                new ExpressionStatement(
+                        new MethodCallExpression(new VariableExpression(field.name), new ConstantExpression('add'), new ArgumentListExpression(new VariableExpression('listener')))
+                )
+        ])
+        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
+    }
+
+    /**
+     * Adds the remove<Listener> method like:
+     * <pre>
+     * synchronized void remove${name.capitalize}(${listener.name} listener) {
+     *     if (listener == null)
+     *         return
+     *     if (${field.name} == null)
+     *         ${field.name} = []
+     *     ${field.name}.remove(listener)
+     * }
+     * </pre>
+     */
+    void addRemoveListener(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
+        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
+        def methodReturnType = ClassHelper.make(Void.TYPE)
+        def methodName = "remove${name.capitalize()}"
+        def cn = ClassHelper.makeWithoutCaching(listener.name)
+        cn.redirect = listener
+        def methodParameter = [new Parameter(cn,'listener')] as Parameter[]
+
+        if (declaringClass.hasMethod(methodName, methodParameter)) {
+            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
+            return
+        }
+
+        BlockStatement block = new BlockStatement()
+        block.addStatements([
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression('listener'),
+                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new ReturnStatement(ConstantExpression.NULL),
+                        EmptyStatement.INSTANCE
+                ),
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.COMPARE_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new ExpressionStatement(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.EQUAL, 0, 0),
+                                        new ListExpression()
+                                )
+                        ),
+                        EmptyStatement.INSTANCE
+                ),
+                new ExpressionStatement(
+                        new MethodCallExpression(new VariableExpression(field.name), new ConstantExpression('remove'), new ArgumentListExpression(new VariableExpression("listener")))
+                )
+        ])
+        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
+    }
+
+    /**
+     * Adds the get&lt;Listener&gt;s method like:
+     * <pre>
+     * synchronized ${name.capitalize}[] get${name.capitalize}s() {
+     *     def __result = []
+     *     if (${field.name} != null)
+     *         __result.addAll(${field.name})
+     *     return __result as ${name.capitalize}[]
+     * }
+     * </pre>
+     */
+    void addGetListeners(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, ClassNode listener, String name, synchronize) {
+        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
+        def methodReturnType = listener.makeArray()
+        def methodName = "get${name.capitalize()}s"
+        def methodParameter = [] as Parameter[]
+
+        if (declaringClass.hasMethod(methodName, methodParameter)) {
+            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
+            return
+        }
+
+        BlockStatement block = new BlockStatement()
+        block.addStatements([
+                new ExpressionStatement(
+                        new DeclarationExpression(
+                                new VariableExpression("__result", ClassHelper.DYNAMIC_TYPE),
+                                Token.newSymbol(Types.EQUALS, 0, 0),
+                                new ListExpression()
+                        )),
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.COMPARE_NOT_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new ExpressionStatement(
+                                new MethodCallExpression(new VariableExpression('__result'), new ConstantExpression('addAll'), new ArgumentListExpression(new VariableExpression(field.name)))
+                        ),
+                        EmptyStatement.INSTANCE
+                ),
+                new ReturnStatement(
+                        new CastExpression(
+                                methodReturnType,
+                                new VariableExpression('__result')
+                        )
+                )
+        ])
+        declaringClass.addMethod(new MethodNode(methodName, methodModifiers, methodReturnType, methodParameter, [] as ClassNode[], block))
+    }
+
+    /**
+     * Adds the fire&lt;Event&gt; methods like:
+     * <pre>
+     * void fire${fireMethod.capitalize()}(${parameterList.join(', ')}) {
+     *     if (${field.name} != null) {
+     *         def __list = new ArrayList(${field.name})
+     *         __list.each { listener ->
+     *             listener.$eventMethod(${evt})
+     *         }
+     *     }
+     * }
+     * </pre>
+     */
+    void addFireMethods(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field, GenericsType[] types, boolean synchronize, MethodNode method) {
+
+        def methodReturnType = ClassHelper.make(Void.TYPE)
+        def methodName = "fire${method.name.capitalize()}"
+        def methodModifiers = synchronize ? ACC_PUBLIC | ACC_SYNCHRONIZED : ACC_PUBLIC
+
+        if (declaringClass.hasMethod(methodName, method.parameters)) {
+            addError node, source, "Conflict using @${MY_CLASS.name}. Class $declaringClass.name already has method $methodName"
+            return
+        }
+
+        def args = new ArgumentListExpression(method.parameters)
+
+        BlockStatement block = new BlockStatement()
+        def listenerListType = ClassHelper.make(ArrayList).plainNodeReference
+        listenerListType.setGenericsTypes(types)
+        block.addStatements([
+                new IfStatement(
+                        new BooleanExpression(
+                                new BinaryExpression(
+                                        new VariableExpression(field.name),
+                                        Token.newSymbol(Types.COMPARE_NOT_EQUAL, 0, 0),
+                                        ConstantExpression.NULL
+                                )
+                        ),
+                        new BlockStatement([
+                                new ExpressionStatement(
+                                        new DeclarationExpression(
+                                                new VariableExpression('__list', listenerListType),
+                                                Token.newSymbol(Types.EQUALS, 0, 0),
+                                                new ConstructorCallExpression(listenerListType, new ArgumentListExpression(
+                                                        new VariableExpression(field.name)
+                                                ))
+                                        )
+                                ),
+                                new ForStatement(
+                                        new Parameter(ClassHelper.DYNAMIC_TYPE, 'listener'),
+                                        new VariableExpression('__list'),
+                                        new BlockStatement([
+                                                new ExpressionStatement(
+                                                        new MethodCallExpression(
+                                                                new VariableExpression('listener'),
+                                                                method.name,
+                                                                args
+                                                        )
+                                                )
+                                        ], new VariableScope())
+                                )
+                        ], new VariableScope()),
+                        EmptyStatement.INSTANCE
+                )
+        ])
+
+        def params = method.parameters.collect {
+            def paramType = ClassHelper.getWrapper(it.type)
+            def cn = paramType.plainNodeReference
+            cn.setRedirect(paramType)
+            new Parameter(cn, it.name)
+        }
+        declaringClass.addMethod(methodName, methodModifiers, methodReturnType, params as Parameter[], [] as ClassNode[], block)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/PropertyAccessor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/PropertyAccessor.java b/src/main/groovy/groovy/beans/PropertyAccessor.java
new file mode 100644
index 0000000..822ab10
--- /dev/null
+++ b/src/main/groovy/groovy/beans/PropertyAccessor.java
@@ -0,0 +1,25 @@
+/*
+ *  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 groovy.beans;
+
+/**
+ * @author Andres Almiray
+ */
+public interface PropertyAccessor extends PropertyReader, PropertyWriter {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/PropertyReader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/PropertyReader.java b/src/main/groovy/groovy/beans/PropertyReader.java
new file mode 100644
index 0000000..4ef13af
--- /dev/null
+++ b/src/main/groovy/groovy/beans/PropertyReader.java
@@ -0,0 +1,26 @@
+/*
+ *  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 groovy.beans;
+
+/**
+ * @author Andres Almiray
+ */
+public interface PropertyReader {
+    Object read(Object owner, String propertyName);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/PropertyWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/PropertyWriter.java b/src/main/groovy/groovy/beans/PropertyWriter.java
new file mode 100644
index 0000000..5b9e1ce
--- /dev/null
+++ b/src/main/groovy/groovy/beans/PropertyWriter.java
@@ -0,0 +1,26 @@
+/*
+ *  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 groovy.beans;
+
+/**
+ * @author Andres Almiray
+ */
+public interface PropertyWriter {
+    void write(Object owner, String propertyName, Object value);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/Vetoable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/Vetoable.java b/src/main/groovy/groovy/beans/Vetoable.java
new file mode 100644
index 0000000..ff7d8de
--- /dev/null
+++ b/src/main/groovy/groovy/beans/Vetoable.java
@@ -0,0 +1,113 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a groovy property or a class.
+ * <p>
+ * When annotating a property it indicates that the property should be a
+ * constrained property according to the JavaBeans spec, subject to
+ * listeners vetoing the property change.
+ * <p>
+ * When annotating a class it indicates that all groovy properties in that
+ * class should be bound as though each property had the annotation (even
+ * if it already has it explicitly).
+ * <p>
+ * It is a compilation error to place this annotation on a field (that is
+ * not a property, i.e. has scope visibility modifiers).
+ * <p>
+ * If a property with a user defined setter method is annotated the code
+ * block is wrapped with the needed code to fire off the event.
+ * <p>
+ * Here is a simple example of how to annotate a class with Vetoable: 
+ * <pre>
+ * &#064;groovy.beans.Vetoable
+ * class Person {
+ *     String firstName
+ *     def zipCode
+ * }
+ * </pre>
+ * This code is transformed by the compiler into something resembling the following
+ * snippet. Notice the difference between a String and a def/Object property: 
+ * <pre>
+ * public class Person implements groovy.lang.GroovyObject { 
+ *     private java.lang.String firstName
+ *     private java.lang.Object zipCode 
+ *     final private java.beans.VetoableChangeSupport this$vetoableChangeSupport 
+ * 
+ *     public Person() {
+ *         this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)
+ *     }
+ * 
+ *     public void addVetoableChangeListener(java.beans.VetoableChangeListener listener) {
+ *         this$vetoableChangeSupport.addVetoableChangeListener(listener)
+ *     }
+ * 
+ *     public void addVetoableChangeListener(java.lang.String name, java.beans.VetoableChangeListener listener) {
+ *         this$vetoableChangeSupport.addVetoableChangeListener(name, listener)
+ *     }
+ * 
+ *     public void removeVetoableChangeListener(java.beans.VetoableChangeListener listener) {
+ *         this$vetoableChangeSupport.removeVetoableChangeListener(listener)
+ *     }
+ * 
+ *     public void removeVetoableChangeListener(java.lang.String name, java.beans.VetoableChangeListener listener) {
+ *         this$vetoableChangeSupport.removeVetoableChangeListener(name, listener)
+ *     }
+ * 
+ *     public void fireVetoableChange(java.lang.String name, java.lang.Object oldValue, java.lang.Object newValue) throws java.beans.PropertyVetoException {
+ *         this$vetoableChangeSupport.fireVetoableChange(name, oldValue, newValue)
+ *     }
+ * 
+ *     public java.beans.VetoableChangeListener[] getVetoableChangeListeners() {
+ *         return this$vetoableChangeSupport.getVetoableChangeListeners()
+ *     }
+ * 
+ *     public java.beans.VetoableChangeListener[] getVetoableChangeListeners(java.lang.String name) {
+ *         return this$vetoableChangeSupport.getVetoableChangeListeners(name)
+ *     }
+ * 
+ *     public void setFirstName(java.lang.String value) throws java.beans.PropertyVetoException {
+ *         this.fireVetoableChange('firstName', firstName, value)
+ *         firstName = value 
+ *     }
+ * 
+ *     public void setZipCode(java.lang.Object value) throws java.beans.PropertyVetoException {
+ *         this.fireVetoableChange('zipCode', zipCode, value)
+ *         zipCode = value 
+ *     }
+ * }
+ * </pre>
+ *
+ * @see VetoableASTTransformation
+ * @author Danno Ferrin (shemnon)
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD, ElementType.TYPE})
+@GroovyASTTransformationClass("groovy.beans.VetoableASTTransformation")
+public @interface Vetoable {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/beans/VetoableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/beans/VetoableASTTransformation.java b/src/main/groovy/groovy/beans/VetoableASTTransformation.java
new file mode 100644
index 0000000..e52e3a8
--- /dev/null
+++ b/src/main/groovy/groovy/beans/VetoableASTTransformation.java
@@ -0,0 +1,444 @@
+/*
+ *  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 groovy.beans;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.PropertyNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.ast.tools.PropertyNodeUtils;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.messages.SimpleMessage;
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
+import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.codehaus.groovy.syntax.SyntaxException;
+import org.codehaus.groovy.transform.GroovyASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+
+/**
+ * Handles generation of code for the {@code @Vetoable} annotation, and {@code @Bindable}
+ * if also present.
+ * <p>
+ * Generally, it adds (if needed) a VetoableChangeSupport field and
+ * the needed add/removeVetoableChangeListener methods to support the
+ * listeners.
+ * <p>
+ * It also generates the setter and wires the setter through the
+ * VetoableChangeSupport.
+ * <p>
+ * If a {@link Bindable} annotation is detected it also adds support similar
+ * to what {@link BindableASTTransformation} would do.
+ *
+ * @author Danno Ferrin (shemnon)
+ * @author Chris Reeves
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+public class VetoableASTTransformation extends BindableASTTransformation {
+
+    protected static ClassNode constrainedClassNode = ClassHelper.make(Vetoable.class);
+
+    /**
+     * Convenience method to see if an annotated node is {@code @Vetoable}.
+     *
+     * @param node the node to check
+     * @return true if the node is constrained
+     */
+    public static boolean hasVetoableAnnotation(AnnotatedNode node) {
+        for (AnnotationNode annotation : node.getAnnotations()) {
+            if (constrainedClassNode.equals(annotation.getClassNode())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Handles the bulk of the processing, mostly delegating to other methods.
+     *
+     * @param nodes   the AST nodes
+     * @param source  the source unit for the nodes
+     */
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
+            throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
+        }
+        AnnotationNode node = (AnnotationNode) nodes[0];
+
+        if (nodes[1] instanceof ClassNode) {
+            addListenerToClass(source, (ClassNode) nodes[1]);
+        } else {
+            if ((((FieldNode)nodes[1]).getModifiers() & Opcodes.ACC_FINAL) != 0) {
+                source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                        new SyntaxException("@groovy.beans.Vetoable cannot annotate a final property.",
+                                node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                        source));
+            }
+
+            addListenerToProperty(source, node, (AnnotatedNode) nodes[1]);
+        }
+    }
+
+    private void addListenerToProperty(SourceUnit source, AnnotationNode node, AnnotatedNode parent) {
+        ClassNode declaringClass = parent.getDeclaringClass();
+        FieldNode field = ((FieldNode) parent);
+        String fieldName = field.getName();
+        for (PropertyNode propertyNode : declaringClass.getProperties()) {
+            boolean bindable = BindableASTTransformation.hasBindableAnnotation(parent)
+                    || BindableASTTransformation.hasBindableAnnotation(parent.getDeclaringClass());
+
+            if (propertyNode.getName().equals(fieldName)) {
+                if (field.isStatic()) {
+                    //noinspection ThrowableInstanceNeverThrown
+                    source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                            new SyntaxException("@groovy.beans.Vetoable cannot annotate a static property.",
+                                    node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                            source));
+                } else {
+                    createListenerSetter(source, bindable, declaringClass, propertyNode);
+                }
+                return;
+            }
+        }
+        //noinspection ThrowableInstanceNeverThrown
+        source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
+                new SyntaxException("@groovy.beans.Vetoable must be on a property, not a field.  Try removing the private, protected, or public modifier.",
+                        node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
+                source));
+    }
+
+
+    private void addListenerToClass(SourceUnit source, ClassNode classNode) {
+        boolean bindable = BindableASTTransformation.hasBindableAnnotation(classNode);
+        for (PropertyNode propertyNode : classNode.getProperties()) {
+            if (!hasVetoableAnnotation(propertyNode.getField())
+                && !propertyNode.getField().isFinal()
+                && !propertyNode.getField().isStatic())
+            {
+                createListenerSetter(source,
+                        bindable || BindableASTTransformation.hasBindableAnnotation(propertyNode.getField()),
+                    classNode, propertyNode);
+            }
+        }
+    }
+
+    /**
+     * Wrap an existing setter.
+     */
+    private static void wrapSetterMethod(ClassNode classNode, boolean bindable, String propertyName) {
+        String getterName = "get" + MetaClassHelper.capitalize(propertyName);
+        MethodNode setter = classNode.getSetterMethod("set" + MetaClassHelper.capitalize(propertyName));
+
+        if (setter != null) {
+            // Get the existing code block
+            Statement code = setter.getCode();
+
+            Expression oldValue = varX("$oldValue");
+            Expression newValue = varX("$newValue");
+            Expression proposedValue = varX(setter.getParameters()[0].getName());
+            BlockStatement block = new BlockStatement();
+
+            // create a local variable to hold the old value from the getter
+            block.addStatement(declS(oldValue, callThisX(getterName)));
+
+            // add the fireVetoableChange method call
+            block.addStatement(stmt(callThisX("fireVetoableChange", args(
+                    constX(propertyName), oldValue, proposedValue))));
+
+            // call the existing block, which will presumably set the value properly
+            block.addStatement(code);
+
+            if (bindable) {
+                // get the new value to emit in the event
+                block.addStatement(declS(newValue, callThisX(getterName)));
+
+                // add the firePropertyChange method call
+                block.addStatement(stmt(callThisX("firePropertyChange", args(constX(propertyName), oldValue, newValue))));
+            }
+
+            // replace the existing code block with our new one
+            setter.setCode(block);
+        }
+    }
+
+    private void createListenerSetter(SourceUnit source, boolean bindable, ClassNode declaringClass, PropertyNode propertyNode) {
+        if (bindable && needsPropertyChangeSupport(declaringClass, source)) {
+            addPropertyChangeSupport(declaringClass);
+        }
+        if (needsVetoableChangeSupport(declaringClass, source)) {
+            addVetoableChangeSupport(declaringClass);
+        }
+        String setterName = "set" + MetaClassHelper.capitalize(propertyNode.getName());
+        if (declaringClass.getMethods(setterName).isEmpty()) {
+            Expression fieldExpression = fieldX(propertyNode.getField());
+            BlockStatement setterBlock = new BlockStatement();
+            setterBlock.addStatement(createConstrainedStatement(propertyNode, fieldExpression));
+            if (bindable) {
+                setterBlock.addStatement(createBindableStatement(propertyNode, fieldExpression));
+            } else {
+                setterBlock.addStatement(createSetStatement(fieldExpression));
+            }
+
+            // create method void <setter>(<type> fieldName)
+            createSetterMethod(declaringClass, propertyNode, setterName, setterBlock);
+        } else {
+            wrapSetterMethod(declaringClass, bindable, propertyNode.getName());
+        }
+    }
+
+    /**
+     * Creates a statement body similar to:
+     * <code>this.fireVetoableChange("field", field, field = value)</code>
+     *
+     * @param propertyNode           the field node for the property
+     * @param fieldExpression a field expression for setting the property value
+     * @return the created statement
+     */
+    protected Statement createConstrainedStatement(PropertyNode propertyNode, Expression fieldExpression) {
+        return stmt(callThisX("fireVetoableChange", args(constX(propertyNode.getName()), fieldExpression, varX("value"))));
+    }
+
+    /**
+     * Creates a statement body similar to:
+     * <code>field = value</code>.
+     * <p>
+     * Used when the field is not also {@code @Bindable}.
+     *
+     * @param fieldExpression a field expression for setting the property value
+     * @return the created statement
+     */
+    protected Statement createSetStatement(Expression fieldExpression) {
+        return assignS(fieldExpression, varX("value"));
+    }
+
+    /**
+     * Snoops through the declaring class and all parents looking for a field
+     * of type VetoableChangeSupport.  Remembers the field and returns false
+     * if found otherwise returns true to indicate that such support should
+     * be added.
+     *
+     * @param declaringClass the class to search
+     * @return true if vetoable change support should be added
+     */
+    protected boolean needsVetoableChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) {
+        boolean foundAdd = false, foundRemove = false, foundFire = false;
+        ClassNode consideredClass = declaringClass;
+        while (consideredClass!= null) {
+            for (MethodNode method : consideredClass.getMethods()) {
+                // just check length, MOP will match it up
+                foundAdd = foundAdd || method.getName().equals("addVetoableChangeListener") && method.getParameters().length == 1;
+                foundRemove = foundRemove || method.getName().equals("removeVetoableChangeListener") && method.getParameters().length == 1;
+                foundFire = foundFire || method.getName().equals("fireVetoableChange") && method.getParameters().length == 3;
+                if (foundAdd && foundRemove && foundFire) {
+                    return false;
+                }
+            }
+            consideredClass = consideredClass.getSuperClass();
+        }
+        // check if a super class has @Vetoable annotations
+        consideredClass = declaringClass.getSuperClass();
+        while (consideredClass!=null) {
+            if (hasVetoableAnnotation(consideredClass)) return false;
+            for (FieldNode field : consideredClass.getFields()) {
+                if (hasVetoableAnnotation(field)) return false;
+            }
+            consideredClass = consideredClass.getSuperClass();
+        }
+        if (foundAdd || foundRemove || foundFire) {
+            sourceUnit.getErrorCollector().addErrorAndContinue(
+                new SimpleMessage("@Vetoable cannot be processed on "
+                    + declaringClass.getName()
+                    + " because some but not all of addVetoableChangeListener, removeVetoableChange, and fireVetoableChange were declared in the current or super classes.",
+                sourceUnit)
+            );
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Creates a setter method with the given body.
+     * <p>
+     * This differs from normal setters in that we need to add a declared
+     * exception java.beans.PropertyVetoException
+     *
+     * @param declaringClass the class to which we will add the setter
+     * @param propertyNode          the field to back the setter
+     * @param setterName     the name of the setter
+     * @param setterBlock    the statement representing the setter block
+     */
+    protected void createSetterMethod(ClassNode declaringClass, PropertyNode propertyNode, String setterName, Statement setterBlock) {
+        ClassNode[] exceptions = {ClassHelper.make(PropertyVetoException.class)};
+        MethodNode setter = new MethodNode(
+                setterName,
+                PropertyNodeUtils.adjustPropertyModifiersForMethod(propertyNode),
+                ClassHelper.VOID_TYPE,
+                params(param(propertyNode.getType(), "value")),
+                exceptions,
+                setterBlock);
+        setter.setSynthetic(true);
+        // add it to the class
+        declaringClass.addMethod(setter);
+    }
+
+    /**
+     * Adds the necessary field and methods to support vetoable change support.
+     * <p>
+     * Adds a new field:
+     * <code>"protected final java.beans.VetoableChangeSupport this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)"</code>
+     * <p>
+     * Also adds support methods:
+     * <code>public void addVetoableChangeListener(java.beans.VetoableChangeListener)</code>
+     * <code>public void addVetoableChangeListener(String, java.beans.VetoableChangeListener)</code>
+     * <code>public void removeVetoableChangeListener(java.beans.VetoableChangeListener)</code>
+     * <code>public void removeVetoableChangeListener(String, java.beans.VetoableChangeListener)</code>
+     * <code>public java.beans.VetoableChangeListener[] getVetoableChangeListeners()</code>
+     *
+     * @param declaringClass the class to which we add the support field and methods
+     */
+    protected void addVetoableChangeSupport(ClassNode declaringClass) {
+        ClassNode vcsClassNode = ClassHelper.make(VetoableChangeSupport.class);
+        ClassNode vclClassNode = ClassHelper.make(VetoableChangeListener.class);
+
+        // add field:
+        // protected static VetoableChangeSupport this$vetoableChangeSupport = new java.beans.VetoableChangeSupport(this)
+        FieldNode vcsField = declaringClass.addField(
+                "this$vetoableChangeSupport",
+                ACC_FINAL | ACC_PRIVATE | ACC_SYNTHETIC,
+                vcsClassNode,
+                ctorX(vcsClassNode, args(varX("this"))));
+
+        // add method:
+        // void addVetoableChangeListener(listener) {
+        //     this$vetoableChangeSupport.addVetoableChangeListener(listener)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "addVetoableChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(vclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(vcsField), "addVetoableChangeListener", args(varX("listener", vclClassNode))))));
+
+        // add method:
+        // void addVetoableChangeListener(name, listener) {
+        //     this$vetoableChangeSupport.addVetoableChangeListener(name, listener)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "addVetoableChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(vclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(vcsField), "addVetoableChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", vclClassNode))))));
+
+        // add method:
+        // boolean removeVetoableChangeListener(listener) {
+        //    return this$vetoableChangeSupport.removeVetoableChangeListener(listener);
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "removeVetoableChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(vclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(vcsField), "removeVetoableChangeListener", args(varX("listener", vclClassNode))))));
+
+        // add method: void removeVetoableChangeListener(name, listener)
+        declaringClass.addMethod(
+                new MethodNode(
+                        "removeVetoableChangeListener",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(vclClassNode, "listener")),
+                        ClassNode.EMPTY_ARRAY,
+                        stmt(callX(fieldX(vcsField), "removeVetoableChangeListener", args(varX("name", ClassHelper.STRING_TYPE), varX("listener", vclClassNode))))));
+
+        // add method:
+        // void fireVetoableChange(String name, Object oldValue, Object newValue)
+        //    throws PropertyVetoException
+        // {
+        //     this$vetoableChangeSupport.fireVetoableChange(name, oldValue, newValue)
+        //  }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "fireVetoableChange",
+                        ACC_PUBLIC,
+                        ClassHelper.VOID_TYPE,
+                        params(param(ClassHelper.STRING_TYPE, "name"), param(ClassHelper.OBJECT_TYPE, "oldValue"), param(ClassHelper.OBJECT_TYPE, "newValue")),
+                        new ClassNode[] {ClassHelper.make(PropertyVetoException.class)},
+                        stmt(callX(fieldX(vcsField), "fireVetoableChange", args(varX("name", ClassHelper.STRING_TYPE), varX("oldValue"), varX("newValue"))))));
+
+        // add method:
+        // VetoableChangeListener[] getVetoableChangeListeners() {
+        //   return this$vetoableChangeSupport.getVetoableChangeListeners
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "getVetoableChangeListeners",
+                        ACC_PUBLIC,
+                        vclClassNode.makeArray(),
+                        Parameter.EMPTY_ARRAY,
+                        ClassNode.EMPTY_ARRAY,
+                        returnS(callX(fieldX(vcsField), "getVetoableChangeListeners"))));
+
+        // add method:
+        // VetoableChangeListener[] getVetoableChangeListeners(String name) {
+        //   return this$vetoableChangeSupport.getVetoableChangeListeners(name)
+        // }
+        declaringClass.addMethod(
+                new MethodNode(
+                        "getVetoableChangeListeners",
+                        ACC_PUBLIC,
+                        vclClassNode.makeArray(),
+                        params(param(ClassHelper.STRING_TYPE, "name")),
+                        ClassNode.EMPTY_ARRAY,
+                        returnS(callX(fieldX(vcsField), "getVetoableChangeListeners", args(varX("name", ClassHelper.STRING_TYPE))))));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/CliBuilderException.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/CliBuilderException.groovy b/src/main/groovy/groovy/cli/CliBuilderException.groovy
new file mode 100644
index 0000000..84a9438
--- /dev/null
+++ b/src/main/groovy/groovy/cli/CliBuilderException.groovy
@@ -0,0 +1,24 @@
+/*
+ *  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 groovy.cli
+
+import groovy.transform.InheritConstructors
+
+@InheritConstructors
+class CliBuilderException extends RuntimeException { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/Option.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/Option.java b/src/main/groovy/groovy/cli/Option.java
new file mode 100644
index 0000000..9b48861
--- /dev/null
+++ b/src/main/groovy/groovy/cli/Option.java
@@ -0,0 +1,105 @@
+/*
+ *  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 groovy.cli;
+
+import groovy.transform.Undefined;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a method or property can be used to set a CLI option.
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.FIELD})
+public @interface Option {
+    /**
+     * The description of this option
+     *
+     * @return the description of this option
+     */
+    String description() default "";
+
+    /**
+     * The short name of this option. Defaults to the name of member being annotated if the longName is empty.
+     *
+     * @return the short name of this option
+     */
+    String shortName() default "";
+
+    /**
+     * The long name of this option. Defaults to the name of member being annotated.
+     *
+     * @return the long name of this option
+     */
+    String longName() default "";
+
+    /**
+     * The value separator for this multi-valued option. Only allowed for array-typed arguments.
+     *
+     * @return the value separator for this multi-valued option
+     */
+    String valueSeparator() default "";
+
+    /**
+     * Whether this option can have an optional argument.
+     * Only supported for array-typed arguments to indicate that the array may be empty.
+     *
+     * @return true if this array-typed option can have an optional argument (i.e. could be empty)
+     */
+    boolean optionalArg() default false;
+
+    /**
+     * How many arguments this option has.
+     * A value greater than 1 is only allowed for array-typed arguments.
+     * Ignored for boolean options which are assumed to have a default of 0
+     * or if {@code numberOfArgumentsString} is set.
+     *
+     * @return the number of arguments
+     */
+    int numberOfArguments() default 1;
+
+    /**
+     * How many arguments this option has represented as a String.
+     * Only allowed for array-typed arguments.
+     * Overrides {@code numberOfArguments} if set.
+     * The special values of '+' means one or more and '*' as 0 or more.
+     *
+     * @return the number of arguments (as a String)
+     */
+    String numberOfArgumentsString() default "";
+
+    /**
+     * The default value for this option as a String; subject to type conversion and 'convert'.
+     * Ignored for Boolean options.
+     *
+     * @return the default value for this option
+     */
+    String defaultValue() default "";
+
+    /**
+     * A conversion closure to convert the incoming String into the desired object
+     *
+     * @return the closure to convert this option's argument(s)
+     */
+    Class convert() default Undefined.CLASS.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/cli/OptionField.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/cli/OptionField.groovy b/src/main/groovy/groovy/cli/OptionField.groovy
new file mode 100644
index 0000000..69cc1f5
--- /dev/null
+++ b/src/main/groovy/groovy/cli/OptionField.groovy
@@ -0,0 +1,27 @@
+/*
+ *  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 groovy.cli
+
+import groovy.transform.AnnotationCollector
+import groovy.transform.Field
+
+@Option
+@Field
+@AnnotationCollector
+@interface OptionField { }
\ No newline at end of file


[06/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/ClosureSignatureHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/ClosureSignatureHint.java b/src/main/groovy/transform/stc/ClosureSignatureHint.java
deleted file mode 100644
index 9a77d20..0000000
--- a/src/main/groovy/transform/stc/ClosureSignatureHint.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.GenericsType;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.List;
-
-/**
- * <p>A closure signature hint class is always used in conjunction with the {@link ClosureParams} annotation. It is
- * called at compile time (or may be used by IDEs) to infer the types of the parameters of a {@link groovy.lang.Closure}.</p>
-
- * <p>A closure hint class is responsible for generating the list of arguments that a closure accepts. Since closures
- * may accept several signatures, {@link #getClosureSignatures(org.codehaus.groovy.ast.MethodNode, org.codehaus.groovy.control.SourceUnit, org.codehaus.groovy.control.CompilationUnit, String[], org.codehaus.groovy.ast.ASTNode)} should
- * return a list.</p>
- *
- * <p>Whenever the type checker encounters a method call that targets a method accepting a closure, it will search
- * for the {@link ClosureParams} annotation on the {@link groovy.lang.Closure} argument. If it is found, then it
- * creates an instance of the hint class and calls the {@link #getClosureSignatures(org.codehaus.groovy.ast.MethodNode, org.codehaus.groovy.control.SourceUnit, org.codehaus.groovy.control.CompilationUnit, String[], org.codehaus.groovy.ast.ASTNode)}
- * method, which will in turn return the list of signatures.</p>
- *
- * <p><i>Note that the signature concept here is used only to describe the parameter types, not the result type, which
- * is found in the generic type argument of the {@link groovy.lang.Closure} class.</i></p>
- *
- * <p>Several predefined hints can be found, which should cover most of the use cases.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- *
- */
-public abstract class ClosureSignatureHint {
-
-    /**
-     * A helper method which will extract the n-th generic type from a class node.
-     * @param type the class node from which to pick a generic type
-     * @param gtIndex the index of the generic type to extract
-     * @return the n-th generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
-     */
-    public static ClassNode pickGenericType(ClassNode type, int gtIndex) {
-        final GenericsType[] genericsTypes = type.getGenericsTypes();
-        if (genericsTypes==null || genericsTypes.length<gtIndex) {
-            return ClassHelper.OBJECT_TYPE;
-        }
-        return genericsTypes[gtIndex].getType();
-    }
-
-    /**
-     * A helper method which will extract the n-th generic type from the n-th parameter of a method node.
-     * @param node the method node from which the generic type should be picked
-     * @param parameterIndex the index of the parameter in the method parameter list
-     * @param gtIndex the index of the generic type to extract
-     * @return the generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
-     */
-    public static ClassNode pickGenericType(MethodNode node, int parameterIndex, int gtIndex) {
-        final Parameter[] parameters = node.getParameters();
-        final ClassNode type = parameters[parameterIndex].getOriginType();
-        return pickGenericType(type, gtIndex);
-    }
-
-    /**
-     * <p>Subclasses should implement this method, which returns the list of accepted closure signatures.</p>
-     *
-     * <p>The compiler will call this method each time, in a source file, a method call using a closure
-     * literal is encountered and that the target method has the corresponding {@link groovy.lang.Closure} parameter
-     * annotated with {@link groovy.transform.stc.ClosureParams}. So imagine the following code needs to be compiled:</p>
-     *
-     * <code>@groovy.transform.TypeChecked
-     * void doSomething() {
-     *     println ['a','b'].collect { it.toUpperCase() }
-     * }</code>
-     *
-     * <p>The <i>collect</i> method accepts a closure, but normally, the type checker doesn't have enough type information
-     * in the sole {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#collect(java.util.Collection, groovy.lang.Closure)} method
-     * signature to infer the type of <i>it</i>. With the annotation, it will now try to find an annotation on the closure parameter.
-     * If it finds it, then an instance of the hint class is created and the type checker calls it with the following arguments:</p>
-     * <ul>
-     *     <li>the method node corresponding to the target method (here, the {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#collect(java.util.Collection, groovy.lang.Closure)} method</li>
-     *     <li>the (optional) list of options found in the annotation</li>
-     * </ul>
-     *
-     * <p>Now, the hint instance can return the list of expected parameters. Here, it would have to say that the collect method accepts
-     * a closure for which the only argument is of the type of the first generic type of the first argument.</p>
-     * <p>With that type information, the type checker can now infer that the type of <i>it</i> is <i>String</i>, because the first argument (here the receiver of the collect method)
-     * is a <i>List&lt;String&gt;</i></p>
-     *
-     * <p></p>
-     *
-     * <p>Subclasses are therefore expected to return the signatures according to the available context, which is only the target method and the potential options.</p>
-     *
-     *
-     * @param node the method node for which a {@link groovy.lang.Closure} parameter was annotated with
-     *             {@link ClosureParams}
-     * @param sourceUnit the source unit of the file being compiled
-     * @param compilationUnit the compilation unit of the file being compiled
-     * @param options the options, corresponding to the {@link ClosureParams#options()} found on the annotation  @return a non-null list of signature, where a signature corresponds to an array of class nodes, each of them matching a parameter.
-     * @param usage the AST node, in the compiled file, which triggered a call to this method. Normally only used for logging/error handling
-     */
-    public abstract List<ClassNode[]> getClosureSignatures(MethodNode node, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options, ASTNode usage);
-
-    /**
-     * Finds a class node given a string representing the type. Performs a lookup in the compilation unit to check if it is done in the same source unit.
-     * @param sourceUnit source unit
-     * @param compilationUnit compilation unit
-     * @param className the name of the class we want to get a {@link org.codehaus.groovy.ast.ClassNode} for
-     * @return a ClassNode representing the type
-     */
-    protected ClassNode findClassNode(final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String className) {
-        if (className.endsWith("[]")) {
-            return findClassNode(sourceUnit, compilationUnit, className.substring(0, className.length() - 2)).makeArray();
-        }
-        ClassNode cn = compilationUnit.getClassNode(className);
-        if (cn == null) {
-            try {
-                cn = ClassHelper.make(Class.forName(className, false, sourceUnit.getClassLoader()));
-            } catch (ClassNotFoundException e) {
-                cn = ClassHelper.make(className);
-            }
-        }
-        return cn;
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/FirstParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/FirstParam.java b/src/main/groovy/transform/stc/FirstParam.java
deleted file mode 100644
index 81eb0e7..0000000
--- a/src/main/groovy/transform/stc/FirstParam.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-/**
- * <p>A hint used to instruct the type checker to pick the first parameter type. For example:</p>
- * <code>public &lt;T&gt; def doWith(T src, @ClosureParams(FirstParam.class) Closure c) { c.call(src); }</code>
- *
- * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class FirstParam extends PickAnyArgumentHint {
-    public FirstParam() {
-        super(0,-1);
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the first generic type of the first parameter type. For example:</p>
-     * <code>void &lt;T&gt; doWithElements(List&lt;T&gt; src, @ClosureParams(FirstParam.FirstGenericType.class) Closure c) { src.each { c.call(it) } }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class FirstGenericType extends PickAnyArgumentHint {
-        public FirstGenericType() {
-            super(0,0);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the second generic type of the first parameter type. For example:</p>
-     * <code>void &lt;T,U&gt; doWithElements(Tuple&lt;T,U&gt; src, @ClosureParams(FirstParam.SecondGenericType.class) Closure c) { src.each { c.call(it) } }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class SecondGenericType extends PickAnyArgumentHint {
-        public SecondGenericType() {
-            super(0,1);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the third generic type of the first parameter type. For example:</p>
-     * <code>void &lt;T,U,V&gt; doWithElements(Triple&lt;T,U,V&gt; src, @ClosureParams(FirstParam.ThirdGenericType.class) Closure c) { src.each { c.call(it) } }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class ThirdGenericType extends PickAnyArgumentHint {
-        public ThirdGenericType() {
-            super(0,2);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the type of the component of the first parameter type, which is therefore
-     * expected to be an array, like in this example:</p>
-     * <code>void &lt;T&gt; doWithArray(T[] array, @ClosureParams(FirstParam.Component.class) Closure c) { array.each { c.call(it)} }</code>
-     */
-    public static class Component extends FirstParam {
-        @Override
-        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
-            parameterTypes[0] = parameterTypes[0].getComponentType();
-            return parameterTypes;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/FromAbstractTypeMethods.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/FromAbstractTypeMethods.java b/src/main/groovy/transform/stc/FromAbstractTypeMethods.java
deleted file mode 100644
index e5125f1..0000000
--- a/src/main/groovy/transform/stc/FromAbstractTypeMethods.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.transform.trait.Traits;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * This signature hint uses abstract methods from some type (abstract class or interface) in order
- * to infer the expected parameter types. This is especially useful for closure parameter type
- * inference when implicit closure coercion is in action.
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class FromAbstractTypeMethods extends ClosureSignatureHint {
-    @Override
-    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
-        String className = options[0];
-        ClassNode cn = findClassNode(sourceUnit, compilationUnit, className);
-        return extractSignaturesFromMethods(cn);
-    }
-
-    private static List<ClassNode[]> extractSignaturesFromMethods(final ClassNode cn) {
-        List<MethodNode> methods = cn.getAllDeclaredMethods();
-        List<ClassNode[]> signatures = new LinkedList<ClassNode[]>();
-        for (MethodNode method : methods) {
-            if (!method.isSynthetic() && method.isAbstract()) {
-                extractParametersFromMethod(signatures, method);
-            }
-        }
-        return signatures;
-    }
-
-    private static void extractParametersFromMethod(final List<ClassNode[]> signatures, final MethodNode method) {
-        if (Traits.hasDefaultImplementation(method)) return;
-        Parameter[] parameters = method.getParameters();
-        ClassNode[] typeParams = new ClassNode[parameters.length];
-        for (int i = 0; i < parameters.length; i++) {
-            typeParams[i] = parameters[i].getOriginType();
-        }
-        signatures.add(typeParams);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/FromString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/FromString.java b/src/main/groovy/transform/stc/FromString.java
deleted file mode 100644
index 12f9371..0000000
--- a/src/main/groovy/transform/stc/FromString.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.tools.GenericsUtils;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * <p>A closure parameter hint class that is convenient if you want to use a String representation
- * of the signature. It makes use of the {@link ClosureParams#options() option strings}, where
- * each string corresponds to a single signature.</p>
- *
- * <p>The following example describes a closure as accepting a single signature (List&lt;T&gt; list -&gt;):</p>
- *
- * <code>public &lt;T&gt; T apply(T src, @ClosureParams(value=FromString.class, options="List&lt;T&gt;" Closure&lt;T&gt; cl)</code>
- *
- * <p>The next example describes a closure as accepting two signatures (List&lt;T&gt; list -&gt;) and (T t -&gt;):</p>
- *
- * <code>public &lt;T&gt; T apply(T src, @ClosureParams(value=FromString.class, options={"List&lt;T&gt;","T"} Closure&lt;T&gt; cl)</code>
- *
- * <p>It is advisable not to use this hint as a replacement for the various {@link FirstParam}, {@link SimpleType},
- * ... hints because it is actually much slower. Using this hint should therefore be limited
- * to cases where it's not possible to express the signature using the existing hints.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class FromString extends ClosureSignatureHint {
-
-    @Override
-    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
-        List<ClassNode[]> list = new ArrayList<ClassNode[]>(options.length);
-        for (String option : options) {
-            list.add(parseOption(option, sourceUnit, compilationUnit, node, usage));
-        }
-        return list;
-    }
-
-    /**
-     * Parses a string representing a type, that must be aligned with the current context.
-     * For example, <i>"List&lt;T&gt;"</i> must be converted into the appropriate ClassNode
-     * for which <i>T</i> matches the appropriate placeholder.
-     *
-     *
-     * @param option a string representing a type
-     * @param sourceUnit the source unit (of the file being compiled)
-     * @param compilationUnit the compilation unit (of the file being compiled)
-     * @param mn the method node
-     * @param usage
-     * @return a class node if it could be parsed and resolved, null otherwise
-     */
-    private static ClassNode[] parseOption(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) {
-        return GenericsUtils.parseClassNodesFromString(option, sourceUnit, compilationUnit, mn, usage);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/IncorrectTypeHintException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/IncorrectTypeHintException.java b/src/main/groovy/transform/stc/IncorrectTypeHintException.java
deleted file mode 100644
index aed167a..0000000
--- a/src/main/groovy/transform/stc/IncorrectTypeHintException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.syntax.SyntaxException;
-
-public class IncorrectTypeHintException extends SyntaxException {
-    public IncorrectTypeHintException(final MethodNode mn, final Throwable e, int line, int column) {
-        super("Incorrect type hint in @ClosureParams in class "+mn.getDeclaringClass().getName()+" method "+mn.getTypeDescriptor()+" : "+e.getMessage(), e, line, column);
-    }
-
-    public IncorrectTypeHintException(final MethodNode mn, final String msg, final int line, final int column) {
-        super("Incorrect type hint in @ClosureParams in class "+mn.getDeclaringClass().getName()+" method "+mn.getTypeDescriptor()+" : "+msg, line, column);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/MapEntryOrKeyValue.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/MapEntryOrKeyValue.java b/src/main/groovy/transform/stc/MapEntryOrKeyValue.java
deleted file mode 100644
index 9316ef8..0000000
--- a/src/main/groovy/transform/stc/MapEntryOrKeyValue.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.GenericsType;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * <p>A special hint which handles a common use case in the Groovy methods that work on maps. In case of an
- * iteration on a list of map entries, you often want the user to be able to work either on a {@link java.util.Map.Entry} map entry
- * or on a key,value pair.</p>
- * <p>The result is a closure which can have the following forms:</p>
- * <ul>
- *     <li><code>{ key, value -> ...}</code> where key is the key of a map entry, and value the corresponding value</li>
- *     <li><code>{ entry -> ... }</code> where entry is a {@link java.util.Map.Entry} map entry</li>
- *     <li><code>{ ...}</code> where <i>it</i> is an implicit {@link java.util.Map.Entry} map entry</li>
- * </ul>
- * <p>This hint handles all those cases by picking the generics from the first argument of the method (by default).</p>
- * <p>The options array is used to modify the behavior of this hint. Each string in the option array consists of
- * a key=value pair.</p>
- * <ul>
- *     <li><i>argNum=index</i> of the parameter representing the map (by default, 0)</li>
- *     <li><i>index=true or false</i>, by default false. If true, then an additional "int" parameter is added,
- *     for "withIndex" variants</li>
- * </ul>
- * <code>void doSomething(String str, Map&lt;K,&gt;V map, @ClosureParams(value=MapEntryOrKeyValue.class,options="argNum=1") Closure c) { ... }</code>
- */
-public class MapEntryOrKeyValue extends ClosureSignatureHint {
-    private static final ClassNode MAPENTRY_TYPE = ClassHelper.make(Map.Entry.class);
-
-    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
-        Options opt;
-        try {
-            opt = Options.parse(node, usage, options);
-        } catch (IncorrectTypeHintException e) {
-            sourceUnit.addError(e);
-            return Collections.emptyList();
-        }
-        GenericsType[] genericsTypes = node.getParameters()[opt.parameterIndex].getOriginType().getGenericsTypes();
-        if (genericsTypes==null) {
-            // would happen if you have a raw Map type for example
-            genericsTypes = new GenericsType[] {
-                new GenericsType(ClassHelper.OBJECT_TYPE),
-                new GenericsType(ClassHelper.OBJECT_TYPE)
-            };
-        }
-        ClassNode[] firstSig;
-        ClassNode[] secondSig;
-        ClassNode mapEntry = MAPENTRY_TYPE.getPlainNodeReference();
-        mapEntry.setGenericsTypes(genericsTypes);
-        if (opt.generateIndex) {
-            firstSig = new ClassNode[] {genericsTypes[0].getType(), genericsTypes[1].getType(), ClassHelper.int_TYPE};
-            secondSig = new ClassNode[] {mapEntry, ClassHelper.int_TYPE};
-
-        } else {
-            firstSig = new ClassNode[] {genericsTypes[0].getType(), genericsTypes[1].getType()};
-            secondSig = new ClassNode[] {mapEntry};
-        }
-        return Arrays.asList(firstSig, secondSig);
-    }
-    
-    private static final class Options {
-        final int parameterIndex;
-        final boolean generateIndex;
-
-        private Options(final int parameterIndex, final boolean generateIndex) {
-            this.parameterIndex = parameterIndex;
-            this.generateIndex = generateIndex;
-        }
-        
-        static Options parse(MethodNode mn, ASTNode source, String[] options) throws IncorrectTypeHintException {
-            int pIndex = 0;
-            boolean generateIndex = false;
-            for (String option : options) {
-                String[] keyValue = option.split("=");
-                if (keyValue.length==2) {
-                    String key = keyValue[0];
-                    String value = keyValue[1];
-                    if ("argNum".equals(key)) {
-                        pIndex = Integer.parseInt(value);
-                    } else if ("index".equals(key)) {
-                        generateIndex = Boolean.valueOf(value);
-                    } else {
-                        throw new IncorrectTypeHintException(mn, "Unrecognized option: "+key, source.getLineNumber(), source.getColumnNumber());
-                    }
-                } else {
-                    throw new IncorrectTypeHintException(mn, "Incorrect option format. Should be argNum=<num> or index=<boolean> ", source.getLineNumber(), source.getColumnNumber());
-                }
-            }
-            return new Options(pIndex, generateIndex);
-        }
-    } 
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/PickAnyArgumentHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/PickAnyArgumentHint.java b/src/main/groovy/transform/stc/PickAnyArgumentHint.java
deleted file mode 100644
index 6a5463f..0000000
--- a/src/main/groovy/transform/stc/PickAnyArgumentHint.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-/**
- * <p>Base class for hints which use the type of a parameter of the annotated method as the signature.
- * This can optionally use a generic type of the selected parameter as the hint. For example, imagine the following
- * method:</p>
- * <code>void foo(A firstArg, B secondArg, Closure c) {...}</code>
- * <p>If the <i>c</i> closure should be <code>{ B it -> ...}</code>, then we can see that the parameter type
- * should be picked from the second parameter of the foo method, which is what {@link groovy.transform.stc.PickAnyArgumentHint}
- * lets you do.</p>
- * <p>Alternatively, the method may look like this:</p>
- * <code>void &lt;T&gt; foo(A&lt;T&gt; firstArg, B secondArg, Closure c) {...}</code>
- * <p>in which case if you want to express the fact that <i>c</i> should accept a &lt;T&gt; then you can use the
- * {@link #genericTypeIndex} value.</p>
- * <p></p>
- * <p>This class is extended by several hint providers that make it easier to use as annotation values.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class PickAnyArgumentHint extends SingleSignatureClosureHint {
-    private final int parameterIndex;
-    private final int genericTypeIndex;
-
-    /**
-     * Creates the an argument picker which extracts the type of the first parameter.
-     */
-    public PickAnyArgumentHint() {
-        this(0,-1);
-    }
-
-    /**
-     * Creates a picker which will extract the parameterIndex-th parameter type, or its
-     * genericTypeIndex-th generic type genericTypeIndex is &gt;=0.
-     * @param parameterIndex the index of the parameter from which to extract the type
-     * @param genericTypeIndex if &gt;=0, then returns the corresponding generic type instead of the parameter type.
-     */
-    public PickAnyArgumentHint(final int parameterIndex, final int genericTypeIndex) {
-        this.parameterIndex = parameterIndex;
-        this.genericTypeIndex = genericTypeIndex;
-    }
-
-    @Override
-    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-        ClassNode type = node.getParameters()[parameterIndex].getOriginType();
-        if (genericTypeIndex>=0) {
-            type = pickGenericType(type, genericTypeIndex);
-        }
-        return new ClassNode[]{type};
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/PickFirstResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/PickFirstResolver.java b/src/main/groovy/transform/stc/PickFirstResolver.java
deleted file mode 100644
index 0bebb3e..0000000
--- a/src/main/groovy/transform/stc/PickFirstResolver.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Returns the first of several candidates found.
- * This is useful if several types should be supported but only the first
- * should be the default/inferred type. Other options in the list are
- * obtained through explicitly typing the parameter(s).
- *
- * @since 2.5.0
- */
-public class PickFirstResolver extends ClosureSignatureConflictResolver {
-    @Override
-    public List<ClassNode[]> resolve(List<ClassNode[]> candidates, ClassNode receiver, Expression arguments, ClosureExpression closure,
-                                     MethodNode methodNode, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options) {
-        return Collections.singletonList(candidates.get(0));
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/SecondParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/SecondParam.java b/src/main/groovy/transform/stc/SecondParam.java
deleted file mode 100644
index c077750..0000000
--- a/src/main/groovy/transform/stc/SecondParam.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-/**
- * <p>A hint used to instruct the type checker to pick the second parameter type. For example:</p>
- * <code>public &lt;T,U&gt; def doWith(T first, U second, @ClosureParams(SecondParam.class) Closure c) { c.call(src); }</code>
- *
- * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class SecondParam extends PickAnyArgumentHint {
-    public SecondParam() {
-        super(1,-1);
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the first generic type of the second parameter type. For example:</p>
-     * <code>void &lt;T&gt; doWithElements(String base, List&lt;T&gt; src, @ClosureParams(SecondParam.FirstGenericType.class) Closure c) { ... } }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class FirstGenericType extends PickAnyArgumentHint {
-        public FirstGenericType() {
-            super(1,0);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the second generic type of the second parameter type. For example:</p>
-     * <code>void &lt;T,U&gt; doWithElements(String base, Tuple&lt;T,U&gt; src, @ClosureParams(SecondParam.SecondGenericType.class) Closure c) { ... }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class SecondGenericType extends PickAnyArgumentHint {
-        public SecondGenericType() {
-            super(1,1);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the second generic type of the second parameter type. For example:</p>
-     * <code>void &lt;T,U,V&gt; doWithElements(String base, Triple&lt;T,U,V&gt; src, @ClosureParams(SecondParam.ThirdGenericType.class) Closure c) { ... }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class ThirdGenericType extends PickAnyArgumentHint {
-        public ThirdGenericType() {
-            super(1,2);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the type of the component of the second parameter type, which is therefore
-     * expected to be an array, like in this example:</p>
-     * <code>void &lt;T&gt; doWithArray(String first, T[] array, @ClosureParams(FirstParam.Component.class) Closure c) { ... }</code>
-     */
-    public static class Component extends SecondParam {
-        @Override
-        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
-            parameterTypes[0] = parameterTypes[0].getComponentType();
-            return parameterTypes;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/SimpleType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/SimpleType.java b/src/main/groovy/transform/stc/SimpleType.java
deleted file mode 100644
index 8866e3b..0000000
--- a/src/main/groovy/transform/stc/SimpleType.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-public class SimpleType extends SingleSignatureClosureHint {
-    @Override
-    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-        ClassNode[] result = new ClassNode[options.length];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = findClassNode(sourceUnit, unit, options[i]);
-        }
-        return result;
-    }
- }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/SingleSignatureClosureHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/SingleSignatureClosureHint.java b/src/main/groovy/transform/stc/SingleSignatureClosureHint.java
deleted file mode 100644
index 3db66ff..0000000
--- a/src/main/groovy/transform/stc/SingleSignatureClosureHint.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A simplified version of a {@link groovy.transform.stc.ClosureSignatureHint} which is suitable
- * for monomorphic closures, that is to say closures which only respond to a single signature.
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public abstract class SingleSignatureClosureHint extends ClosureSignatureHint {
-
-    public abstract ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage);
-
-    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
-        return Collections.singletonList(getParameterTypes(node, options, sourceUnit, compilationUnit, usage));
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/transform/stc/ThirdParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/stc/ThirdParam.java b/src/main/groovy/transform/stc/ThirdParam.java
deleted file mode 100644
index c493e36..0000000
--- a/src/main/groovy/transform/stc/ThirdParam.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *  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 groovy.transform.stc;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.SourceUnit;
-
-/**
- * <p>A hint used to instruct the type checker to pick the third parameter type. For example:</p>
- * <code>public &lt;T,U,V&gt; def doWith(T first, U second, V third, @ClosureParams(ThirdParam.class) Closure c) { ... }</code>
- *
- * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
- *
- * @author Cédric Champeau
- * @since 2.3.0
- */
-public class ThirdParam extends PickAnyArgumentHint {
-    public ThirdParam() {
-        super(2,-1);
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the first generic type of the third parameter type. For example:</p>
-     * <code>void &lt;T&gt; doWithElements(String first, Integer second, List&lt;T&gt; third, @ClosureParams(SecondParam.FirstGenericType.class) Closure c) { ... } }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class FirstGenericType extends PickAnyArgumentHint {
-        public FirstGenericType() {
-            super(2,0);
-        }
-    }
-
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the second generic type of the third parameter type. For example:</p>
-     * <code>void &lt;T,U&gt; doWithElements(String first, Integer second, Tuple&lt;T,U&gt; third, @ClosureParams(SecondParam.SecondGenericType.class) Closure c) { ... }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class SecondGenericType extends PickAnyArgumentHint {
-        public SecondGenericType() {
-            super(2,1);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the second generic type of the third parameter type. For example:</p>
-     * <code>void &lt;T,U,V&gt; doWithElements(String first, Integer second, Triple&lt;T,U,V&gt; src, @ClosureParams(SecondParam.ThirdGenericType.class) Closure c) { ... }</code>
-     *
-     * @author Cédric Champeau
-     * @since 2.3.0
-     */
-    public static class ThirdGenericType extends PickAnyArgumentHint {
-        public ThirdGenericType() {
-            super(2,2);
-        }
-    }
-
-    /**
-     * <p>A hint used to instruct the type checker to pick the type of the component of the third parameter type, which is therefore
-     * expected to be an array, like in this example:</p>
-     * <code>void &lt;T&gt; doWithArray(String first, int second, T[] third, @ClosureParams(FirstParam.Component.class) Closure c) { ... }</code>
-     */
-    public static class Component extends ThirdParam {
-        @Override
-        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
-            parameterTypes[0] = parameterTypes[0].getComponentType();
-            return parameterTypes;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ui/GroovyMain.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/ui/GroovyMain.java b/src/main/groovy/ui/GroovyMain.java
deleted file mode 100644
index cedb8fb..0000000
--- a/src/main/groovy/ui/GroovyMain.java
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- *  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 groovy.ui;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyCodeSource;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.GroovyShell;
-import groovy.lang.GroovySystem;
-import groovy.lang.MissingMethodException;
-import groovy.lang.Script;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.control.customizers.ImportCustomizer;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-import org.codehaus.groovy.runtime.ResourceGroovyMethods;
-import org.codehaus.groovy.runtime.StackTraceUtils;
-import org.codehaus.groovy.runtime.StringGroovyMethods;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.math.BigInteger;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
-import java.util.regex.Pattern;
-
-import static org.apache.commons.cli.Option.builder;
-
-/**
- * A Command line to execute groovy.
- */
-public class GroovyMain {
-
-    // arguments to the script
-    private List args;
-
-    // is this a file on disk
-    private boolean isScriptFile;
-
-    // filename or content of script
-    private String script;
-
-    // process args as input files
-    private boolean processFiles;
-
-    // edit input files in place
-    private boolean editFiles;
-
-    // automatically output the result of each script
-    private boolean autoOutput;
-
-    // automatically split each line using the splitpattern
-    private boolean autoSplit;
-
-    // The pattern used to split the current line
-    private String splitPattern = " ";
-
-    // process sockets
-    private boolean processSockets;
-
-    // port to listen on when processing sockets
-    private int port;
-
-    // backup input files with extension
-    private String backupExtension;
-
-    // do you want full stack traces in script exceptions?
-    private boolean debug = false;
-
-    // Compiler configuration, used to set the encodings of the scripts/classes
-    private CompilerConfiguration conf = new CompilerConfiguration(System.getProperties());
-
-    /**
-     * Main CLI interface.
-     *
-     * @param args all command line args.
-     */
-    public static void main(String args[]) {
-        processArgs(args, System.out);
-    }
-
-    // package-level visibility for testing purposes (just usage/errors at this stage)
-    // TODO: should we have an 'err' printstream too for ParseException?
-    static void processArgs(String[] args, final PrintStream out) {
-        Options options = buildOptions();
-
-        try {
-            CommandLine cmd = parseCommandLine(options, args);
-
-            if (cmd.hasOption('h')) {
-                printHelp(out, options);
-            } else if (cmd.hasOption('v')) {
-                String version = GroovySystem.getVersion();
-                out.println("Groovy Version: " + version + " JVM: " + System.getProperty("java.version") + 
-                        " Vendor: " + System.getProperty("java.vm.vendor")  + " OS: " + System.getProperty("os.name"));
-            } else {
-                // If we fail, then exit with an error so scripting frameworks can catch it
-                // TODO: pass printstream(s) down through process
-                if (!process(cmd)) {
-                    System.exit(1);
-                }
-            }
-        } catch (ParseException pe) {
-            out.println("error: " + pe.getMessage());
-            printHelp(out, options);
-        } catch (IOException ioe) {
-            out.println("error: " + ioe.getMessage());
-        }
-    }
-
-    private static void printHelp(PrintStream out, Options options) {
-        HelpFormatter formatter = new HelpFormatter();
-        PrintWriter pw = new PrintWriter(out);
-
-        formatter.printHelp(
-            pw,
-            80,
-            "groovy [options] [filename] [args]",
-            "The Groovy command line processor.\nOptions:",
-            options,
-            2,
-            4,
-            null, // footer
-            false);
-       
-        pw.flush();
-    }
-
-    /**
-     * Parse the command line.
-     *
-     * @param options the options parser.
-     * @param args    the command line args.
-     * @return parsed command line.
-     * @throws ParseException if there was a problem.
-     */
-    private static CommandLine parseCommandLine(Options options, String[] args) throws ParseException {
-        CommandLineParser parser = new DefaultParser();
-        return parser.parse(options, args, true);
-    }
-
-    /**
-     * Build the options parser.
-     *
-     * @return an options parser.
-     */
-    private static Options buildOptions() {
-        return new Options()
-                .addOption(builder("classpath").hasArg().argName("path").desc("Specify where to find the class files - must be first argument").build())
-                .addOption(builder("cp").longOpt("classpath").hasArg().argName("path").desc("Aliases for '-classpath'").build())
-                .addOption(builder("D").longOpt("define").desc("Define a system property").numberOfArgs(2).valueSeparator().argName("name=value").build())
-                .addOption(
-                        builder().longOpt("disableopt")
-                                .desc("Disables one or all optimization elements; " +
-                                        "optlist can be a comma separated list with the elements: " +
-                                        "all (disables all optimizations), " +
-                                        "int (disable any int based optimizations)")
-                                .hasArg().argName("optlist").build())
-                .addOption(builder("h").hasArg(false).desc("Usage information").longOpt("help").build())
-                .addOption(builder("d").hasArg(false).desc("Debug mode will print out full stack traces").longOpt("debug").build())
-                .addOption(builder("v").hasArg(false).desc("Display the Groovy and JVM versions").longOpt("version").build())
-                .addOption(builder("c").argName("charset").hasArg().desc("Specify the encoding of the files").longOpt("encoding").build())
-                .addOption(builder("e").argName("script").hasArg().desc("Specify a command line script").build())
-                .addOption(builder("i").argName("extension").optionalArg(true).desc("Modify files in place; create backup if extension is given (e.g. \'.bak\')").build())
-                .addOption(builder("n").hasArg(false).desc("Process files line by line using implicit 'line' variable").build())
-                .addOption(builder("p").hasArg(false).desc("Process files line by line and print result (see also -n)").build())
-                .addOption(builder("pa").hasArg(false).desc("Generate metadata for reflection on method parameter names (jdk8+ only)").longOpt("parameters").build())
-                .addOption(builder("l").argName("port").optionalArg(true).desc("Listen on a port and process inbound lines (default: 1960)").build())
-                .addOption(builder("a").argName("splitPattern").optionalArg(true).desc("Split lines using splitPattern (default '\\s') using implicit 'split' variable").longOpt("autosplit").build())
-                .addOption(builder().longOpt("indy").desc("Enables compilation using invokedynamic").build())
-                .addOption(builder().longOpt("configscript").hasArg().desc("A script for tweaking the configuration options").build())
-                .addOption(builder("b").longOpt("basescript").hasArg().argName("class").desc("Base class name for scripts (must derive from Script)").build());
-    }
-
-    /**
-     * Process the users request.
-     *
-     * @param line the parsed command line.
-     * @throws ParseException if invalid options are chosen
-     */
-     private static boolean process(CommandLine line) throws ParseException, IOException {
-        List args = line.getArgList();
-        
-        if (line.hasOption('D')) {
-            Properties optionProperties = line.getOptionProperties("D");
-            Enumeration<String> propertyNames = (Enumeration<String>) optionProperties.propertyNames();
-            while (propertyNames.hasMoreElements()) {
-                String nextName = propertyNames.nextElement();
-                System.setProperty(nextName, optionProperties.getProperty(nextName));
-            }
-        }
-
-        GroovyMain main = new GroovyMain();
-        
-        // add the ability to parse scripts with a specified encoding
-        main.conf.setSourceEncoding(line.getOptionValue('c',main.conf.getSourceEncoding()));
-
-        main.isScriptFile = !line.hasOption('e');
-        main.debug = line.hasOption('d');
-        main.conf.setDebug(main.debug);
-        main.conf.setParameters(line.hasOption("pa"));
-        main.processFiles = line.hasOption('p') || line.hasOption('n');
-        main.autoOutput = line.hasOption('p');
-        main.editFiles = line.hasOption('i');
-        if (main.editFiles) {
-            main.backupExtension = line.getOptionValue('i');
-        }
-        main.autoSplit = line.hasOption('a');
-        String sp = line.getOptionValue('a');
-        if (sp != null)
-            main.splitPattern = sp;
-
-        if (main.isScriptFile) {
-            if (args.isEmpty())
-                throw new ParseException("neither -e or filename provided");
-
-            main.script = (String) args.remove(0);
-            if (main.script.endsWith(".java"))
-                throw new ParseException("error: cannot compile file with .java extension: " + main.script);
-        } else {
-            main.script = line.getOptionValue('e');
-        }
-
-        main.processSockets = line.hasOption('l');
-        if (main.processSockets) {
-            String p = line.getOptionValue('l', "1960"); // default port to listen to
-            main.port = Integer.parseInt(p);
-        }
-        
-        // we use "," as default, because then split will create
-        // an empty array if no option is set
-        String disabled = line.getOptionValue("disableopt", ",");
-        String[] deopts = disabled.split(",");
-        for (String deopt_i : deopts) {
-            main.conf.getOptimizationOptions().put(deopt_i,false);
-        }
-        
-        if (line.hasOption("indy")) {
-            CompilerConfiguration.DEFAULT.getOptimizationOptions().put("indy", true);
-            main.conf.getOptimizationOptions().put("indy", true);
-        }
-
-         if (line.hasOption("basescript")) {
-             main.conf.setScriptBaseClass(line.getOptionValue("basescript"));
-         }
-
-        String configScripts = System.getProperty("groovy.starter.configscripts", null);
-        if (line.hasOption("configscript") || (configScripts != null && !configScripts.isEmpty())) {
-            List<String> scripts = new ArrayList<String>();
-            if (line.hasOption("configscript")) {
-                scripts.add(line.getOptionValue("configscript"));
-            }
-            if (configScripts != null) {
-                scripts.addAll(StringGroovyMethods.tokenize((CharSequence) configScripts, ','));
-            }
-            processConfigScripts(scripts, main.conf);
-        }
-
-        main.args = args;
-        return main.run();
-    }
-
-    public static void processConfigScripts(List<String> scripts, CompilerConfiguration conf) throws IOException {
-        if (scripts.isEmpty()) return;
-        Binding binding = new Binding();
-        binding.setVariable("configuration", conf);
-        CompilerConfiguration configuratorConfig = new CompilerConfiguration();
-        ImportCustomizer customizer = new ImportCustomizer();
-        customizer.addStaticStars("org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder");
-        configuratorConfig.addCompilationCustomizers(customizer);
-        GroovyShell shell = new GroovyShell(binding, configuratorConfig);
-        for (String script : scripts) {
-            shell.evaluate(new File(script));
-        }
-    }
-
-
-    /**
-     * Run the script.
-     */
-    private boolean run() {
-        try {
-            if (processSockets) {
-                processSockets();
-            } else if (processFiles) {
-                processFiles();
-            } else {
-                processOnce();
-            }
-            return true;
-        } catch (CompilationFailedException e) {
-            System.err.println(e);
-            return false;
-        } catch (Throwable e) {
-            if (e instanceof InvokerInvocationException) {
-                InvokerInvocationException iie = (InvokerInvocationException) e;
-                e = iie.getCause();
-            }
-            System.err.println("Caught: " + e);
-            if (!debug) {
-                StackTraceUtils.deepSanitize(e);
-            }
-            e.printStackTrace();
-            return false;
-        }
-    }
-
-    /**
-     * Process Sockets.
-     */
-    private void processSockets() throws CompilationFailedException, IOException, URISyntaxException {
-        GroovyShell groovy = new GroovyShell(conf);
-        new GroovySocketServer(groovy, getScriptSource(isScriptFile, script), autoOutput, port);
-    }
-
-    /**
-     * Get the text of the Groovy script at the given location.
-     * If the location is a file path and it does not exist as given,
-     * then {@link GroovyMain#huntForTheScriptFile(String)} is called to try
-     * with some Groovy extensions appended.
-     *
-     * This method is not used to process scripts and is retained for backward
-     * compatibility.  If you want to modify how GroovyMain processes scripts
-     * then use {@link GroovyMain#getScriptSource(boolean, String)}.
-     *
-     * @param uriOrFilename
-     * @return the text content at the location
-     * @throws IOException
-     * @deprecated
-     */
-    @Deprecated
-    public String getText(String uriOrFilename) throws IOException {
-        if (URI_PATTERN.matcher(uriOrFilename).matches()) {
-            try {
-                return ResourceGroovyMethods.getText(new URL(uriOrFilename));
-            } catch (Exception e) {
-                throw new GroovyRuntimeException("Unable to get script from URL: ", e);
-            }
-        }
-        return ResourceGroovyMethods.getText(huntForTheScriptFile(uriOrFilename));
-    }
-
-    /**
-     * Get a new GroovyCodeSource for a script which may be given as a location
-     * (isScript is true) or as text (isScript is false).
-     *
-     * @param isScriptFile indicates whether the script parameter is a location or content
-     * @param script the location or context of the script
-     * @return a new GroovyCodeSource for the given script
-     * @throws IOException
-     * @throws URISyntaxException
-     * @since 2.3.0
-     */
-    protected GroovyCodeSource getScriptSource(boolean isScriptFile, String script) throws IOException, URISyntaxException {
-        //check the script is currently valid before starting a server against the script
-        if (isScriptFile) {
-            // search for the file and if it exists don't try to use URIs ...
-            File scriptFile = huntForTheScriptFile(script);
-            if (!scriptFile.exists() && URI_PATTERN.matcher(script).matches()) {
-                return new GroovyCodeSource(new URI(script));
-            }
-            return new GroovyCodeSource( scriptFile );
-        }
-        return new GroovyCodeSource(script, "script_from_command_line", GroovyShell.DEFAULT_CODE_BASE);
-    }
-
-    // RFC2396
-    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
-    // match URIs but not Windows filenames, e.g.: http://cnn.com but not C:\xxx\file.ext
-    private static final Pattern URI_PATTERN = Pattern.compile("\\p{Alpha}[-+.\\p{Alnum}]*:[^\\\\]*");
-
-    /**
-     * Search for the script file, doesn't bother if it is named precisely.
-     *
-     * Tries in this order:
-     * - actual supplied name
-     * - name.groovy
-     * - name.gvy
-     * - name.gy
-     * - name.gsh
-     *
-     * @since 2.3.0
-     */
-    public static File searchForGroovyScriptFile(String input) {
-        String scriptFileName = input.trim();
-        File scriptFile = new File(scriptFileName);
-        // TODO: Shouldn't these extensions be kept elsewhere?  What about CompilerConfiguration?
-        // This method probably shouldn't be in GroovyMain either.
-        String[] standardExtensions = {".groovy",".gvy",".gy",".gsh"};
-        int i = 0;
-        while (i < standardExtensions.length && !scriptFile.exists()) {
-            scriptFile = new File(scriptFileName + standardExtensions[i]);
-            i++;
-        }
-        // if we still haven't found the file, point back to the originally specified filename
-        if (!scriptFile.exists()) {
-            scriptFile = new File(scriptFileName);
-        }
-        return scriptFile;
-    }
-
-    /**
-     * Hunt for the script file by calling searchForGroovyScriptFile(String).
-     *
-     * @see GroovyMain#searchForGroovyScriptFile(String)
-     */
-    public File huntForTheScriptFile(String input) {
-        return GroovyMain.searchForGroovyScriptFile(input);
-    }
-
-    // GROOVY-6771
-    private static void setupContextClassLoader(GroovyShell shell) {
-        final Thread current = Thread.currentThread();
-        class DoSetContext implements PrivilegedAction {
-            ClassLoader classLoader;
-
-            public DoSetContext(ClassLoader loader) {
-                classLoader = loader;
-            }
-
-            public Object run() {
-                current.setContextClassLoader(classLoader);
-                return null;
-            }
-        }
-
-        AccessController.doPrivileged(new DoSetContext(shell.getClassLoader()));
-    }
-
-    /**
-     * Process the input files.
-     */
-    private void processFiles() throws CompilationFailedException, IOException, URISyntaxException {
-        GroovyShell groovy = new GroovyShell(conf);
-        setupContextClassLoader(groovy);
-
-        Script s = groovy.parse(getScriptSource(isScriptFile, script));
-
-        if (args.isEmpty()) {
-            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
-            PrintWriter writer = new PrintWriter(System.out);
-
-            try {
-                processReader(s, reader, writer);
-            } finally {
-                reader.close();
-                writer.close();
-            }
-
-        } else {
-            Iterator i = args.iterator();
-            while (i.hasNext()) {
-                String filename = (String) i.next();
-                //TODO: These are the arguments for -p and -i.  Why are we searching using Groovy script extensions?
-                // Where is this documented?
-                File file = huntForTheScriptFile(filename);
-                processFile(s, file);
-            }
-        }
-    }
-
-    /**
-     * Process a single input file.
-     *
-     * @param s    the script to execute.
-     * @param file the input file.
-     */
-    private void processFile(Script s, File file) throws IOException {
-        if (!file.exists())
-            throw new FileNotFoundException(file.getName());
-
-        if (!editFiles) {
-            BufferedReader reader = new BufferedReader(new FileReader(file));
-            try {
-                PrintWriter writer = new PrintWriter(System.out);
-                processReader(s, reader, writer);
-                writer.flush();
-            } finally {
-                reader.close();
-            }
-        } else {
-            File backup;
-            if (backupExtension == null) {
-                backup = File.createTempFile("groovy_", ".tmp");
-                backup.deleteOnExit();
-            } else {
-                backup = new File(file.getPath() + backupExtension);
-            }
-            backup.delete();
-            if (!file.renameTo(backup))
-                throw new IOException("unable to rename " + file + " to " + backup);
-
-            BufferedReader reader = new BufferedReader(new FileReader(backup));
-            try {
-                PrintWriter writer = new PrintWriter(new FileWriter(file));
-                try {
-                    processReader(s, reader, writer);
-                } finally {
-                    writer.close();
-                }
-            } finally {
-                reader.close();
-            }
-        }
-    }
-
-    /**
-     * Process a script against a single input file.
-     *
-     * @param s      script to execute.
-     * @param reader input file.
-     * @param pw     output sink.
-     */
-    private void processReader(Script s, BufferedReader reader, PrintWriter pw) throws IOException {
-        String line;
-        String lineCountName = "count";
-        s.setProperty(lineCountName, BigInteger.ZERO);
-        String autoSplitName = "split";
-        s.setProperty("out", pw);
-
-        try {
-            InvokerHelper.invokeMethod(s, "begin", null);
-        } catch (MissingMethodException mme) {
-            // ignore the missing method exception
-            // as it means no begin() method is present
-        }
-
-        while ((line = reader.readLine()) != null) {
-            s.setProperty("line", line);
-            s.setProperty(lineCountName, ((BigInteger)s.getProperty(lineCountName)).add(BigInteger.ONE));
-
-            if(autoSplit) {
-                s.setProperty(autoSplitName, line.split(splitPattern));
-            }
-
-            Object o = s.run();
-
-            if (autoOutput && o != null) {
-                pw.println(o);
-            }
-        }
-
-        try {
-            InvokerHelper.invokeMethod(s, "end", null);
-        } catch (MissingMethodException mme) {
-            // ignore the missing method exception
-            // as it means no end() method is present
-        }
-    }
-
-    /**
-     * Process the standard, single script with args.
-     */
-    private void processOnce() throws CompilationFailedException, IOException, URISyntaxException {
-        GroovyShell groovy = new GroovyShell(conf);
-        setupContextClassLoader(groovy);
-        groovy.run(getScriptSource(isScriptFile, script), args);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ui/GroovySocketServer.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/ui/GroovySocketServer.java b/src/main/groovy/ui/GroovySocketServer.java
deleted file mode 100644
index b0d27c5..0000000
--- a/src/main/groovy/ui/GroovySocketServer.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- *  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 groovy.ui;
-
-import groovy.lang.GroovyCodeSource;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.GroovyShell;
-import groovy.lang.Script;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.regex.Pattern;
-
-/**
- * Simple server that executes supplied script against a socket.
- * <p>
- * Typically this is used from the groovy command line agent but it can be 
- * invoked programmatically. To run this program from the command line please
- * refer to the command line documentation at
- * <a href="http://docs.groovy-lang.org/docs/latest/html/documentation/#_running_groovy_from_the_commandline">
- * Running Groovy from the commandline</a>.
- * <p>
- * Here is an example of how to use this class to open a listening socket on the server, 
- * listen for incoming data, and then echo the data back to the client in reverse order: 
- * <pre>
- * new GroovySocketServer(
- *         new GroovyShell(),      // evaluator
- *         false,                  // is not a file
- *         "println line.reverse()",         // script to evaluate
- *         true,                   // return result to client
- *         1960)                   //port
- * </pre>
- * There are several variables in the script binding:
- * <ul>
- * <li>line - The data from the socket</li> 
- * <li>out - The output PrintWriter, should you need it for some reason.</li> 
- * <li>socket - The socket, should you need it for some reason.</li> 
- * </ul>
- * 
- * @author Jeremy Rayner
- */
-public class GroovySocketServer implements Runnable {
-    private URL url;
-    private final GroovyShell groovy;
-    private final GroovyCodeSource source;
-    private final boolean autoOutput;
-    private static int counter;
-
-    /**
-     * This creates and starts the socket server on a new Thread. There is no need to call run or spawn
-     * a new thread yourself.
-     * @param groovy
-     *       The GroovyShell object that evaluates the incoming text. If you need additional classes in the
-     *       classloader then configure that through this object.
-     * @param isScriptFile
-     *       Whether the incoming socket data String will be a script or a file path.
-     * @param scriptFilenameOrText
-     *       This will be a groovy script or a file location depending on the argument isScriptFile.
-     * @param autoOutput
-     *       whether output should be automatically echoed back to the client
-     * @param port
-     *       the port to listen on
-     *
-     */
-    public GroovySocketServer(GroovyShell groovy, boolean isScriptFile, String scriptFilenameOrText, boolean autoOutput, int port) {
-        this(groovy, getCodeSource(isScriptFile, scriptFilenameOrText), autoOutput, port);
-    }
-
-    private static GroovyCodeSource getCodeSource(boolean scriptFile, String scriptFilenameOrText) {
-        if (scriptFile) {
-            try {
-                if (URI_PATTERN.matcher(scriptFilenameOrText).matches()) {
-                    return new GroovyCodeSource(new URI(scriptFilenameOrText));
-                } else {
-                    return new GroovyCodeSource(GroovyMain.searchForGroovyScriptFile(scriptFilenameOrText));
-                }
-            } catch (IOException e) {
-                throw new GroovyRuntimeException("Unable to get script from: " + scriptFilenameOrText, e);
-            } catch (URISyntaxException e) {
-                throw new GroovyRuntimeException("Unable to get script from URI: " + scriptFilenameOrText, e);
-            }
-        } else {
-            // We could jump through some hoops to have GroovyShell make our script name, but that seems unwarranted.
-            // If we *did* jump through that hoop then we should probably change the run loop to not recompile
-            // the script on every iteration since the script text can't change (the reason for the recompilation).
-            return new GroovyCodeSource(scriptFilenameOrText, generateScriptName(), GroovyShell.DEFAULT_CODE_BASE);
-        }
-    }
-
-    private static synchronized String generateScriptName() {
-        return "ServerSocketScript" + (++counter) + ".groovy";
-    }
-
-
-    // RFC2396
-    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
-    private static final Pattern URI_PATTERN = Pattern.compile("\\p{Alpha}[-+.\\p{Alnum}]*:.*");
-
-    /**
-    * This creates and starts the socket server on a new Thread. There is no need to call run or spawn
-    * a new thread yourself. 
-    * @param groovy
-    *       The GroovyShell object that evaluates the incoming text. If you need additional classes in the 
-    *       classloader then configure that through this object. 
-    * @param source
-    *       GroovyCodeSource for the Groovy script
-    * @param autoOutput
-    *       whether output should be automatically echoed back to the client
-    * @param port
-    *       the port to listen on
-    * @since 2.3.0
-    */ 
-    public GroovySocketServer(GroovyShell groovy, GroovyCodeSource source, boolean autoOutput, int port) {
-        this.groovy = groovy;
-        this.source = source;
-        this.autoOutput = autoOutput;
-        try {
-            url = new URL("http", InetAddress.getLocalHost().getHostAddress(), port, "/");
-            System.out.println("groovy is listening on port " + port);
-        } catch (IOException e) { 
-            e.printStackTrace();
-        }
-        new Thread(this).start();
-    }
-
-    /**
-    * Runs this server. There is typically no need to call this method, as the object's constructor
-    * creates a new thread and runs this object automatically. 
-    */ 
-    public void run() {
-        try {
-            ServerSocket serverSocket = new ServerSocket(url.getPort());
-            while (true) {
-                // Create one script per socket connection.
-                // This is purposefully not caching the Script
-                // so that the script source file can be changed on the fly,
-                // as each connection is made to the server.
-                //FIXME: Groovy has other mechanisms specifically for watching to see if source code changes.
-                // We should probably be using that here.
-                // See also the comment about the fact we recompile a script that can't change.
-                Script script = groovy.parse(source);
-                new GroovyClientConnection(script, autoOutput, serverSocket.accept());
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-    
-    static class GroovyClientConnection implements Runnable {
-        private Script script;
-        private Socket socket;
-        private BufferedReader reader;
-        private PrintWriter writer;
-        private boolean autoOutputFlag;
-    
-        GroovyClientConnection(Script script, boolean autoOutput,Socket socket) throws IOException {
-            this.script = script;
-            this.autoOutputFlag = autoOutput;
-            this.socket = socket;
-            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-            writer = new PrintWriter(socket.getOutputStream());
-            new Thread(this, "Groovy client connection - " + socket.getInetAddress().getHostAddress()).start();
-        }
-        public void run() {
-            try {
-                String line = null;
-                script.setProperty("out", writer);
-                script.setProperty("socket", socket);
-                script.setProperty("init", Boolean.TRUE);
-                while ((line = reader.readLine()) != null) {
-                    // System.out.println(line);
-                    script.setProperty("line", line);
-                    Object o = script.run();
-                    script.setProperty("init", Boolean.FALSE);
-                    if (o != null) {
-                        if ("success".equals(o)) {
-                            break; // to close sockets gracefully etc...
-                        } else {
-                            if (autoOutputFlag) {
-                                writer.println(o);
-                            }
-                        }
-                    }
-                    writer.flush();
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    writer.flush();
-                    writer.close();
-                } finally {
-                    try {
-                        socket.close();
-                    } catch (IOException e3) {
-                        e3.printStackTrace();
-                    }
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/AbstractFactory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/AbstractFactory.java b/src/main/groovy/util/AbstractFactory.java
deleted file mode 100644
index d3e628c..0000000
--- a/src/main/groovy/util/AbstractFactory.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- * @author Danno Ferrin
- */
-public abstract class AbstractFactory implements Factory {
-    public boolean isLeaf() {
-        return false;
-    }
-
-    public boolean isHandlesNodeChildren() {
-        return false;
-    }
-
-    public void onFactoryRegistration(FactoryBuilderSupport builder, String registeredName, String group) {
-        // do nothing
-    }
-
-    public boolean onHandleNodeAttributes( FactoryBuilderSupport builder, Object node,
-            Map attributes ) {
-        return true;
-    }
-
-    public boolean onNodeChildren( FactoryBuilderSupport builder, Object node, Closure childContent) {
-        return true;
-    }
-
-    public void onNodeCompleted( FactoryBuilderSupport builder, Object parent, Object node ) {
-        // do nothing
-    }
-
-    public void setParent( FactoryBuilderSupport builder, Object parent, Object child ) {
-        // do nothing
-    }
-
-    public void setChild( FactoryBuilderSupport builder, Object parent, Object child ) {
-        // do nothing
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/BufferedIterator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/BufferedIterator.java b/src/main/groovy/util/BufferedIterator.java
deleted file mode 100644
index 6fa50a9..0000000
--- a/src/main/groovy/util/BufferedIterator.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  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 groovy.util;
-
-import java.util.Iterator;
-
-/**
- * An iterator that allows examining the next element without consuming it.
- *
- * @author Andrew Taylor
- * @since 2.5.0
- */
-public interface BufferedIterator<T> extends Iterator<T> {
-    T head();
-}


[22/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/PermutationGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/PermutationGenerator.java b/src/main/groovy/groovy/util/PermutationGenerator.java
new file mode 100644
index 0000000..a9b68e2
--- /dev/null
+++ b/src/main/groovy/groovy/util/PermutationGenerator.java
@@ -0,0 +1,149 @@
+/*
+ *  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 groovy.util;
+
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Systematically generate permutations.
+ *
+ * Adapted from Java Code by Michael Gilleland (released with no restrictions) using an algorithm described here:
+ * Kenneth H. Rosen, Discrete Mathematics and Its Applications, 2nd edition (NY: McGraw-Hill, 1991), pp. 282-284
+ */
+public class PermutationGenerator<E> implements Iterator<List<E>> {
+    private final int[] a;
+    private BigInteger numLeft;
+    private final BigInteger total;
+    private final List<E> items;
+
+    /**
+     * WARNING: Don't make n too large.
+     * Recall that the number of permutations is n!
+     * which can be very large, even when n is as small as 20 --
+     * 20! = 2,432,902,008,176,640,000 and
+     * 21! is too big to fit into a Java long, which is
+     * why we use BigInteger instead.
+     *
+     * @param items the items to permute
+     */
+    public PermutationGenerator(Collection<E> items) {
+        this.items = new ArrayList<E>(items);
+        int n = items.size();
+        if (n < 1) {
+            throw new IllegalArgumentException("At least one item required");
+        }
+        a = new int[n];
+        total = getFactorial(n);
+        reset();
+    }
+
+    public PermutationGenerator(Iterable<E> items) {
+        this(DefaultGroovyMethods.asCollection(items));
+    }
+
+    public void reset() {
+        for (int i = 0; i < a.length; i++) {
+            a[i] = i;
+        }
+        numLeft = new BigInteger(total.toString());
+    }
+
+    public BigInteger getTotal() {
+        return total;
+    }
+
+    public boolean hasNext() {
+        return numLeft.compareTo(BigInteger.ZERO) == 1;
+    }
+
+    /**
+     * Compute factorial (TODO: expose this)
+     *
+     * @param n the input integer
+     * @return the factorial for n
+     */
+    private static BigInteger getFactorial(int n) {
+        BigInteger fact = BigInteger.ONE;
+        for (int i = n; i > 1; i--) {
+            fact = fact.multiply(new BigInteger(Integer.toString(i)));
+        }
+        return fact;
+    }
+
+    /**
+     * Generate next permutation (algorithm from Rosen p. 284)
+     *
+     * @return the items permuted
+     */
+    public List<E> next() {
+        if (numLeft.equals(total)) {
+            numLeft = numLeft.subtract(BigInteger.ONE);
+            return items;
+        }
+
+        int temp;
+
+        // Find largest index j with a[j] < a[j+1]
+        int j = a.length - 2;
+        while (a[j] > a[j + 1]) {
+            j--;
+        }
+
+        // Find index k such that a[k] is smallest integer
+        // greater than a[j] to the right of a[j]
+        int k = a.length - 1;
+        while (a[j] > a[k]) {
+            k--;
+        }
+
+        // Interchange a[j] and a[k]
+        temp = a[k];
+        a[k] = a[j];
+        a[j] = temp;
+
+        // Put tail end of permutation after jth position in increasing order
+        int r = a.length - 1;
+        int s = j + 1;
+
+        while (r > s) {
+            temp = a[s];
+            a[s] = a[r];
+            a[r] = temp;
+            r--;
+            s++;
+        }
+
+        numLeft = numLeft.subtract(BigInteger.ONE);
+        List<E> ans = new ArrayList<E>(a.length);
+        for (int index : a) {
+            ans.add(items.get(index));
+        }
+        return ans;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("remove() not allowed for PermutationGenerator");
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/Proxy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/Proxy.java b/src/main/groovy/groovy/util/Proxy.java
new file mode 100644
index 0000000..ac080b3
--- /dev/null
+++ b/src/main/groovy/groovy/util/Proxy.java
@@ -0,0 +1,70 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.MissingMethodException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.util.Iterator;
+
+/**
+ * Dynamic groovy proxy for another object.  All method
+ * invocations get forwarded to actual object, unless the proxy overrides it.
+ * See groovy/util/ProxyTest.groovy for usage details.
+ *
+ * @author Troy Heninger
+ * @author Dierk Koenig
+ */
+public class Proxy extends GroovyObjectSupport {
+
+    private Object adaptee = null;
+
+    /**
+     * This method is for convenience.
+     * It allows to get around the need for defining dump ctors in subclasses.
+     * See unit tests for details.
+     */
+    public Proxy wrap(Object adaptee){
+        setAdaptee(adaptee);
+        return this;
+    }
+
+    public Object getAdaptee() {
+        return adaptee;
+    }
+
+    public void setAdaptee(Object adaptee) {
+        this.adaptee = adaptee;
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return super.invokeMethod(name, args);
+        }
+        catch (MissingMethodException e) {
+            return InvokerHelper.invokeMethod(adaptee, name, args);
+        }
+    }
+    
+    public Iterator iterator() {
+        return InvokerHelper.asIterator(adaptee);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ProxyGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ProxyGenerator.java b/src/main/groovy/groovy/util/ProxyGenerator.java
new file mode 100644
index 0000000..da12b97
--- /dev/null
+++ b/src/main/groovy/groovy/util/ProxyGenerator.java
@@ -0,0 +1,339 @@
+/*
+ *  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 groovy.util;
+
+import groovy.lang.Closure;
+import groovy.lang.DelegatingMetaClass;
+import groovy.lang.GroovyObject;
+import groovy.lang.GroovySystem;
+import groovy.lang.MetaClass;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.ProxyGeneratorAdapter;
+import org.codehaus.groovy.runtime.memoize.LRUCache;
+import org.codehaus.groovy.runtime.typehandling.GroovyCastException;
+import org.codehaus.groovy.transform.trait.Traits;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Classes to generate 'Proxy' objects which implement interfaces,
+ * maps of closures and/or extend classes/delegates.
+ *
+ * @author Paul King
+ * @author Guillaume Laforge
+ * @author Cedric Champeau
+ */
+public class ProxyGenerator {
+    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+    private static final Class[] EMPTY_INTERFACE_ARRAY = EMPTY_CLASS_ARRAY;
+    private static final Map<Object,Object> EMPTY_CLOSURE_MAP = Collections.emptyMap();
+    private static final Set<String> EMPTY_KEYSET = Collections.emptySet();
+
+    public static final ProxyGenerator INSTANCE = new ProxyGenerator();
+
+    static {
+        // wrap the standard MetaClass with the delegate
+        setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(ProxyGenerator.class));
+    }
+
+    private ClassLoader override = null;
+    private boolean debug = false;
+    private boolean emptyMethods = false;
+
+    /**
+     * The adapter cache is used to cache proxy classes. When, for example, a call like:
+     * map as MyClass is found, then a lookup is made into the cache to find if a suitable
+     * adapter already exists. If so, then the class is reused, instead of generating a
+     * new class.
+     */
+    private final LRUCache adapterCache = new LRUCache(16);
+
+    public boolean getDebug() {
+        return debug;
+    }
+
+    /**
+     * Instructs <code>ProxyGenerator</code> to dump generated Groovy
+     * source code to standard output during construction. This is useful
+     * for debugging purposes but should be turned off in production.
+     *
+     * @param debug true if you want generated source to be printed
+     */
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public boolean getEmptyMethods() {
+        return emptyMethods;
+    }
+
+    /**
+     * Changes generated methods to have empty implementations.
+     * <p>
+     * Methods in generated aggregates not supplied in a closures map or
+     * base class are given 'default' implementations. The implementation
+     * will normally throw an <code>UnsupportedOperationException</code>
+     * but setting this boolean will leave it empty.
+     *
+     * @param emptyMethods true if you want generated methods to be empty
+     */
+    public void setEmptyMethods(boolean emptyMethods) {
+        this.emptyMethods = emptyMethods;
+    }
+
+    public ClassLoader getOverride() {
+        return override;
+    }
+
+    public void setOverride(ClassLoader override) {
+        this.override = override;
+    }
+
+    public GroovyObject instantiateAggregateFromBaseClass(Class clazz) {
+        return instantiateAggregateFromBaseClass((Map) null, clazz);
+    }
+
+    public GroovyObject instantiateAggregateFromBaseClass(Map map, Class clazz) {
+        return instantiateAggregateFromBaseClass(map, clazz, null);
+    }
+
+    public GroovyObject instantiateAggregateFromBaseClass(Closure cl, Class clazz) {
+        Map<String, Closure> m = new HashMap<String, Closure>();
+        m.put("*", cl);
+        return instantiateAggregateFromBaseClass(m, clazz, null);
+    }
+
+    public GroovyObject instantiateAggregateFromBaseClass(Class clazz, Object[] constructorArgs) {
+        return instantiateAggregate(null, null, clazz, constructorArgs);
+    }
+
+    public GroovyObject instantiateAggregateFromBaseClass(Map map, Class clazz, Object[] constructorArgs) {
+        return instantiateAggregate(map, null, clazz, constructorArgs);
+    }
+
+    public GroovyObject instantiateAggregateFromInterface(Class clazz) {
+        return instantiateAggregateFromInterface(null, clazz);
+    }
+
+    public GroovyObject instantiateAggregateFromInterface(Map map, Class clazz) {
+        List<Class> interfaces = new ArrayList<Class>();
+        interfaces.add(clazz);
+        return instantiateAggregate(map, interfaces);
+    }
+
+    public GroovyObject instantiateAggregate(List<Class> interfaces) {
+        return instantiateAggregate(null, interfaces);
+    }
+
+    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces) {
+        return instantiateAggregate(closureMap, interfaces, null);
+    }
+
+    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces, Class clazz) {
+        return instantiateAggregate(closureMap, interfaces, clazz, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public GroovyObject instantiateAggregate(Map closureMap, List<Class> interfaces, Class clazz, Object[] constructorArgs) {
+        if (clazz != null && Modifier.isFinal(clazz.getModifiers())) {
+            throw new GroovyCastException("Cannot coerce a map to class " + clazz.getName() + " because it is a final class");
+        }
+        Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
+        ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, null, clazz);
+
+        return adapter.proxy(map, constructorArgs);
+    }
+
+    public GroovyObject instantiateDelegate(Object delegate) {
+        return instantiateDelegate(null, delegate);
+    }
+
+    public GroovyObject instantiateDelegate(List<Class> interfaces, Object delegate) {
+        return instantiateDelegate(null, interfaces, delegate);
+    }
+
+    public GroovyObject instantiateDelegate(Map closureMap, List<Class> interfaces, Object delegate) {
+        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, null);
+    }
+
+    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate) {
+        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, delegate.getClass());
+    }
+
+    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate, Class baseClass) {
+        return instantiateDelegateWithBaseClass(closureMap, interfaces, delegate, baseClass, null);
+    }
+
+    /**
+     * Creates a proxy with a delegate object.
+     *
+     * @param closureMap the closure for methods not handled by the delegate
+     * @param interfaces interfaces to be implemented
+     * @param delegate the delegate object
+     * @param baseClass the base class
+     * @param name the name of the proxy, unused, but kept for compatibility with previous versions of Groovy.
+     * @return a proxy object implementing the specified interfaces, and delegating to the provided object
+     */
+    @SuppressWarnings("unchecked")
+    public GroovyObject instantiateDelegateWithBaseClass(Map closureMap, List<Class> interfaces, Object delegate, Class baseClass, String name) {
+        Map<Object,Object> map = closureMap != null ? closureMap : EMPTY_CLOSURE_MAP;
+        ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, delegate.getClass(), baseClass);
+
+        return adapter.delegatingProxy(delegate, map, (Object[])null);
+    }
+
+    private ProxyGeneratorAdapter createAdapter(Map closureMap, List<Class> interfaces, Class delegateClass, Class baseClass) {
+        // According to https://shipilev.net/blog/2016/arrays-wisdom-ancients/#_conclusion
+        // toArray(new T[0]) seems faster, safer, and contractually cleaner, and therefore should be the default choice now.
+        Class[] intfs = interfaces != null ? interfaces.toArray(EMPTY_CLASS_ARRAY) : EMPTY_INTERFACE_ARRAY;
+        Class base = baseClass;
+        if (base == null) {
+            if (intfs.length > 0) {
+                base = intfs[0];
+            } else {
+                base = Object.class;
+            }
+        }
+        Set<String> keys = closureMap == EMPTY_CLOSURE_MAP ? EMPTY_KEYSET : new HashSet<String>();
+        for (Object o : closureMap.keySet()) {
+            keys.add(o.toString());
+        }
+        boolean useDelegate = null != delegateClass;
+        CacheKey key = new CacheKey(base, useDelegate ? delegateClass : Object.class, keys, intfs, emptyMethods, useDelegate);
+        ProxyGeneratorAdapter adapter = (ProxyGeneratorAdapter) adapterCache.get(key);
+        if (adapter == null) {
+            adapter = new ProxyGeneratorAdapter(closureMap, base, intfs, useDelegate ? delegateClass.getClassLoader() : base.getClassLoader(), emptyMethods, useDelegate ? delegateClass : null);
+            adapterCache.put(key, adapter);
+        }
+
+        return adapter;
+    }
+
+    private static void setMetaClass(final MetaClass metaClass) {
+        final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
+            @Override
+            public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
+                return InvokerHelper.invokeMethod(INSTANCE, methodName, arguments);
+            }
+        };
+        GroovySystem.getMetaClassRegistry().setMetaClass(ProxyGenerator.class, newMetaClass);
+    }
+    
+    private static final class CacheKey {
+        private static final Comparator<Class> INTERFACE_COMPARATOR = new Comparator<Class>() {
+            public int compare(final Class o1, final Class o2) {
+                // Traits order *must* be preserved
+                // See GROOVY-7285
+                if (Traits.isTrait(o1)) return -1;
+                if (Traits.isTrait(o2)) return 1;
+                return o1.getName().compareTo(o2.getName());
+            }
+        };
+        private final boolean emptyMethods;
+        private final boolean useDelegate;
+        private final Set<String> methods;
+        private final ClassReference delegateClass;
+        private final ClassReference baseClass;
+        private final ClassReference[] interfaces;
+
+        private CacheKey(final Class baseClass, final Class delegateClass, final Set<String> methods, final Class[] interfaces, final boolean emptyMethods, final boolean useDelegate) {
+            this.useDelegate = useDelegate;
+            this.baseClass = new ClassReference(baseClass);
+            this.delegateClass = new ClassReference(delegateClass);
+            this.emptyMethods = emptyMethods;
+            this.interfaces = interfaces == null ? null : new ClassReference[interfaces.length];
+            if (interfaces != null) {
+                Class[] interfacesCopy = new Class[interfaces.length];
+                System.arraycopy(interfaces, 0, interfacesCopy, 0, interfaces.length);
+                Arrays.sort(interfacesCopy, INTERFACE_COMPARATOR);
+                for (int i = 0; i < interfacesCopy.length; i++) {
+                    Class anInterface = interfacesCopy[i];
+                    this.interfaces[i] = new ClassReference(anInterface);
+                }
+            }
+            this.methods = methods;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            final CacheKey cacheKey = (CacheKey) o;
+
+            if (emptyMethods != cacheKey.emptyMethods) return false;
+            if (useDelegate != cacheKey.useDelegate) return false;
+            if (baseClass != null ? !baseClass.equals(cacheKey.baseClass) : cacheKey.baseClass != null) return false;
+            if (delegateClass != null ? !delegateClass.equals(cacheKey.delegateClass) : cacheKey.delegateClass != null) return false;
+            if (!Arrays.equals(interfaces, cacheKey.interfaces)) return false;
+            if (methods != null ? !methods.equals(cacheKey.methods) : cacheKey.methods != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = (emptyMethods ? 1 : 0);
+            result = 31 * result + (useDelegate ? 1 : 0);
+            result = 31 * result + (methods != null ? methods.hashCode() : 0);
+            result = 31 * result + (baseClass != null ? baseClass.hashCode() : 0);
+            result = 31 * result + (delegateClass != null ? delegateClass.hashCode() : 0);
+            result = 31 * result + (interfaces != null ? Arrays.hashCode(interfaces) : 0);
+            return result;
+        }
+
+        /**
+         * A weak reference which delegates equals and hashcode to the referent.
+         */
+        private static class ClassReference extends WeakReference<Class> {
+
+            public ClassReference(Class referent) {
+                super(referent);
+            }
+
+            @Override
+            public boolean equals(final Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+                Class thisClass = this.get();
+                ClassReference that = (ClassReference) o;
+                if (thisClass == null) return false;
+                return thisClass.equals(that.get());
+            }
+
+            @Override
+            public int hashCode() {
+                Class thisClass = this.get();
+                if (thisClass == null) return 0;
+                return thisClass.hashCode();
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ResourceConnector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ResourceConnector.java b/src/main/groovy/groovy/util/ResourceConnector.java
new file mode 100644
index 0000000..81e329a
--- /dev/null
+++ b/src/main/groovy/groovy/util/ResourceConnector.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 groovy.util;
+
+import java.net.URLConnection;
+
+/**
+ * Base interface for customizing where resources can be found for the <code>GroovyScriptEngine</code>.
+ *
+ * @author sam
+ */
+public interface ResourceConnector {
+
+    /**
+     * Retrieve a URLConnection to a script referenced by name.
+     *
+     * @param name
+     * @throws ResourceException
+     */
+    URLConnection getResourceConnection(String name) throws ResourceException;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ResourceException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ResourceException.java b/src/main/groovy/groovy/util/ResourceException.java
new file mode 100644
index 0000000..8b31d7e
--- /dev/null
+++ b/src/main/groovy/groovy/util/ResourceException.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 groovy.util;
+
+/**
+ * @author sam
+ */
+public class ResourceException extends Exception {
+
+    /**
+     *
+     */
+    public ResourceException() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param message
+     */
+    public ResourceException(String message) {
+        super(message);
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public ResourceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * @param cause
+     */
+    public ResourceException(Throwable cause) {
+        super(cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/ScriptException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/ScriptException.java b/src/main/groovy/groovy/util/ScriptException.java
new file mode 100644
index 0000000..85ce60f
--- /dev/null
+++ b/src/main/groovy/groovy/util/ScriptException.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 groovy.util;
+
+/**
+ * @author sam
+ */
+public class ScriptException extends Exception {
+
+    /**
+     *
+     */
+    public ScriptException() {
+        super();
+    }
+
+    /**
+     * @param message
+     */
+    public ScriptException(String message) {
+        super(message);
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public ScriptException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * @param cause
+     */
+    public ScriptException(Throwable cause) {
+        super(cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/logging/Commons.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/logging/Commons.java b/src/main/groovy/groovy/util/logging/Commons.java
new file mode 100644
index 0000000..aa456d2
--- /dev/null
+++ b/src/main/groovy/groovy/util/logging/Commons.java
@@ -0,0 +1,108 @@
+/*
+ *  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 groovy.util.logging;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.codehaus.groovy.transform.LogASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * This local transform adds a logging ability to your program using
+ * Apache Commons logging. Every method call on a unbound variable named <i>log</i>
+ * will be mapped to a call to the logger. For this a <i>log</i> field will be
+ * inserted in the class. If the field already exists the usage of this transform
+ * will cause a compilation error. The method name will be used to determine
+ * what to call on the logger.
+ * <pre>
+ * log.name(exp)
+ * </pre>is mapped to
+ * <pre>
+ * if (log.isNameEnabled() {
+ *    log.name(exp)
+ * }</pre>
+ * Here name is a place holder for info, debug, warning, error, etc.
+ * If the expression exp is a constant or only a variable access the method call will
+ * not be transformed. But this will still cause a call on the injected logger.
+ *
+ * @author Hamlet D'Arcy
+ * @author Matthias Cullmann
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
+public @interface Commons {
+    String value() default "log";
+    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
+    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default CommonsLoggingStrategy.class;
+
+    public  static class CommonsLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
+
+        private static final String LOGGER_NAME = "org.apache.commons.logging.Log";
+        private static final String LOGGERFACTORY_NAME = "org.apache.commons.logging.LogFactory";
+
+        protected CommonsLoggingStrategy(final GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
+            return classNode.addField(logFieldName,
+                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                    classNode(LOGGER_NAME),
+                    new MethodCallExpression(
+                            new ClassExpression(classNode(LOGGERFACTORY_NAME)),
+                            "getLog",
+                            new ConstantExpression(getCategoryName(classNode, categoryName))));
+        }
+
+        public boolean isLoggingMethod(String methodName) {
+            return methodName.matches("fatal|error|warn|info|debug|trace");
+        }
+
+        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
+            MethodCallExpression condition = new MethodCallExpression(
+                    logVariable,
+                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
+                    ArgumentListExpression.EMPTY_ARGUMENTS);
+            condition.setImplicitThis(false);
+
+            return new TernaryExpression(
+                    new BooleanExpression(condition),
+                    originalExpression,
+                    ConstantExpression.NULL);
+        }
+   }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/logging/Log.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/logging/Log.java b/src/main/groovy/groovy/util/logging/Log.java
new file mode 100644
index 0000000..e52d39b
--- /dev/null
+++ b/src/main/groovy/groovy/util/logging/Log.java
@@ -0,0 +1,124 @@
+/*
+ *  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 groovy.util.logging;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.AttributeExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.codehaus.groovy.transform.LogASTTransformation;
+import org.codehaus.groovy.transform.LogASTTransformation.LoggingStrategy;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * This local transform adds a logging ability to your program using
+ * java.util.logging. Every method call on a unbound variable named <i>log</i>
+ * will be mapped to a call to the logger. For this a <i>log</i> field will be
+ * inserted in the class. If the field already exists the usage of this transform
+ * will cause a compilation error. The method name will be used to determine
+ * what to call on the logger.
+ * <pre>
+ * log.name(exp)
+ * </pre>is mapped to
+ * <pre>
+ * if (log.isLoggable(Level.NAME) {
+ *    log.name(exp)
+ * }</pre>
+ * Here name is a place holder for info, fine, finer, finest, config, warning, severe.
+ * NAME is name transformed to upper case. if anything else is used it will result in
+ * an exception at runtime. If the expression exp is a constant or only a variable access
+ * the method call will not be transformed. But this will still cause a call on the injected
+ * logger.
+ *
+ * @author Guillaume Laforge
+ * @author Jochen Theodorou
+ * @author Dinko Srkoc
+ * @author Hamlet D'Arcy
+ * @author Raffaele Cigni
+ * @author Alberto Vilches Raton
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
+public @interface Log {
+    String value() default "log";
+    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
+    Class<? extends LoggingStrategy> loggingStrategy() default JavaUtilLoggingStrategy.class;
+
+    /**
+     * This class contains the logic of how to weave a Java Util Logging logger into the host class.
+     */
+    public static class JavaUtilLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
+
+        private static final ClassNode LOGGER_CLASSNODE = ClassHelper.make(java.util.logging.Logger.class);
+        private static final ClassNode LEVEL_CLASSNODE = ClassHelper.make(java.util.logging.Level.class);
+
+        protected JavaUtilLoggingStrategy(final GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
+            return classNode.addField(logFieldName,
+                        Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                        LOGGER_CLASSNODE,
+                        new MethodCallExpression(
+                                new ClassExpression(LOGGER_CLASSNODE),
+                                "getLogger",
+                                new ConstantExpression(getCategoryName(classNode, categoryName))));
+        }
+
+        public boolean isLoggingMethod(String methodName) {
+            return methodName.matches("severe|warning|info|fine|finer|finest");
+        }
+
+        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
+            AttributeExpression logLevelExpression = new AttributeExpression(
+                    new ClassExpression(LEVEL_CLASSNODE),
+                    new ConstantExpression(methodName.toUpperCase(Locale.ENGLISH)));
+
+            ArgumentListExpression args = new ArgumentListExpression();
+            args.addExpression(logLevelExpression);
+            MethodCallExpression condition = new MethodCallExpression(logVariable, "isLoggable", args);
+            condition.setImplicitThis(false);
+
+            return new TernaryExpression(
+                    new BooleanExpression(condition),
+                    originalExpression,
+                    ConstantExpression.NULL);
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/logging/Log4j.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/logging/Log4j.java b/src/main/groovy/groovy/util/logging/Log4j.java
new file mode 100644
index 0000000..2dfdf7f
--- /dev/null
+++ b/src/main/groovy/groovy/util/logging/Log4j.java
@@ -0,0 +1,119 @@
+/*
+ *  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 groovy.util.logging;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.AttributeExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.codehaus.groovy.transform.LogASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * This local transform adds a logging ability to your program using
+ * Log4j logging. Every method call on a unbound variable named <i>log</i>
+ * will be mapped to a call to the logger. For this a <i>log</i> field will be
+ * inserted in the class. If the field already exists the usage of this transform
+ * will cause a compilation error. The method name will be used to determine
+ * what to call on the logger.
+ * <pre>
+ * log.name(exp)
+ * </pre>is mapped to
+ * <pre>
+ * if (log.isNameEnabled() {
+ *    log.name(exp)
+ * }</pre>
+ * Here name is a place holder for info, debug, warning, error, etc.
+ * If the expression exp is a constant or only a variable access the method call will
+ * not be transformed. But this will still cause a call on the injected logger.
+ *
+ * @author Hamlet D'Arcy
+ * @author Tomek Bujok
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
+public @interface Log4j {
+    String value() default "log";
+    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
+    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Log4jLoggingStrategy.class;
+
+    public static class Log4jLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
+        private static final String LOGGER_NAME = "org.apache.log4j.Logger";
+        private static final String PRIORITY_NAME = "org.apache.log4j.Priority";
+
+        protected Log4jLoggingStrategy(final GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
+            return classNode.addField(logFieldName,
+                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                    classNode(LOGGER_NAME),
+                    new MethodCallExpression(
+                            new ClassExpression(classNode(LOGGER_NAME)),
+                            "getLogger",
+                            new ConstantExpression(getCategoryName(classNode, categoryName))));
+        }
+
+        public boolean isLoggingMethod(String methodName) {
+            return methodName.matches("fatal|error|warn|info|debug|trace");
+        }
+
+        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
+            final MethodCallExpression condition;
+            if (!"trace".equals(methodName)) {
+                AttributeExpression logLevelExpression = new AttributeExpression(
+                        new ClassExpression(classNode(PRIORITY_NAME)),
+                        new ConstantExpression(methodName.toUpperCase(Locale.ENGLISH)));
+                ArgumentListExpression args = new ArgumentListExpression();
+                args.addExpression(logLevelExpression);
+                condition = new MethodCallExpression(logVariable, "isEnabledFor", args);
+            } else {
+                // log4j api is inconsistent, so trace requires special handling
+                condition = new MethodCallExpression(
+                        logVariable,
+                        "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
+                        ArgumentListExpression.EMPTY_ARGUMENTS);
+            }
+            condition.setImplicitThis(false);
+
+            return new TernaryExpression(
+                    new BooleanExpression(condition),
+                    originalExpression,
+                    ConstantExpression.NULL);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/logging/Log4j2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/logging/Log4j2.java b/src/main/groovy/groovy/util/logging/Log4j2.java
new file mode 100644
index 0000000..7aca5a5
--- /dev/null
+++ b/src/main/groovy/groovy/util/logging/Log4j2.java
@@ -0,0 +1,105 @@
+/*
+ *  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 groovy.util.logging;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.codehaus.groovy.transform.LogASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * This local transform adds a logging ability to your program using
+ * Log4j2 logging. Every method call on a unbound variable named <i>log</i>
+ * will be mapped to a call to the logger. For this a <i>log</i> field will be
+ * inserted in the class. If the field already exists the usage of this transform
+ * will cause a compilation error. The method name will be used to determine
+ * what to call on the logger.
+ * <pre>
+ * log.name(exp)
+ * </pre>is mapped to
+ * <pre>
+ * if (log.isNameEnabled() {
+ *    log.name(exp)
+ * }</pre>
+ * Here name is a place holder for info, debug, warning, error, etc.
+ * If the expression exp is a constant or only a variable access the method call will
+ * not be transformed. But this will still cause a call on the injected logger.
+ *
+ * @since 2.2.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
+public @interface Log4j2 {
+    String value() default "log";
+    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
+    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Log4j2LoggingStrategy.class;
+
+    public static class Log4j2LoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
+        private static final String LOGGER_NAME = "org.apache.logging.log4j.core.Logger";
+        private static final String LOG_MANAGER_NAME = "org.apache.logging.log4j.LogManager";
+
+        protected Log4j2LoggingStrategy(final GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
+            return classNode.addField(logFieldName,
+                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                    classNode(LOGGER_NAME),
+                    new MethodCallExpression(
+                            new ClassExpression(classNode(LOG_MANAGER_NAME)),
+                            "getLogger",
+                            new ConstantExpression(getCategoryName(classNode, categoryName))));
+        }
+
+        public boolean isLoggingMethod(String methodName) {
+            return methodName.matches("fatal|error|warn|info|debug|trace");
+        }
+
+        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
+            MethodCallExpression condition = new MethodCallExpression(
+                    logVariable,
+                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
+                    ArgumentListExpression.EMPTY_ARGUMENTS);
+            condition.setImplicitThis(false);
+
+            return new TernaryExpression(
+                    new BooleanExpression(condition),
+                    originalExpression,
+                    ConstantExpression.NULL);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/logging/Slf4j.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/logging/Slf4j.java b/src/main/groovy/groovy/util/logging/Slf4j.java
new file mode 100644
index 0000000..0e866e4
--- /dev/null
+++ b/src/main/groovy/groovy/util/logging/Slf4j.java
@@ -0,0 +1,108 @@
+/*
+ *  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 groovy.util.logging;
+
+import groovy.lang.GroovyClassLoader;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import org.codehaus.groovy.transform.LogASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+/**
+ * This local transform adds a logging ability to your program using
+ * LogBack logging. Every method call on a unbound variable named <i>log</i>
+ * will be mapped to a call to the logger. For this a <i>log</i> field will be
+ * inserted in the class. If the field already exists the usage of this transform
+ * will cause a compilation error. The method name will be used to determine
+ * what to call on the logger.
+ * <pre>
+ * log.name(exp)
+ * </pre>is mapped to
+ * <pre>
+ * if (log.isNameLoggable() {
+ *    log.name(exp)
+ * }</pre>
+ * Here name is a place holder for info, debug, warning, error, etc.
+ * If the expression exp is a constant or only a variable access the method call will
+ * not be transformed. But this will still cause a call on the injected logger.
+ *
+ * @author Hamlet D'Arcy
+ * @author Alberto Mijares
+ * @since 1.8.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.LogASTTransformation")
+public @interface Slf4j {
+    String value() default "log";
+    String category() default LogASTTransformation.DEFAULT_CATEGORY_NAME;
+    Class<? extends LogASTTransformation.LoggingStrategy> loggingStrategy() default Slf4jLoggingStrategy.class;
+
+    public static class Slf4jLoggingStrategy extends LogASTTransformation.AbstractLoggingStrategy {
+        private static final String LOGGER_NAME = "org.slf4j.Logger";
+        private static final String FACTORY_NAME = "org.slf4j.LoggerFactory";
+
+        protected Slf4jLoggingStrategy(final GroovyClassLoader loader) {
+            super(loader);
+        }
+
+        public FieldNode addLoggerFieldToClass(ClassNode classNode, String logFieldName, String categoryName) {
+            return classNode.addField(logFieldName,
+                    Opcodes.ACC_FINAL | Opcodes.ACC_TRANSIENT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+                    classNode(LOGGER_NAME),
+                    new MethodCallExpression(
+                            new ClassExpression(classNode(FACTORY_NAME)),
+                            "getLogger",
+                            new ConstantExpression(getCategoryName(classNode, categoryName))));
+        }
+
+        public boolean isLoggingMethod(String methodName) {
+            return methodName.matches("error|warn|info|debug|trace");
+        }
+
+        public Expression wrapLoggingMethodCall(Expression logVariable, String methodName, Expression originalExpression) {
+            MethodCallExpression condition = new MethodCallExpression(
+                    logVariable,
+                    "is" + methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1, methodName.length()) + "Enabled",
+                    ArgumentListExpression.EMPTY_ARGUMENTS);
+            condition.setImplicitThis(false);
+
+            return new TernaryExpression(
+                    new BooleanExpression(condition),
+                    originalExpression,
+                    ConstantExpression.NULL);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/util/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/util/package.html b/src/main/groovy/groovy/util/package.html
new file mode 100644
index 0000000..e7a2c5a
--- /dev/null
+++ b/src/main/groovy/groovy/util/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 groovy.util.*</title>
+  </head>
+  <body>
+    <p>Various Groovy utilities for working with nodes, builders, logging, JUnit test cases, text expressions, Ant tasks or JMX MBeans.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/xml/QName.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/xml/QName.java b/src/main/groovy/groovy/xml/QName.java
new file mode 100644
index 0000000..06a733d
--- /dev/null
+++ b/src/main/groovy/groovy/xml/QName.java
@@ -0,0 +1,287 @@
+/*
+ *  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 groovy.xml;
+
+import java.io.Serializable;
+
+/**
+ * <code>QName</code> class represents the value of a qualified name
+ * as specified in <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML
+ * Schema Part2: Datatypes specification</a>.
+ * <p>
+ * The value of a QName contains a <b>namespaceURI</b>, a <b>localPart</b> and a <b>prefix</b>.
+ * The localPart provides the local part of the qualified name. The
+ * namespaceURI is a URI reference identifying the namespace.
+ */
+public class QName implements Serializable {
+    private static final long serialVersionUID = -9029109610006696081L;
+
+    /** comment/shared empty string */
+    private static final String EMPTY_STRING = "";
+
+    /** Field namespaceURI */
+    private String namespaceURI;
+
+    /** Field localPart */
+    private String localPart;
+
+    /** Field prefix */
+    private String prefix;
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param localPart Local part of the QName
+     */
+    public QName(String localPart) {
+        this(EMPTY_STRING, localPart, EMPTY_STRING);
+    }
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param namespaceURI Namespace URI for the QName
+     * @param localPart Local part of the QName.
+     */
+    public QName(String namespaceURI, String localPart) {
+        this(namespaceURI, localPart, EMPTY_STRING);
+    }
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param namespaceURI Namespace URI for the QName
+     * @param localPart Local part of the QName.
+     * @param prefix Prefix of the QName.
+     */
+    public QName(String namespaceURI, String localPart, String prefix) {
+        this.namespaceURI = (namespaceURI == null)
+                ? EMPTY_STRING
+                : namespaceURI;
+        if (localPart == null) {
+            throw new IllegalArgumentException("invalid QName local part");
+        } else {
+            this.localPart = localPart;
+        }
+
+        if (prefix == null) {
+            throw new IllegalArgumentException("invalid QName prefix");
+        } else {
+            this.prefix = prefix;
+        }
+    }
+
+    /**
+     * Gets the Namespace URI for this QName
+     *
+     * @return Namespace URI
+     */
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    /**
+     * Gets the Local part for this QName
+     *
+     * @return Local part
+     */
+    public String getLocalPart() {
+        return localPart;
+    }
+
+    /**
+     * Gets the Prefix for this QName
+     *
+     * @return Prefix
+     */
+    public String getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * Returns the fully qualified name of this QName
+     *
+     * @return  a string representation of the QName
+     */
+    public String getQualifiedName() {
+        return ((prefix.equals(EMPTY_STRING))
+                ? localPart
+                : prefix + ':' + localPart);
+    }
+
+    /**
+     * Returns a string representation of this QName
+     *
+     * @return  a string representation of the QName
+     */
+    public String toString() {
+        return ((namespaceURI.equals(EMPTY_STRING))
+                ? localPart
+                : '{' + namespaceURI + '}' + localPart);
+    }
+
+    /**
+     * Tests this QName for equality with another object.
+     * <p>
+     * If the given object is not a QName or String equivalent or is null then this method
+     * returns <tt>false</tt>.
+     * <p>
+     * For two QNames to be considered equal requires that both
+     * localPart and namespaceURI must be equal. This method uses
+     * <code>String.equals</code> to check equality of localPart
+     * and namespaceURI. Any class that extends QName is required
+     * to satisfy this equality contract.
+     *
+     * If the supplied object is a String, then it is split in two on the last colon
+     * and the first half is compared against the prefix || namespaceURI
+     * and the second half is compared against the localPart
+     *
+     * i.e.&#160;assert new QName("namespace","localPart").equals("namespace:localPart")
+     *
+     * Intended Usage: for gpath accessors, e.g.&#160;root.'urn:mynamespace:node'
+     *
+     * Warning: this equivalence is not commutative,
+     * i.e.&#160;qname.equals(string) may be true/false  but string.equals(qname) is always false
+     *
+     * <p>
+     * This method satisfies the general contract of the <code>Object.equals</code> method.
+     *
+     * @param o the reference object with which to compare
+     *
+     * @return <code>true</code> if the given object is identical to this
+     *      QName: <code>false</code> otherwise.
+     */
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null) return false;
+        if (o instanceof QName) {
+            final QName qName = (QName) o;
+            if (!namespaceURI.equals(qName.namespaceURI)) return false;
+            return localPart.equals(qName.localPart);
+
+        } else if (o instanceof String) {
+            final String string = (String)o;
+            if (string.length() == 0) return false;
+            int lastColonIndex = string.lastIndexOf(":");
+            if (lastColonIndex < 0 || lastColonIndex == string.length() - 1) return false;
+            final String stringPrefix = string.substring(0,lastColonIndex);
+            final String stringLocalPart = string.substring(lastColonIndex + 1);
+            if (stringPrefix.equals(prefix) || stringPrefix.equals(namespaceURI)) {
+                return localPart.equals(stringLocalPart);
+            }
+            return false;
+        }
+        return false;
+    }
+
+    /**
+     * Tests if this QName matches another object.
+     * <p>
+     * If the given object is not a QName or String equivalent or is null then this method
+     * returns <tt>false</tt>.
+     * <p>
+     * For two QNames to be considered matching requires that both
+     * localPart and namespaceURI must be equal or one of them is a wildcard.
+     *
+     * If the supplied object is a String, then it is split in two on the last colon
+     * and the first half is matched against the prefix || namespaceURI
+     * and the second half is matched against the localPart
+     *
+     * @param o the reference object with which to compare
+     *
+     * @return <code>true</code> if the given object matches
+     * this QName: <code>false</code> otherwise.
+     */
+    public boolean matches(Object o) {
+        if (this == o) return true;
+        if (o == null) return false;
+        if (o instanceof QName) {
+            final QName qName = (QName) o;
+            if (!namespaceURI.equals(qName.namespaceURI) && !namespaceURI.equals("*") && !qName.namespaceURI.equals("*")) return false;
+            return localPart.equals(qName.localPart) || localPart.equals("*") || qName.localPart.equals("*");
+        } else if (o instanceof String) {
+            final String string = (String)o;
+            if (string.length() == 0) return false;
+            // try matching against 'prefix:localname'
+            int lastColonIndex = string.lastIndexOf(":");
+            if (lastColonIndex < 0 && prefix.length() == 0) return string.equals(localPart);
+            if (lastColonIndex < 0 || lastColonIndex == string.length() - 1) return false;
+            final String stringPrefix = string.substring(0,lastColonIndex);
+            final String stringLocalPart = string.substring(lastColonIndex + 1);
+            if (stringPrefix.equals(prefix) || stringPrefix.equals(namespaceURI) || stringPrefix.equals("*")) {
+                return localPart.equals(stringLocalPart) || stringLocalPart.equals("*");
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns a QName holding the value of the specified String.
+     * <p>
+     * The string must be in the form returned by the QName.toString()
+     * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}"
+     * part being optional.
+     * <p>
+     * This method doesn't do a full validation of the resulting QName.
+     * In particular, it doesn't check that the resulting namespace URI
+     * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting
+     * local part is a legal NCName per the XML Namespaces specification.
+     *
+     * @param s the string to be parsed
+     * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName
+     * @return QName corresponding to the given String
+     */
+    public static QName valueOf(String s) {
+
+        if ((s == null) || s.equals("")) {
+            throw new IllegalArgumentException("invalid QName literal");
+        }
+
+        if (s.charAt(0) == '{') {
+            int i = s.indexOf('}');
+
+            if (i == -1) {
+                throw new IllegalArgumentException("invalid QName literal");
+            }
+
+            if (i == s.length() - 1) {
+                throw new IllegalArgumentException("invalid QName literal");
+            } else {
+                return new QName(s.substring(1, i), s.substring(i + 1));
+            }
+        } else {
+            return new QName(s);
+        }
+    }
+
+    /**
+     * Returns a hash code value for this QName object. The hash code
+     * is based on both the localPart and namespaceURI parts of the
+     * QName. This method satisfies the  general contract of the
+     * <code>Object.hashCode</code> method.
+     *
+     * @return a hash code value for this Qname object
+     */
+    public int hashCode() {
+        int result;
+        result = namespaceURI.hashCode();
+        result = 29 * result + localPart.hashCode();
+        return result;
+    }
+} 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/inspect/Inspector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/inspect/Inspector.java b/src/main/groovy/inspect/Inspector.java
deleted file mode 100644
index f0c94a7..0000000
--- a/src/main/groovy/inspect/Inspector.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- *  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 groovy.inspect;
-
-import groovy.lang.GroovyObject;
-import groovy.lang.MetaClass;
-import groovy.lang.MetaMethod;
-import groovy.lang.PropertyValue;
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-import java.io.PrintStream;
-import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * The Inspector provides a unified access to an object's
- * information that can be determined by introspection.
- *
- * @author Dierk Koenig
- */
-public class Inspector {
-    protected Object objectUnderInspection;
-
-    // Indexes to retrieve Class Property information
-    public static final int CLASS_PACKAGE_IDX = 0;
-    public static final int CLASS_CLASS_IDX = 1;
-    public static final int CLASS_INTERFACE_IDX = 2;
-    public static final int CLASS_SUPERCLASS_IDX = 3;
-    public static final int CLASS_OTHER_IDX = 4;
-
-    // Indexes to retrieve field and method information
-    public static final int MEMBER_ORIGIN_IDX = 0;
-    public static final int MEMBER_MODIFIER_IDX = 1;
-    public static final int MEMBER_DECLARER_IDX = 2;
-    public static final int MEMBER_TYPE_IDX = 3;
-    public static final int MEMBER_NAME_IDX = 4;
-    public static final int MEMBER_PARAMS_IDX = 5;
-    public static final int MEMBER_VALUE_IDX = 5;
-    public static final int MEMBER_EXCEPTIONS_IDX = 6;
-
-    public static final String NOT_APPLICABLE = "n/a";
-    public static final String GROOVY = "GROOVY";
-    public static final String JAVA = "JAVA";
-
-    /**
-     * @param objectUnderInspection must not be null
-     */
-    public Inspector(Object objectUnderInspection) {
-        if (null == objectUnderInspection) {
-            throw new IllegalArgumentException("argument must not be null");
-        }
-        this.objectUnderInspection = objectUnderInspection;
-    }
-
-    /**
-     * Get the Class Properties of the object under inspection.
-     *
-     * @return String array to be indexed by the CLASS_xxx_IDX constants
-     */
-    public String[] getClassProps() {
-        String[] result = new String[CLASS_OTHER_IDX + 1];
-        Package pack = getClassUnderInspection().getPackage();
-        result[CLASS_PACKAGE_IDX] = "package " + ((pack == null) ? NOT_APPLICABLE : pack.getName());
-        String modifiers = Modifier.toString(getClassUnderInspection().getModifiers());
-        result[CLASS_CLASS_IDX] = modifiers + " class " + shortName(getClassUnderInspection());
-        result[CLASS_INTERFACE_IDX] = "implements ";
-        Class[] interfaces = getClassUnderInspection().getInterfaces();
-        for (Class anInterface : interfaces) {
-            result[CLASS_INTERFACE_IDX] += shortName(anInterface) + " ";
-        }
-        result[CLASS_SUPERCLASS_IDX] = "extends " + shortName(getClassUnderInspection().getSuperclass());
-        result[CLASS_OTHER_IDX] = "is Primitive: " + getClassUnderInspection().isPrimitive()
-                + ", is Array: " + getClassUnderInspection().isArray()
-                + ", is Groovy: " + isGroovy();
-        return result;
-    }
-
-    public boolean isGroovy() {
-        return GroovyObject.class.isAssignableFrom(getClassUnderInspection());
-    }
-
-    /**
-     * Gets the object being inspected.
-     *
-     * @return the object
-     */
-    public Object getObject() {
-        return objectUnderInspection;
-    }
-
-    /**
-     * Get info about usual Java instance and class Methods as well as Constructors.
-     *
-     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
-     */
-    public Object[] getMethods() {
-        Method[] methods = getClassUnderInspection().getMethods();
-        Constructor[] ctors = getClassUnderInspection().getConstructors();
-        Object[] result = new Object[methods.length + ctors.length];
-        int resultIndex = 0;
-        for (; resultIndex < methods.length; resultIndex++) {
-            Method method = methods[resultIndex];
-            result[resultIndex] = methodInfo(method);
-        }
-        for (int i = 0; i < ctors.length; i++, resultIndex++) {
-            Constructor ctor = ctors[i];
-            result[resultIndex] = methodInfo(ctor);
-        }
-        return result;
-    }
-
-    /**
-     * Get info about instance and class Methods that are dynamically added through Groovy.
-     *
-     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
-     */
-    public Object[] getMetaMethods() {
-        MetaClass metaClass = InvokerHelper.getMetaClass(objectUnderInspection);
-        List metaMethods = metaClass.getMetaMethods();
-        Object[] result = new Object[metaMethods.size()];
-        int i = 0;
-        for (Iterator iter = metaMethods.iterator(); iter.hasNext(); i++) {
-            MetaMethod metaMethod = (MetaMethod) iter.next();
-            result[i] = methodInfo(metaMethod);
-        }
-        return result;
-    }
-
-    /**
-     * Get info about usual Java public fields incl. constants.
-     *
-     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
-     */
-    public Object[] getPublicFields() {
-        Field[] fields = getClassUnderInspection().getFields();
-        Object[] result = new Object[fields.length];
-        for (int i = 0; i < fields.length; i++) {
-            Field field = fields[i];
-            result[i] = fieldInfo(field);
-        }
-        return result;
-    }
-
-    /**
-     * Get info about Properties (Java and Groovy alike).
-     *
-     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
-     */
-    public Object[] getPropertyInfo() {
-        List props = DefaultGroovyMethods.getMetaPropertyValues(objectUnderInspection);
-        Object[] result = new Object[props.size()];
-        int i = 0;
-        for (Iterator iter = props.iterator(); iter.hasNext(); i++) {
-            PropertyValue pv = (PropertyValue) iter.next();
-            result[i] = fieldInfo(pv);
-        }
-        return result;
-    }
-
-    protected String[] fieldInfo(Field field) {
-        String[] result = new String[MEMBER_VALUE_IDX + 1];
-        result[MEMBER_ORIGIN_IDX] = JAVA;
-        result[MEMBER_MODIFIER_IDX] = Modifier.toString(field.getModifiers());
-        result[MEMBER_DECLARER_IDX] = shortName(field.getDeclaringClass());
-        result[MEMBER_TYPE_IDX] = shortName(field.getType());
-        result[MEMBER_NAME_IDX] = field.getName();
-        try {
-            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(field.get(objectUnderInspection));
-        } catch (IllegalAccessException e) {
-            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
-        }
-        return withoutNulls(result);
-    }
-
-    protected String[] fieldInfo(PropertyValue pv) {
-        String[] result = new String[MEMBER_VALUE_IDX + 1];
-        result[MEMBER_ORIGIN_IDX] = GROOVY;
-        result[MEMBER_MODIFIER_IDX] = "public";
-        result[MEMBER_DECLARER_IDX] = NOT_APPLICABLE;
-        result[MEMBER_TYPE_IDX] = shortName(pv.getType());
-        result[MEMBER_NAME_IDX] = pv.getName();
-        try {
-            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(pv.getValue());
-        } catch (Exception e) {
-            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
-        }
-        return withoutNulls(result);
-    }
-
-    protected Class getClassUnderInspection() {
-        return objectUnderInspection.getClass();
-    }
-
-    public static String shortName(Class clazz) {
-        if (null == clazz) return NOT_APPLICABLE;
-        String className = clazz.getName();
-        if (null == clazz.getPackage()) return className;
-        String packageName = clazz.getPackage().getName();
-        int offset = packageName.length();
-        if (offset > 0) offset++;
-        className = className.substring(offset);
-        return className;
-    }
-
-    protected String[] methodInfo(Method method) {
-        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
-        int mod = method.getModifiers();
-        result[MEMBER_ORIGIN_IDX] = JAVA;
-        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass());
-        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
-        result[MEMBER_NAME_IDX] = method.getName();
-        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
-        Class[] params = method.getParameterTypes();
-        StringBuilder sb = new StringBuilder();
-        for (int j = 0; j < params.length; j++) {
-            sb.append(shortName(params[j]));
-            if (j < (params.length - 1)) sb.append(", ");
-        }
-        result[MEMBER_PARAMS_IDX] = sb.toString();
-        sb.setLength(0);
-        Class[] exceptions = method.getExceptionTypes();
-        for (int k = 0; k < exceptions.length; k++) {
-            sb.append(shortName(exceptions[k]));
-            if (k < (exceptions.length - 1)) sb.append(", ");
-        }
-        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
-        return withoutNulls(result);
-    }
-
-    protected String[] methodInfo(Constructor ctor) {
-        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
-        int mod = ctor.getModifiers();
-        result[MEMBER_ORIGIN_IDX] = JAVA;
-        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
-        result[MEMBER_DECLARER_IDX] = shortName(ctor.getDeclaringClass());
-        result[MEMBER_TYPE_IDX] = shortName(ctor.getDeclaringClass());
-        result[MEMBER_NAME_IDX] = ctor.getName();
-        Class[] params = ctor.getParameterTypes();
-        StringBuilder sb = new StringBuilder();
-        for (int j = 0; j < params.length; j++) {
-            sb.append(shortName(params[j]));
-            if (j < (params.length - 1)) sb.append(", ");
-        }
-        result[MEMBER_PARAMS_IDX] = sb.toString();
-        sb.setLength(0);
-        Class[] exceptions = ctor.getExceptionTypes();
-        for (int k = 0; k < exceptions.length; k++) {
-            sb.append(shortName(exceptions[k]));
-            if (k < (exceptions.length - 1)) sb.append(", ");
-        }
-        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
-        return withoutNulls(result);
-    }
-
-    protected String[] methodInfo(MetaMethod method) {
-        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
-        int mod = method.getModifiers();
-        result[MEMBER_ORIGIN_IDX] = GROOVY;
-        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
-        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass().getTheClass());
-        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
-        result[MEMBER_NAME_IDX] = method.getName();
-        CachedClass[] params = method.getParameterTypes();
-        StringBuilder sb = new StringBuilder();
-        for (int j = 0; j < params.length; j++) {
-            sb.append(shortName(params[j].getTheClass()));
-            if (j < (params.length - 1)) sb.append(", ");
-        }
-        result[MEMBER_PARAMS_IDX] = sb.toString();
-        result[MEMBER_EXCEPTIONS_IDX] = NOT_APPLICABLE; // no exception info for Groovy MetaMethods
-        return withoutNulls(result);
-    }
-
-    protected String[] withoutNulls(String[] toNormalize) {
-        for (int i = 0; i < toNormalize.length; i++) {
-            String s = toNormalize[i];
-            if (null == s) toNormalize[i] = NOT_APPLICABLE;
-        }
-        return toNormalize;
-    }
-
-    public static void print(Object[] memberInfo) {
-        print(System.out, memberInfo);
-    }
-
-    static void print(final PrintStream out, Object[] memberInfo) {
-        for (int i = 0; i < memberInfo.length; i++) {
-            String[] metaMethod = (String[]) memberInfo[i];
-            out.print(i + ":\t");
-            for (String s : metaMethod) {
-                out.print(s + " ");
-            }
-            out.println("");
-        }
-    }
-
-    public static Collection sort(List<Object> memberInfo) {
-        Collections.sort(memberInfo, new MemberComparator());
-        return memberInfo;
-    }
-
-    public static class MemberComparator implements Comparator<Object>, Serializable {
-        private static final long serialVersionUID = -7691851726606749541L;
-
-        public int compare(Object a, Object b) {
-            String[] aStr = (String[]) a;
-            String[] bStr = (String[]) b;
-            int result = aStr[Inspector.MEMBER_NAME_IDX].compareTo(bStr[Inspector.MEMBER_NAME_IDX]);
-            if (0 != result) return result;
-            result = aStr[Inspector.MEMBER_TYPE_IDX].compareTo(bStr[Inspector.MEMBER_TYPE_IDX]);
-            if (0 != result) return result;
-            result = aStr[Inspector.MEMBER_PARAMS_IDX].compareTo(bStr[Inspector.MEMBER_PARAMS_IDX]);
-            if (0 != result) return result;
-            result = aStr[Inspector.MEMBER_DECLARER_IDX].compareTo(bStr[Inspector.MEMBER_DECLARER_IDX]);
-            if (0 != result) return result;
-            result = aStr[Inspector.MEMBER_MODIFIER_IDX].compareTo(bStr[Inspector.MEMBER_MODIFIER_IDX]);
-            if (0 != result) return result;
-            result = aStr[Inspector.MEMBER_ORIGIN_IDX].compareTo(bStr[Inspector.MEMBER_ORIGIN_IDX]);
-            return result;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/inspect/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/inspect/package.html b/src/main/groovy/inspect/package.html
deleted file mode 100644
index 6d80c2b..0000000
--- a/src/main/groovy/inspect/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-
-     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 groovy.inspect.*</title>
-  </head>
-  <body>
-    <p>Classes for inspecting object properties through introspection.</p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/EncodingAwareBufferedWriter.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/EncodingAwareBufferedWriter.java b/src/main/groovy/io/EncodingAwareBufferedWriter.java
deleted file mode 100644
index 2faaaeb..0000000
--- a/src/main/groovy/io/EncodingAwareBufferedWriter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  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 groovy.io;
-
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-
-/**
- * A buffered writer only for OutputStreamWriter that is aware of
- * the encoding of the OutputStreamWriter.
- *
- * @author Paul King
- */
-
-public class EncodingAwareBufferedWriter extends BufferedWriter {
-    private final OutputStreamWriter out;
-    public EncodingAwareBufferedWriter(OutputStreamWriter out) {
-        super(out);
-        this.out = out;
-    }
-
-    /**
-     * The encoding as returned by the underlying OutputStreamWriter. Can be the historical name.
-     *
-     * @return the encoding
-     * @see java.io.OutputStreamWriter#getEncoding()
-     */
-    public String getEncoding() {
-        return out.getEncoding();
-    }
-
-    /**
-     * The encoding as returned by the underlying OutputStreamWriter. Will be the preferred name.
-     *
-     * @return the encoding
-     * @see java.io.OutputStreamWriter#getEncoding()
-     */
-    public String getNormalizedEncoding() {
-        return Charset.forName(getEncoding()).name();
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/io/FileType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/io/FileType.java b/src/main/groovy/io/FileType.java
deleted file mode 100644
index 18727e4..0000000
--- a/src/main/groovy/io/FileType.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  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 groovy.io;
-
-/**
- * Represents particular files of interest.
- */
-public enum FileType {
-    /** Represents normal files */
-    FILES,
-    /** Represents directories */
-    DIRECTORIES,
-    /** Represents both normal files and directories */
-    ANY
-}


[47/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
Move source files to proper packages


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/0ad8c07c
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/0ad8c07c
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/0ad8c07c

Branch: refs/heads/GROOVY_2_5_X
Commit: 0ad8c07c233a676ca6e71d04afe783bd560376c7
Parents: b464b23
Author: sunlan <su...@apache.org>
Authored: Wed Dec 20 12:28:56 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Wed Dec 20 12:28:57 2017 +0800

----------------------------------------------------------------------
 src/main/groovy/ASTTestTransformation.groovy    |  233 --
 .../groovy/ASTTransformationCustomizer.groovy   |  301 --
 .../ASTTransformationCustomizerFactory.groovy   |   60 -
 src/main/groovy/AstBuilder.groovy               |  145 -
 src/main/groovy/AstHelper.groovy                |   76 -
 src/main/groovy/AstSpecificationCompiler.groovy | 1080 -----
 src/main/groovy/AstStringCompiler.groovy        |   63 -
 src/main/groovy/CollectRecursiveCalls.groovy    |   62 -
 .../groovy/CompilerCustomizationBuilder.groovy  |   64 -
 ...itionalInterruptibleASTTransformation.groovy |  145 -
 src/main/groovy/GrapeMain.groovy                |  308 --
 src/main/groovy/HasRecursiveCalls.groovy        |   64 -
 src/main/groovy/InWhileLoopWrapper.groovy       |   81 -
 src/main/groovy/RecursivenessTester.groovy      |  100 -
 src/main/groovy/ReturnAdderForClosures.groovy   |   48 -
 .../ReturnStatementToIterationConverter.groovy  |  148 -
 src/main/groovy/StatementReplacer.groovy        |  109 -
 src/main/groovy/StringUtil.groovy               |   57 -
 .../TailRecursiveASTTransformation.groovy       |  261 --
 .../groovy/TernaryToIfStatementConverter.groovy |   42 -
 .../ThreadInterruptibleASTTransformation.groovy |   98 -
 .../TimedInterruptibleASTTransformation.groovy  |  321 --
 src/main/groovy/TransformTestHelper.groovy      |  123 -
 src/main/groovy/VariableAccessReplacer.groovy   |   73 -
 .../groovy/VariableExpressionReplacer.groovy    |  171 -
 .../groovy/VariableExpressionTransformer.groovy |   47 -
 src/main/groovy/beans/Bindable.java             |  116 -
 .../groovy/beans/BindableASTTransformation.java |  428 --
 .../groovy/beans/DefaultPropertyAccessor.java   |   34 -
 .../groovy/beans/DefaultPropertyReader.java     |   32 -
 .../groovy/beans/DefaultPropertyWriter.java     |   32 -
 src/main/groovy/beans/ListenerList.groovy       |  131 -
 .../beans/ListenerListASTTransformation.groovy  |  384 --
 src/main/groovy/beans/PropertyAccessor.java     |   25 -
 src/main/groovy/beans/PropertyReader.java       |   26 -
 src/main/groovy/beans/PropertyWriter.java       |   26 -
 src/main/groovy/beans/Vetoable.java             |  113 -
 .../groovy/beans/VetoableASTTransformation.java |  444 --
 src/main/groovy/cli/CliBuilderException.groovy  |   24 -
 src/main/groovy/cli/Option.java                 |  105 -
 src/main/groovy/cli/OptionField.groovy          |   27 -
 src/main/groovy/cli/TypedOption.java            |   27 -
 src/main/groovy/cli/Unparsed.java               |   39 -
 src/main/groovy/cli/UnparsedField.groovy        |   27 -
 src/main/groovy/genArrayAccess.groovy           |  146 -
 src/main/groovy/genArrays.groovy                |   53 -
 src/main/groovy/genDgmMath.groovy               |   87 -
 src/main/groovy/genMathModification.groovy      |  133 -
 .../grape/GrabAnnotationTransformation.java     |  639 ---
 src/main/groovy/grape/Grape.java                |  236 --
 src/main/groovy/grape/GrapeEngine.java          |   46 -
 src/main/groovy/grape/GrapeIvy.groovy           |  729 ----
 src/main/groovy/groovy/beans/Bindable.java      |  116 +
 .../groovy/beans/BindableASTTransformation.java |  428 ++
 .../groovy/beans/DefaultPropertyAccessor.java   |   34 +
 .../groovy/beans/DefaultPropertyReader.java     |   32 +
 .../groovy/beans/DefaultPropertyWriter.java     |   32 +
 .../groovy/groovy/beans/ListenerList.groovy     |  131 +
 .../beans/ListenerListASTTransformation.groovy  |  384 ++
 .../groovy/groovy/beans/PropertyAccessor.java   |   25 +
 .../groovy/groovy/beans/PropertyReader.java     |   26 +
 .../groovy/groovy/beans/PropertyWriter.java     |   26 +
 src/main/groovy/groovy/beans/Vetoable.java      |  113 +
 .../groovy/beans/VetoableASTTransformation.java |  444 ++
 .../groovy/cli/CliBuilderException.groovy       |   24 +
 src/main/groovy/groovy/cli/Option.java          |  105 +
 src/main/groovy/groovy/cli/OptionField.groovy   |   27 +
 src/main/groovy/groovy/cli/TypedOption.java     |   27 +
 src/main/groovy/groovy/cli/Unparsed.java        |   39 +
 src/main/groovy/groovy/cli/UnparsedField.groovy |   27 +
 .../grape/GrabAnnotationTransformation.java     |  639 +++
 src/main/groovy/groovy/grape/Grape.java         |  236 ++
 src/main/groovy/groovy/grape/GrapeEngine.java   |   46 +
 src/main/groovy/groovy/grape/GrapeIvy.groovy    |  729 ++++
 src/main/groovy/groovy/inspect/Inspector.java   |  348 ++
 src/main/groovy/groovy/inspect/package.html     |   28 +
 .../groovy/io/EncodingAwareBufferedWriter.java  |   58 +
 src/main/groovy/groovy/io/FileType.java         |   31 +
 src/main/groovy/groovy/io/FileVisitResult.java  |   35 +
 .../groovy/groovy/io/GroovyPrintStream.java     |  130 +
 .../groovy/groovy/io/GroovyPrintWriter.java     |  101 +
 src/main/groovy/groovy/io/LineColumnReader.java |  252 ++
 .../groovy/groovy/io/PlatformLineWriter.java    |   64 +
 src/main/groovy/groovy/io/package.html          |   28 +
 .../groovy/groovy/lang/AdaptingMetaClass.java   |   43 +
 .../groovy/lang/BenchmarkInterceptor.java       |  126 +
 src/main/groovy/groovy/lang/Binding.java        |  122 +
 src/main/groovy/groovy/lang/Buildable.java      |   24 +
 src/main/groovy/groovy/lang/Category.java       |  105 +
 src/main/groovy/groovy/lang/Closure.java        | 1054 +++++
 .../groovy/groovy/lang/ClosureException.java    |   38 +
 .../groovy/lang/ClosureInvokingMethod.java      |   48 +
 src/main/groovy/groovy/lang/Delegate.java       |  218 +
 src/main/groovy/groovy/lang/DelegatesTo.java    |   96 +
 .../groovy/groovy/lang/DelegatingMetaClass.java |  308 ++
 .../groovy/lang/DeprecationException.java       |   43 +
 src/main/groovy/groovy/lang/EmptyRange.java     |  214 +
 .../groovy/groovy/lang/ExpandoMetaClass.java    | 1510 +++++++
 .../lang/ExpandoMetaClassCreationHandle.java    |   95 +
 src/main/groovy/groovy/lang/GString.java        |  245 ++
 .../groovy/lang/GeneratedGroovyProxy.java       |   34 +
 src/main/groovy/groovy/lang/Grab.java           |  143 +
 src/main/groovy/groovy/lang/GrabConfig.java     |  117 +
 src/main/groovy/groovy/lang/GrabExclude.java    |   61 +
 src/main/groovy/groovy/lang/GrabResolver.java   |   86 +
 src/main/groovy/groovy/lang/Grapes.java         |   71 +
 src/main/groovy/groovy/lang/GroovyCallable.java |   32 +
 .../groovy/groovy/lang/GroovyClassLoader.java   | 1099 +++++
 .../groovy/groovy/lang/GroovyCodeSource.java    |  266 ++
 .../groovy/groovy/lang/GroovyInterceptable.java |   28 +
 src/main/groovy/groovy/lang/GroovyObject.java   |   68 +
 .../groovy/groovy/lang/GroovyObjectSupport.java |   63 +
 .../groovy/lang/GroovyResourceLoader.java       |   39 +
 .../groovy/lang/GroovyRuntimeException.java     |   88 +
 src/main/groovy/groovy/lang/GroovyShell.java    |  611 +++
 src/main/groovy/groovy/lang/GroovySystem.java   |  103 +
 .../lang/IllegalPropertyAccessException.java    |   49 +
 .../IncorrectClosureArgumentsException.java     |   60 +
 src/main/groovy/groovy/lang/IntRange.java       |  440 ++
 src/main/groovy/groovy/lang/Interceptor.java    |   52 +
 src/main/groovy/groovy/lang/Lazy.java           |  156 +
 .../groovy/groovy/lang/ListWithDefault.java     |  257 ++
 src/main/groovy/groovy/lang/MapWithDefault.java |  105 +
 .../groovy/lang/MetaArrayLengthProperty.java    |   56 +
 .../groovy/groovy/lang/MetaBeanProperty.java    |  156 +
 src/main/groovy/groovy/lang/MetaClass.java      |  207 +
 src/main/groovy/groovy/lang/MetaClassImpl.java  | 3958 ++++++++++++++++++
 .../groovy/groovy/lang/MetaClassRegistry.java   |  192 +
 .../lang/MetaClassRegistryChangeEvent.java      |  104 +
 .../MetaClassRegistryChangeEventListener.java   |   42 +
 .../groovy/groovy/lang/MetaExpandoProperty.java |   55 +
 src/main/groovy/groovy/lang/MetaMethod.java     |  330 ++
 .../groovy/groovy/lang/MetaObjectProtocol.java  |  227 +
 src/main/groovy/groovy/lang/MetaProperty.java   |  102 +
 .../groovy/lang/MissingClassException.java      |   53 +
 .../groovy/lang/MissingFieldException.java      |   67 +
 .../groovy/lang/MissingMethodException.java     |   88 +
 .../groovy/lang/MissingPropertyException.java   |   88 +
 src/main/groovy/groovy/lang/Mixin.java          |   42 +
 .../groovy/groovy/lang/MutableMetaClass.java    |   79 +
 src/main/groovy/groovy/lang/Newify.java         |  109 +
 .../groovy/groovy/lang/NonEmptySequence.java    |   47 +
 src/main/groovy/groovy/lang/NumberRange.java    |  629 +++
 src/main/groovy/groovy/lang/ObjectRange.java    |  539 +++
 src/main/groovy/groovy/lang/ParameterArray.java |   50 +
 .../groovy/lang/PropertyAccessInterceptor.java  |   49 +
 src/main/groovy/groovy/lang/PropertyValue.java  |   49 +
 src/main/groovy/groovy/lang/ProxyMetaClass.java |  242 ++
 src/main/groovy/groovy/lang/Range.java          |  109 +
 .../groovy/lang/ReadOnlyPropertyException.java  |   36 +
 src/main/groovy/groovy/lang/Reference.java      |   82 +
 src/main/groovy/groovy/lang/Script.java         |  231 +
 src/main/groovy/groovy/lang/Sequence.java       |  224 +
 src/main/groovy/groovy/lang/Singleton.java      |   66 +
 .../lang/SpreadListEvaluatingException.java     |   25 +
 src/main/groovy/groovy/lang/SpreadMap.java      |  120 +
 .../lang/SpreadMapEvaluatingException.java      |   25 +
 .../groovy/lang/StringWriterIOException.java    |   37 +
 .../groovy/groovy/lang/TracingInterceptor.java  |  120 +
 .../groovy/groovy/lang/TrampolineClosure.java   |  111 +
 src/main/groovy/groovy/lang/Tuple.java          |   85 +
 src/main/groovy/groovy/lang/Tuple1.java         |   54 +
 src/main/groovy/groovy/lang/Tuple2.java         |   60 +
 src/main/groovy/groovy/lang/Tuple3.java         |   71 +
 src/main/groovy/groovy/lang/Tuple4.java         |   79 +
 src/main/groovy/groovy/lang/Tuple5.java         |   87 +
 src/main/groovy/groovy/lang/Tuple6.java         |   95 +
 src/main/groovy/groovy/lang/Tuple7.java         |  103 +
 src/main/groovy/groovy/lang/Tuple8.java         |  111 +
 src/main/groovy/groovy/lang/Tuple9.java         |  120 +
 src/main/groovy/groovy/lang/Writable.java       |   56 +
 src/main/groovy/groovy/lang/package.html        |   28 +
 .../security/GroovyCodeSourcePermission.java    |   40 +
 src/main/groovy/groovy/security/package.html    |   30 +
 src/main/groovy/groovy/time/BaseDuration.java   |  141 +
 .../groovy/time/DatumDependentDuration.java     |  141 +
 src/main/groovy/groovy/time/Duration.java       |  119 +
 src/main/groovy/groovy/time/TimeCategory.java   |  203 +
 .../groovy/time/TimeDatumDependentDuration.java |   81 +
 src/main/groovy/groovy/time/TimeDuration.java   |  102 +
 src/main/groovy/groovy/time/package.html        |   47 +
 src/main/groovy/groovy/transform/ASTTest.java   |   71 +
 .../groovy/transform/AnnotationCollector.java   |  199 +
 .../transform/AnnotationCollectorMode.java      |   50 +
 src/main/groovy/groovy/transform/AutoClone.java |  281 ++
 .../groovy/groovy/transform/AutoCloneStyle.java |   48 +
 .../groovy/transform/AutoExternalize.groovy     |   66 +
 src/main/groovy/groovy/transform/AutoFinal.java |   99 +
 .../groovy/groovy/transform/AutoImplement.java  |  128 +
 .../groovy/groovy/transform/BaseScript.java     |  154 +
 .../groovy/groovy/transform/Canonical.groovy    |  131 +
 .../groovy/transform/CompilationUnitAware.java  |   30 +
 .../groovy/transform/CompileDynamic.groovy      |   34 +
 .../groovy/groovy/transform/CompileStatic.java  |   63 +
 .../transform/ConditionalInterrupt.groovy       |  155 +
 .../groovy/transform/EqualsAndHashCode.java     |  276 ++
 .../groovy/transform/ExternalizeMethods.java    |   89 +
 .../groovy/transform/ExternalizeVerifier.java   |   62 +
 src/main/groovy/groovy/transform/Field.java     |   55 +
 src/main/groovy/groovy/transform/Generated.java |   32 +
 src/main/groovy/groovy/transform/Immutable.java |  249 ++
 .../groovy/transform/IndexedProperty.java       |  107 +
 .../groovy/transform/InheritConstructors.java   |  169 +
 .../groovy/groovy/transform/MapConstructor.java |  128 +
 src/main/groovy/groovy/transform/Memoized.java  |  145 +
 .../groovy/groovy/transform/PackageScope.java   |   71 +
 .../groovy/transform/PackageScopeTarget.java    |   47 +
 src/main/groovy/groovy/transform/SelfType.java  |   82 +
 src/main/groovy/groovy/transform/Sortable.java  |  179 +
 src/main/groovy/groovy/transform/SourceURI.java |   55 +
 .../groovy/groovy/transform/Synchronized.java   |  170 +
 .../groovy/transform/TailRecursive.groovy       |   87 +
 .../groovy/transform/ThreadInterrupt.groovy     |  148 +
 .../groovy/transform/TimedInterrupt.groovy      |  142 +
 src/main/groovy/groovy/transform/ToString.java  |  339 ++
 src/main/groovy/groovy/transform/Trait.java     |   38 +
 .../groovy/transform/TupleConstructor.java      |  278 ++
 .../groovy/groovy/transform/TypeChecked.java    |   70 +
 .../groovy/transform/TypeCheckingMode.java      |   31 +
 src/main/groovy/groovy/transform/Undefined.java |   37 +
 .../groovy/groovy/transform/WithReadLock.java   |  107 +
 .../groovy/groovy/transform/WithWriteLock.java  |  107 +
 .../groovy/transform/builder/Builder.java       |  160 +
 .../transform/builder/DefaultStrategy.java      |  293 ++
 .../transform/builder/ExternalStrategy.java     |  158 +
 .../transform/builder/InitializerStrategy.java  |  388 ++
 .../transform/builder/SimpleStrategy.java       |  132 +
 .../groovy/transform/stc/ClosureParams.java     |   64 +
 .../stc/ClosureSignatureConflictResolver.java   |   54 +
 .../transform/stc/ClosureSignatureHint.java     |  144 +
 .../groovy/groovy/transform/stc/FirstParam.java |   93 +
 .../transform/stc/FromAbstractTypeMethods.java  |   68 +
 .../groovy/groovy/transform/stc/FromString.java |   80 +
 .../stc/IncorrectTypeHintException.java         |   32 +
 .../transform/stc/MapEntryOrKeyValue.java       |  119 +
 .../transform/stc/PickAnyArgumentHint.java      |   75 +
 .../groovy/transform/stc/PickFirstResolver.java |   45 +
 .../groovy/transform/stc/SecondParam.java       |   93 +
 .../groovy/groovy/transform/stc/SimpleType.java |   36 +
 .../stc/SingleSignatureClosureHint.java         |   44 +
 .../groovy/groovy/transform/stc/ThirdParam.java |   94 +
 src/main/groovy/groovy/ui/GroovyMain.java       |  597 +++
 .../groovy/groovy/ui/GroovySocketServer.java    |  226 +
 .../groovy/groovy/util/AbstractFactory.java     |   63 +
 .../groovy/groovy/util/BufferedIterator.java    |   31 +
 src/main/groovy/groovy/util/BuilderSupport.java |  228 +
 src/main/groovy/groovy/util/CharsetToolkit.java |  419 ++
 src/main/groovy/groovy/util/CliBuilder.groovy   |  798 ++++
 .../groovy/groovy/util/ClosureComparator.java   |   45 +
 src/main/groovy/groovy/util/ConfigObject.java   |  425 ++
 .../groovy/groovy/util/ConfigSlurper.groovy     |  309 ++
 .../groovy/groovy/util/DelegatingScript.java    |  141 +
 src/main/groovy/groovy/util/Eval.java           |  124 +
 src/main/groovy/groovy/util/Expando.java        |  175 +
 src/main/groovy/groovy/util/Factory.java        |   90 +
 .../groovy/util/FactoryBuilderSupport.java      | 1363 ++++++
 .../groovy/util/FileNameByRegexFinder.groovy    |   43 +
 .../groovy/groovy/util/FileTreeBuilder.groovy   |  183 +
 .../groovy/groovy/util/GroovyCollections.java   |  293 ++
 .../groovy/groovy/util/GroovyScriptEngine.java  |  694 +++
 .../groovy/groovy/util/IFileNameFinder.java     |   26 +
 src/main/groovy/groovy/util/IndentPrinter.java  |  234 ++
 src/main/groovy/groovy/util/MapEntry.java       |   83 +
 src/main/groovy/groovy/util/Node.java           |  787 ++++
 src/main/groovy/groovy/util/NodeBuilder.java    |   57 +
 src/main/groovy/groovy/util/NodeList.java       |  202 +
 src/main/groovy/groovy/util/NodePrinter.java    |  130 +
 .../groovy/groovy/util/ObjectGraphBuilder.java  |  857 ++++
 src/main/groovy/groovy/util/ObservableList.java |  570 +++
 src/main/groovy/groovy/util/ObservableMap.java  |  410 ++
 src/main/groovy/groovy/util/ObservableSet.java  |  427 ++
 src/main/groovy/groovy/util/OrderBy.java        |   96 +
 .../groovy/util/PermutationGenerator.java       |  149 +
 src/main/groovy/groovy/util/Proxy.java          |   70 +
 src/main/groovy/groovy/util/ProxyGenerator.java |  339 ++
 .../groovy/groovy/util/ResourceConnector.java   |   37 +
 .../groovy/groovy/util/ResourceException.java   |   56 +
 .../groovy/groovy/util/ScriptException.java     |   55 +
 .../groovy/groovy/util/logging/Commons.java     |  108 +
 src/main/groovy/groovy/util/logging/Log.java    |  124 +
 src/main/groovy/groovy/util/logging/Log4j.java  |  119 +
 src/main/groovy/groovy/util/logging/Log4j2.java |  105 +
 src/main/groovy/groovy/util/logging/Slf4j.java  |  108 +
 src/main/groovy/groovy/util/package.html        |   28 +
 src/main/groovy/groovy/xml/QName.java           |  287 ++
 src/main/groovy/inspect/Inspector.java          |  348 --
 src/main/groovy/inspect/package.html            |   28 -
 .../groovy/io/EncodingAwareBufferedWriter.java  |   58 -
 src/main/groovy/io/FileType.java                |   31 -
 src/main/groovy/io/FileVisitResult.java         |   35 -
 src/main/groovy/io/GroovyPrintStream.java       |  130 -
 src/main/groovy/io/GroovyPrintWriter.java       |  101 -
 src/main/groovy/io/LineColumnReader.java        |  252 --
 src/main/groovy/io/PlatformLineWriter.java      |   64 -
 src/main/groovy/io/package.html                 |   28 -
 src/main/groovy/lang/AdaptingMetaClass.java     |   43 -
 src/main/groovy/lang/BenchmarkInterceptor.java  |  126 -
 src/main/groovy/lang/Binding.java               |  122 -
 src/main/groovy/lang/Buildable.java             |   24 -
 src/main/groovy/lang/Category.java              |  105 -
 src/main/groovy/lang/Closure.java               | 1054 -----
 src/main/groovy/lang/ClosureException.java      |   38 -
 src/main/groovy/lang/ClosureInvokingMethod.java |   48 -
 src/main/groovy/lang/Delegate.java              |  218 -
 src/main/groovy/lang/DelegatesTo.java           |   96 -
 src/main/groovy/lang/DelegatingMetaClass.java   |  308 --
 src/main/groovy/lang/DeprecationException.java  |   43 -
 src/main/groovy/lang/EmptyRange.java            |  214 -
 src/main/groovy/lang/ExpandoMetaClass.java      | 1510 -------
 .../lang/ExpandoMetaClassCreationHandle.java    |   95 -
 src/main/groovy/lang/GString.java               |  245 --
 src/main/groovy/lang/GeneratedGroovyProxy.java  |   34 -
 src/main/groovy/lang/Grab.java                  |  143 -
 src/main/groovy/lang/GrabConfig.java            |  117 -
 src/main/groovy/lang/GrabExclude.java           |   61 -
 src/main/groovy/lang/GrabResolver.java          |   86 -
 src/main/groovy/lang/Grapes.java                |   71 -
 src/main/groovy/lang/GroovyCallable.java        |   32 -
 src/main/groovy/lang/GroovyClassLoader.java     | 1099 -----
 src/main/groovy/lang/GroovyCodeSource.java      |  266 --
 src/main/groovy/lang/GroovyInterceptable.java   |   28 -
 src/main/groovy/lang/GroovyObject.java          |   68 -
 src/main/groovy/lang/GroovyObjectSupport.java   |   63 -
 src/main/groovy/lang/GroovyResourceLoader.java  |   39 -
 .../groovy/lang/GroovyRuntimeException.java     |   88 -
 src/main/groovy/lang/GroovyShell.java           |  611 ---
 src/main/groovy/lang/GroovySystem.java          |  103 -
 .../lang/IllegalPropertyAccessException.java    |   49 -
 .../IncorrectClosureArgumentsException.java     |   60 -
 src/main/groovy/lang/IntRange.java              |  440 --
 src/main/groovy/lang/Interceptor.java           |   52 -
 src/main/groovy/lang/Lazy.java                  |  156 -
 src/main/groovy/lang/ListWithDefault.java       |  257 --
 src/main/groovy/lang/MapWithDefault.java        |  105 -
 .../groovy/lang/MetaArrayLengthProperty.java    |   56 -
 src/main/groovy/lang/MetaBeanProperty.java      |  156 -
 src/main/groovy/lang/MetaClass.java             |  207 -
 src/main/groovy/lang/MetaClassImpl.java         | 3958 ------------------
 src/main/groovy/lang/MetaClassRegistry.java     |  192 -
 .../lang/MetaClassRegistryChangeEvent.java      |  104 -
 .../MetaClassRegistryChangeEventListener.java   |   42 -
 src/main/groovy/lang/MetaExpandoProperty.java   |   55 -
 src/main/groovy/lang/MetaMethod.java            |  330 --
 src/main/groovy/lang/MetaObjectProtocol.java    |  227 -
 src/main/groovy/lang/MetaProperty.java          |  102 -
 src/main/groovy/lang/MissingClassException.java |   53 -
 src/main/groovy/lang/MissingFieldException.java |   67 -
 .../groovy/lang/MissingMethodException.java     |   88 -
 .../groovy/lang/MissingPropertyException.java   |   88 -
 src/main/groovy/lang/Mixin.java                 |   42 -
 src/main/groovy/lang/MutableMetaClass.java      |   79 -
 src/main/groovy/lang/Newify.java                |  109 -
 src/main/groovy/lang/NonEmptySequence.java      |   47 -
 src/main/groovy/lang/NumberRange.java           |  629 ---
 src/main/groovy/lang/ObjectRange.java           |  539 ---
 src/main/groovy/lang/ParameterArray.java        |   50 -
 .../groovy/lang/PropertyAccessInterceptor.java  |   49 -
 src/main/groovy/lang/PropertyValue.java         |   49 -
 src/main/groovy/lang/ProxyMetaClass.java        |  242 --
 src/main/groovy/lang/Range.java                 |  109 -
 .../groovy/lang/ReadOnlyPropertyException.java  |   36 -
 src/main/groovy/lang/Reference.java             |   82 -
 src/main/groovy/lang/Script.java                |  231 -
 src/main/groovy/lang/Sequence.java              |  224 -
 src/main/groovy/lang/Singleton.java             |   66 -
 .../lang/SpreadListEvaluatingException.java     |   25 -
 src/main/groovy/lang/SpreadMap.java             |  120 -
 .../lang/SpreadMapEvaluatingException.java      |   25 -
 .../groovy/lang/StringWriterIOException.java    |   37 -
 src/main/groovy/lang/TracingInterceptor.java    |  120 -
 src/main/groovy/lang/TrampolineClosure.java     |  111 -
 src/main/groovy/lang/Tuple.java                 |   85 -
 src/main/groovy/lang/Tuple1.java                |   54 -
 src/main/groovy/lang/Tuple2.java                |   60 -
 src/main/groovy/lang/Tuple3.java                |   71 -
 src/main/groovy/lang/Tuple4.java                |   79 -
 src/main/groovy/lang/Tuple5.java                |   87 -
 src/main/groovy/lang/Tuple6.java                |   95 -
 src/main/groovy/lang/Tuple7.java                |  103 -
 src/main/groovy/lang/Tuple8.java                |  111 -
 src/main/groovy/lang/Tuple9.java                |  120 -
 src/main/groovy/lang/Writable.java              |   56 -
 src/main/groovy/lang/package.html               |   28 -
 .../groovy/ast/builder/AstBuilder.groovy        |  145 +
 .../ast/builder/AstSpecificationCompiler.groovy | 1080 +++++
 .../groovy/ast/builder/AstStringCompiler.groovy |   63 +
 .../groovy/classgen/genArrayAccess.groovy       |  146 +
 .../codehaus/groovy/classgen/genArrays.groovy   |   53 +
 .../codehaus/groovy/classgen/genDgmMath.groovy  |   87 +
 .../groovy/classgen/genMathModification.groovy  |  133 +
 .../ASTTransformationCustomizer.groovy          |  301 ++
 .../ASTTransformationCustomizerFactory.groovy   |   60 +
 .../builder/CompilerCustomizationBuilder.groovy |   64 +
 .../org/codehaus/groovy/tools/GrapeMain.groovy  |  308 ++
 .../groovy/tools/ast/TransformTestHelper.groovy |  123 +
 .../transform/ASTTestTransformation.groovy      |  233 ++
 ...itionalInterruptibleASTTransformation.groovy |  145 +
 .../ThreadInterruptibleASTTransformation.groovy |   98 +
 .../TimedInterruptibleASTTransformation.groovy  |  321 ++
 .../groovy/transform/tailrec/AstHelper.groovy   |   76 +
 .../tailrec/CollectRecursiveCalls.groovy        |   62 +
 .../transform/tailrec/HasRecursiveCalls.groovy  |   64 +
 .../transform/tailrec/InWhileLoopWrapper.groovy |   81 +
 .../tailrec/RecursivenessTester.groovy          |  100 +
 .../tailrec/ReturnAdderForClosures.groovy       |   48 +
 .../ReturnStatementToIterationConverter.groovy  |  148 +
 .../transform/tailrec/StatementReplacer.groovy  |  109 +
 .../TailRecursiveASTTransformation.groovy       |  261 ++
 .../TernaryToIfStatementConverter.groovy        |   42 +
 .../tailrec/VariableAccessReplacer.groovy       |   73 +
 .../tailrec/VariableExpressionReplacer.groovy   |  171 +
 .../VariableExpressionTransformer.groovy        |   47 +
 .../org/codehaus/groovy/util/StringUtil.groovy  |   57 +
 .../security/GroovyCodeSourcePermission.java    |   40 -
 src/main/groovy/security/package.html           |   30 -
 src/main/groovy/time/BaseDuration.java          |  141 -
 .../groovy/time/DatumDependentDuration.java     |  141 -
 src/main/groovy/time/Duration.java              |  119 -
 src/main/groovy/time/TimeCategory.java          |  203 -
 .../groovy/time/TimeDatumDependentDuration.java |   81 -
 src/main/groovy/time/TimeDuration.java          |  102 -
 src/main/groovy/time/package.html               |   47 -
 src/main/groovy/transform/ASTTest.java          |   71 -
 .../groovy/transform/AnnotationCollector.java   |  199 -
 .../transform/AnnotationCollectorMode.java      |   50 -
 src/main/groovy/transform/AutoClone.java        |  281 --
 src/main/groovy/transform/AutoCloneStyle.java   |   48 -
 .../groovy/transform/AutoExternalize.groovy     |   66 -
 src/main/groovy/transform/AutoFinal.java        |   99 -
 src/main/groovy/transform/AutoImplement.java    |  128 -
 src/main/groovy/transform/BaseScript.java       |  154 -
 src/main/groovy/transform/Canonical.groovy      |  131 -
 .../groovy/transform/CompilationUnitAware.java  |   30 -
 src/main/groovy/transform/CompileDynamic.groovy |   34 -
 src/main/groovy/transform/CompileStatic.java    |   63 -
 .../transform/ConditionalInterrupt.groovy       |  155 -
 .../groovy/transform/EqualsAndHashCode.java     |  276 --
 .../groovy/transform/ExternalizeMethods.java    |   89 -
 .../groovy/transform/ExternalizeVerifier.java   |   62 -
 src/main/groovy/transform/Field.java            |   55 -
 src/main/groovy/transform/Generated.java        |   32 -
 src/main/groovy/transform/Immutable.java        |  249 --
 src/main/groovy/transform/IndexedProperty.java  |  107 -
 .../groovy/transform/InheritConstructors.java   |  169 -
 src/main/groovy/transform/MapConstructor.java   |  128 -
 src/main/groovy/transform/Memoized.java         |  145 -
 src/main/groovy/transform/PackageScope.java     |   71 -
 .../groovy/transform/PackageScopeTarget.java    |   47 -
 src/main/groovy/transform/SelfType.java         |   82 -
 src/main/groovy/transform/Sortable.java         |  179 -
 src/main/groovy/transform/SourceURI.java        |   55 -
 src/main/groovy/transform/Synchronized.java     |  170 -
 src/main/groovy/transform/TailRecursive.groovy  |   87 -
 .../groovy/transform/ThreadInterrupt.groovy     |  148 -
 src/main/groovy/transform/TimedInterrupt.groovy |  142 -
 src/main/groovy/transform/ToString.java         |  339 --
 src/main/groovy/transform/Trait.java            |   38 -
 src/main/groovy/transform/TupleConstructor.java |  278 --
 src/main/groovy/transform/TypeChecked.java      |   70 -
 src/main/groovy/transform/TypeCheckingMode.java |   31 -
 src/main/groovy/transform/Undefined.java        |   37 -
 src/main/groovy/transform/WithReadLock.java     |  107 -
 src/main/groovy/transform/WithWriteLock.java    |  107 -
 src/main/groovy/transform/builder/Builder.java  |  160 -
 .../transform/builder/DefaultStrategy.java      |  293 --
 .../transform/builder/ExternalStrategy.java     |  158 -
 .../transform/builder/InitializerStrategy.java  |  388 --
 .../transform/builder/SimpleStrategy.java       |  132 -
 .../groovy/transform/stc/ClosureParams.java     |   64 -
 .../stc/ClosureSignatureConflictResolver.java   |   54 -
 .../transform/stc/ClosureSignatureHint.java     |  144 -
 src/main/groovy/transform/stc/FirstParam.java   |   93 -
 .../transform/stc/FromAbstractTypeMethods.java  |   68 -
 src/main/groovy/transform/stc/FromString.java   |   80 -
 .../stc/IncorrectTypeHintException.java         |   32 -
 .../transform/stc/MapEntryOrKeyValue.java       |  119 -
 .../transform/stc/PickAnyArgumentHint.java      |   75 -
 .../groovy/transform/stc/PickFirstResolver.java |   45 -
 src/main/groovy/transform/stc/SecondParam.java  |   93 -
 src/main/groovy/transform/stc/SimpleType.java   |   36 -
 .../stc/SingleSignatureClosureHint.java         |   44 -
 src/main/groovy/transform/stc/ThirdParam.java   |   94 -
 src/main/groovy/ui/GroovyMain.java              |  597 ---
 src/main/groovy/ui/GroovySocketServer.java      |  226 -
 src/main/groovy/util/AbstractFactory.java       |   63 -
 src/main/groovy/util/BufferedIterator.java      |   31 -
 src/main/groovy/util/BuilderSupport.java        |  228 -
 src/main/groovy/util/CharsetToolkit.java        |  419 --
 src/main/groovy/util/CliBuilder.groovy          |  798 ----
 src/main/groovy/util/ClosureComparator.java     |   45 -
 src/main/groovy/util/ConfigObject.java          |  425 --
 src/main/groovy/util/ConfigSlurper.groovy       |  309 --
 src/main/groovy/util/DelegatingScript.java      |  141 -
 src/main/groovy/util/Eval.java                  |  124 -
 src/main/groovy/util/Expando.java               |  175 -
 src/main/groovy/util/Factory.java               |   90 -
 src/main/groovy/util/FactoryBuilderSupport.java | 1363 ------
 .../groovy/util/FileNameByRegexFinder.groovy    |   43 -
 src/main/groovy/util/FileTreeBuilder.groovy     |  183 -
 src/main/groovy/util/GroovyCollections.java     |  293 --
 src/main/groovy/util/GroovyScriptEngine.java    |  694 ---
 src/main/groovy/util/IFileNameFinder.java       |   26 -
 src/main/groovy/util/IndentPrinter.java         |  234 --
 src/main/groovy/util/MapEntry.java              |   83 -
 src/main/groovy/util/Node.java                  |  787 ----
 src/main/groovy/util/NodeBuilder.java           |   57 -
 src/main/groovy/util/NodeList.java              |  202 -
 src/main/groovy/util/NodePrinter.java           |  130 -
 src/main/groovy/util/ObjectGraphBuilder.java    |  857 ----
 src/main/groovy/util/ObservableList.java        |  570 ---
 src/main/groovy/util/ObservableMap.java         |  410 --
 src/main/groovy/util/ObservableSet.java         |  427 --
 src/main/groovy/util/OrderBy.java               |   96 -
 src/main/groovy/util/PermutationGenerator.java  |  149 -
 src/main/groovy/util/Proxy.java                 |   70 -
 src/main/groovy/util/ProxyGenerator.java        |  339 --
 src/main/groovy/util/ResourceConnector.java     |   37 -
 src/main/groovy/util/ResourceException.java     |   56 -
 src/main/groovy/util/ScriptException.java       |   55 -
 src/main/groovy/util/logging/Commons.java       |  108 -
 src/main/groovy/util/logging/Log.java           |  124 -
 src/main/groovy/util/logging/Log4j.java         |  119 -
 src/main/groovy/util/logging/Log4j2.java        |  105 -
 src/main/groovy/util/logging/Slf4j.java         |  108 -
 src/main/groovy/util/package.html               |   28 -
 src/main/groovy/xml/QName.java                  |  287 --
 526 files changed, 47072 insertions(+), 47072 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ASTTestTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ASTTestTransformation.groovy b/src/main/groovy/ASTTestTransformation.groovy
deleted file mode 100644
index dcfe314..0000000
--- a/src/main/groovy/ASTTestTransformation.groovy
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *  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.transform
-
-import groovy.transform.CompilationUnitAware
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassCodeVisitorSupport
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.PropertyExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.CompilerConfiguration
-import org.codehaus.groovy.control.ErrorCollector
-import org.codehaus.groovy.control.Janitor
-import org.codehaus.groovy.control.ProcessingUnit
-import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.control.customizers.ImportCustomizer
-import org.codehaus.groovy.control.io.ReaderSource
-import org.codehaus.groovy.runtime.MethodClosure
-import org.codehaus.groovy.syntax.SyntaxException
-import org.codehaus.groovy.tools.Utilities
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
-
-@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
-class ASTTestTransformation extends AbstractASTTransformation implements CompilationUnitAware {
-    private CompilationUnit compilationUnit
-
-    void visit(final ASTNode[] nodes, final SourceUnit source) {
-        AnnotationNode annotationNode = nodes[0]
-        def member = annotationNode.getMember('phase')
-        def phase = null
-        if (member) {
-            if (member instanceof VariableExpression) {
-                phase = CompilePhase.valueOf(member.text)
-            } else if (member instanceof PropertyExpression) {
-                phase = CompilePhase.valueOf(member.propertyAsString)
-            }
-            annotationNode.setMember('phase', propX(classX(ClassHelper.make(CompilePhase)), phase.toString()))
-        }
-        member = annotationNode.getMember('value')
-        if (member && !(member instanceof ClosureExpression)) {
-            throw new SyntaxException("ASTTest value must be a closure", member.getLineNumber(), member.getColumnNumber())
-        }
-        if (!member && !annotationNode.getNodeMetaData(ASTTestTransformation)) {
-            throw new SyntaxException("Missing test expression", annotationNode.getLineNumber(), annotationNode.getColumnNumber())
-        }
-        // convert value into node metadata so that the expression doesn't mix up with other AST xforms like type checking
-        annotationNode.putNodeMetaData(ASTTestTransformation, member)
-        annotationNode.getMembers().remove('value')
-
-        def pcallback = compilationUnit.progressCallback
-        def callback = new CompilationUnit.ProgressCallback() {
-            Binding binding = new Binding([:].withDefault {null})
-
-            @Override
-            void call(final ProcessingUnit context, final int phaseRef) {
-                if (phase==null ||  phaseRef == phase.phaseNumber) {
-                    ClosureExpression testClosure = nodes[0].getNodeMetaData(ASTTestTransformation)
-                    StringBuilder sb = new StringBuilder()
-                    for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i++) {
-                        sb.append(source.source.getLine(i, new Janitor())).append('\n')
-                    }
-                    def testSource = sb.substring(testClosure.columnNumber + 1, sb.length())
-                    testSource = testSource.substring(0, testSource.lastIndexOf('}'))
-                    CompilerConfiguration config = new CompilerConfiguration()
-                    def customizer = new ImportCustomizer()
-                    config.addCompilationCustomizers(customizer)
-                    binding['sourceUnit'] = source
-                    binding['node'] = nodes[1]
-                    binding['lookup'] = new MethodClosure(LabelFinder, "lookup").curry(nodes[1])
-                    binding['compilationUnit'] = compilationUnit
-                    binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseRef)
-
-                    GroovyShell shell = new GroovyShell(binding, config)
-
-                    source.AST.imports.each {
-                        customizer.addImport(it.alias, it.type.name)
-                    }
-                    source.AST.starImports.each {
-                        customizer.addStarImports(it.packageName)
-                    }
-                    source.AST.staticImports.each {
-                        customizer.addStaticImport(it.value.alias, it.value.type.name, it.value.fieldName)
-                    }
-                    source.AST.staticStarImports.each {
-                        customizer.addStaticStars(it.value.className)
-                    }
-                    shell.evaluate(testSource)
-                }
-            }
-        }
-        
-        if (pcallback!=null) {
-            if (pcallback instanceof ProgressCallbackChain) {
-                pcallback.addCallback(callback)                
-            } else {
-                pcallback = new ProgressCallbackChain(pcallback, callback)
-            }
-            callback = pcallback
-        }
-        
-        compilationUnit.setProgressCallback(callback)
-
-    }
-
-    void setCompilationUnit(final CompilationUnit unit) {
-        this.compilationUnit = unit
-    }
-
-    private static class AssertionSourceDelegatingSourceUnit extends SourceUnit {
-        private final ReaderSource delegate
-
-        AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration flags, final GroovyClassLoader loader, final ErrorCollector er) {
-            super(name, '', flags, loader, er)
-            delegate = source
-        }
-
-        @Override
-        String getSample(final int line, final int column, final Janitor janitor) {
-            String sample = null;
-            String text = delegate.getLine(line, janitor);
-
-            if (text != null) {
-                if (column > 0) {
-                    String marker = Utilities.repeatString(" ", column - 1) + "^";
-
-                    if (column > 40) {
-                        int start = column - 30 - 1;
-                        int end = (column + 10 > text.length() ? text.length() : column + 10 - 1);
-                        sample = "   " + text.substring(start, end) + Utilities.eol() + "   " +
-                                marker.substring(start, marker.length());
-                    } else {
-                        sample = "   " + text + Utilities.eol() + "   " + marker;
-                    }
-                } else {
-                    sample = text;
-                }
-            }
-
-            return sample;
-
-        }
-
-    }
-    
-    private static class ProgressCallbackChain extends CompilationUnit.ProgressCallback {
-
-        private final List<CompilationUnit.ProgressCallback> chain = new LinkedList<CompilationUnit.ProgressCallback>()
-
-        ProgressCallbackChain(CompilationUnit.ProgressCallback... callbacks) {
-            if (callbacks!=null) {
-                callbacks.each { addCallback(it) }
-            }
-        }
-
-        public void addCallback(CompilationUnit.ProgressCallback callback) {
-            chain << callback
-        }
-        
-        @Override
-        void call(final ProcessingUnit context, final int phase) {
-            chain*.call(context, phase)
-        }
-    }
-
-    public static class LabelFinder extends ClassCodeVisitorSupport {
-
-        public static List<Statement> lookup(MethodNode node, String label) {
-            LabelFinder finder = new LabelFinder(label, null)
-            node.code.visit(finder)
-
-            finder.targets
-        }
-
-        public static List<Statement> lookup(ClassNode node, String label) {
-            LabelFinder finder = new LabelFinder(label, null)
-            node.methods*.code*.visit(finder)
-            node.declaredConstructors*.code*.visit(finder)
-
-            finder.targets
-        }
-
-        private final String label
-        private final SourceUnit unit
-
-        private final List<Statement> targets = new LinkedList<Statement>();
-
-        LabelFinder(final String label, final SourceUnit unit) {
-            this.label = label
-            this.unit = unit;
-        }
-
-        @Override
-        protected SourceUnit getSourceUnit() {
-            unit
-        }
-
-        @Override
-        protected void visitStatement(final Statement statement) {
-            super.visitStatement(statement)
-            if (statement.statementLabel==label) targets << statement
-        }
-
-        List<Statement> getTargets() {
-            return Collections.unmodifiableList(targets)
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ASTTransformationCustomizer.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ASTTransformationCustomizer.groovy b/src/main/groovy/ASTTransformationCustomizer.groovy
deleted file mode 100644
index 7e84968..0000000
--- a/src/main/groovy/ASTTransformationCustomizer.groovy
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *  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.control.customizers
-
-import groovy.transform.CompilationUnitAware
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.AnnotationNode
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.expr.ClassExpression
-import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.ListExpression
-import org.codehaus.groovy.classgen.GeneratorContext
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.CompilePhase
-import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.transform.ASTTransformation
-import org.codehaus.groovy.transform.GroovyASTTransformation
-import org.codehaus.groovy.transform.GroovyASTTransformationClass
-
-import java.lang.annotation.Annotation
-
-/**
- * This customizer allows applying an AST transformation to a source unit with
- * several strategies.
- *
- * Creating a customizer with the {@link ASTTransformationCustomizer#ASTTransformationCustomizer(Class)
- * class constructor} will trigger an AST transformation for
- * each class node of a source unit. However, you cannot pass parameters to the annotation so the default values
- * will be used. Writing :
- * <pre>
- *     def configuration = new CompilerConfiguration()
- *     configuration.addCompilationCustomizers(new ASTTransformationCustomizer(Log))
- *     def shell = new GroovyShell(configuration)
- *     shell.evaluate("""
- *        class MyClass {
- *
- *        }""")
- * </pre>
- *
- * is equivalent to :
- *
- * <pre>
- *     def shell = new GroovyShell()
- *     shell.evaluate("""
- *        &#64;Log
- *        class MyClass {
- *
- *        }""")
- * </pre>
- *
- * The class passed as a constructor parameter must be an AST transformation annotation.
- *
- * Alternatively, you can apply a global AST transformation by calling the
- * {@link ASTTransformationCustomizer#ASTTransformationCustomizer(ASTTransformation) AST transformation
- * constructor}. In that case, the transformation is applied once for the whole source unit.
- *
- * Unlike a global AST transformation declared in the META-INF/services/org.codehaus.groovy.transform.ASTTransformation
- * file, which are applied if the file is in the classpath, using this customizer you'll have the choice to apply
- * your transformation selectively. It can also be useful to debug global AST transformations without having to
- * package your annotation in a jar file.
- *
- * @author Cedric Champeau
- *
- * @since 1.8.0
- * 
- */
-class ASTTransformationCustomizer extends CompilationCustomizer implements CompilationUnitAware {
-    private final AnnotationNode annotationNode;
-    final ASTTransformation transformation
-
-    protected CompilationUnit compilationUnit;
-    private boolean applied = false; // used for global AST transformations
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
-     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
-     * It's assumed that the annotation is not annotated with {@code GroovyASTTransformationClass} and so the
-     * second argument supplies the link to the ASTTransformation class that should be used.
-     * @param transformationAnnotation
-     * @param astTransformationClassName
-     * @param transformationClassLoader
-     */
-    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName, ClassLoader transformationClassLoader) {
-        super(findPhase(transformationAnnotation, astTransformationClassName, transformationClassLoader))
-        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, astTransformationClassName, transformationClassLoader)
-        this.transformation = clazz.newInstance()
-        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation. It's assumed that the annotation
-     * is not annotated with {@code GroovyASTTransformationClass} and so the second argument supplies the link to
-     * the ASTTransformation class that should be used.
-     * @param transformationAnnotation
-     * @param astTransformationClassName
-     */
-    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName) {
-        this(transformationAnnotation, astTransformationClassName, transformationAnnotation.classLoader)
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
-     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
-     * Additionally, you can pass a map of parameters that will be used to parameterize the annotation.
-     * It's assumed that the annotation is not annotated with {@code GroovyASTTransformationClass} and so the
-     * second argument supplies the link to the ASTTransformation class that should be used.
-     * @param transformationAnnotation
-     * @param astTransformationClassName
-     * @param transformationClassLoader
-     */
-    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName, ClassLoader transformationClassLoader) {
-        super(findPhase(transformationAnnotation, astTransformationClassName, transformationClassLoader))
-        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, astTransformationClassName, transformationClassLoader)
-        this.transformation = clazz.newInstance()
-        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
-        setAnnotationParameters(annotationParams)
-    }
-
-    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, String astTransformationClassName) {
-        this(annotationParams, transformationAnnotation, transformationAnnotation.classLoader)
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
-     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
-     * @param transformationAnnotation
-     * @param transformationClassLoader
-     */
-    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation, ClassLoader transformationClassLoader) {
-        super(findPhase(transformationAnnotation, transformationClassLoader))
-        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, transformationClassLoader)
-        this.transformation = clazz.newInstance()
-        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation.
-     * @param transformationAnnotation
-     */
-    ASTTransformationCustomizer(final Class<? extends Annotation> transformationAnnotation) {
-        this(transformationAnnotation, transformationAnnotation.classLoader)
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified transformation.
-     */
-    ASTTransformationCustomizer(final ASTTransformation transformation) {
-        super(findPhase(transformation))
-        this.transformation = transformation
-        this.annotationNode = null
-    }
-
-    /**
-     * Creates an AST transformation customizer using the specified annotation. The transformation classloader can
-     * be used if the transformation class cannot be loaded from the same class loader as the annotation class.
-     * Additionally, you can pass a map of parameters that will be used to parameterize the annotation.
-     * @param transformationAnnotation
-     * @param transformationClassLoader
-     */
-    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation, ClassLoader transformationClassLoader) {
-        super(findPhase(transformationAnnotation, transformationClassLoader))
-        final Class<ASTTransformation> clazz = findASTTranformationClass(transformationAnnotation, transformationClassLoader)
-        this.transformation = clazz.newInstance()
-        this.annotationNode = new AnnotationNode(ClassHelper.make(transformationAnnotation))
-        setAnnotationParameters(annotationParams)
-    }
-
-    ASTTransformationCustomizer(final Map annotationParams, final Class<? extends Annotation> transformationAnnotation) {
-        this(annotationParams, transformationAnnotation, transformationAnnotation.classLoader)
-    }
-
-    ASTTransformationCustomizer(final Map annotationParams, final ASTTransformation transformation) {
-        this(transformation)
-        setAnnotationParameters(annotationParams)
-    }
-
-    void setCompilationUnit(CompilationUnit unit) {
-        compilationUnit = unit
-    }
-
-    private static Class<ASTTransformation> findASTTranformationClass(Class<? extends Annotation> anAnnotationClass, ClassLoader transformationClassLoader) {
-        final GroovyASTTransformationClass annotation = anAnnotationClass.getAnnotation(GroovyASTTransformationClass)
-        if (annotation==null) throw new IllegalArgumentException("Provided class doesn't look like an AST @interface")
-
-        Class[] classes = annotation.classes()
-        String[] classesAsStrings = annotation.value()
-        if (classes.length+classesAsStrings.length>1) {
-            throw new IllegalArgumentException("AST transformation customizer doesn't support AST transforms with multiple classes")
-        }
-        return classes?classes[0]:Class.forName(classesAsStrings[0], true, transformationClassLoader?:anAnnotationClass.classLoader)
-    }
-
-    private static Class<ASTTransformation> findASTTranformationClass(Class<? extends Annotation> anAnnotationClass, String astTransformationClassName, ClassLoader transformationClassLoader) {
-        return Class.forName(astTransformationClassName, true, transformationClassLoader?:anAnnotationClass.classLoader) as Class<ASTTransformation>
-    }
-
-    private static CompilePhase findPhase(ASTTransformation transformation) {
-        if (transformation==null) throw new IllegalArgumentException("Provided transformation must not be null")
-        final Class<?> clazz = transformation.class
-        final GroovyASTTransformation annotation = clazz.getAnnotation(GroovyASTTransformation)
-        if (annotation==null) throw new IllegalArgumentException("Provided ast transformation is not annotated with "+GroovyASTTransformation.name)
-
-        annotation.phase()
-    }
-
-    private static CompilePhase findPhase(Class<? extends Annotation> annotationClass, ClassLoader transformationClassLoader) {
-        Class<ASTTransformation> clazz = findASTTranformationClass(annotationClass, transformationClassLoader);
-
-        findPhase(clazz.newInstance())
-    }
-
-    private static CompilePhase findPhase(Class<? extends Annotation> annotationClass, String astTransformationClassName, ClassLoader transformationClassLoader) {
-        Class<ASTTransformation> clazz = findASTTranformationClass(annotationClass, astTransformationClassName, transformationClassLoader);
-
-        findPhase(clazz.newInstance())
-    }
-
-    /**
-     * Specify annotation parameters. For example, if the annotation is :
-     * <pre>@Log(value='logger')</pre>
-     * You could create an AST transformation customizer and specify the "value" parameter thanks to this method:
-     * <pre>annotationParameters = [value: 'logger']
-     *
-     * Note that you cannot specify annotation closure values directly. If the annotation you want to add takes
-     * a closure as an argument, you will have to set a {@link ClosureExpression} instead. This can be done by either
-     * creating a custom {@link ClosureExpression} from code, or using the {@link org.codehaus.groovy.ast.builder.AstBuilder}.
-     *
-     * Here is an example :
-     * <pre>
-     *        // add @Contract({distance >= 0 })
-     *        customizer = new ASTTransformationCustomizer(Contract)
-     *        final expression = new AstBuilder().buildFromCode(CompilePhase.CONVERSION) {->
-     *            distance >= 0
-     *        }.expression[0]
-     *        customizer.annotationParameters = [value: expression]</pre>
-     *
-     * @param params the annotation parameters
-     *
-     * @since 1.8.1
-     */
-    public void setAnnotationParameters(Map<String,Object> params) {
-        if (params==null || annotationNode==null) return;
-        params.each { key, value ->
-            if (!annotationNode.classNode.getMethod(key)) {
-                throw new IllegalArgumentException("${annotationNode.classNode.name} does not accept any [$key] parameter")
-            }
-            if (value instanceof Closure) {
-                throw new IllegalArgumentException("Direct usage of closure is not supported by the AST " +
-                "compilation customizer. Please use ClosureExpression instead.")
-            } else if (value instanceof Expression) {
-                // avoid NPEs due to missing source code
-                value.setLineNumber(0)
-                value.setLastLineNumber(0)
-                annotationNode.addMember(key, value)
-            } else if (value instanceof Class) {
-                annotationNode.addMember(key, new ClassExpression(ClassHelper.make(value)))
-            } else if (value instanceof List) {
-                annotationNode.addMember(key, new ListExpression(value.collect {
-                    it instanceof Class ? new ClassExpression(ClassHelper.make(it)) : new ConstantExpression(it)
-                }))
-            } else {
-                annotationNode.addMember(key, new ConstantExpression(value))
-            }
-        }
-    }
-
-    @Override
-    void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
-        if (transformation instanceof CompilationUnitAware) {
-            transformation.compilationUnit = compilationUnit
-        }
-        if (annotationNode!=null) {
-            // this is a local ast transformation which is applied on every class node
-            annotationNode.sourcePosition = classNode
-            transformation.visit([annotationNode, classNode] as ASTNode[], source)
-        } else {
-            // this is a global AST transformation
-            if (!applied) transformation.visit(null, source)
-        }
-        applied = true
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/ASTTransformationCustomizerFactory.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/ASTTransformationCustomizerFactory.groovy b/src/main/groovy/ASTTransformationCustomizerFactory.groovy
deleted file mode 100644
index 4e4f5be..0000000
--- a/src/main/groovy/ASTTransformationCustomizerFactory.groovy
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  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.control.customizers.builder
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
-
-/**
- * This factory generates an {@link ASTTransformationCustomizer ast transformation customizer}.
- * <p>
- * Simple syntax:
- * <pre>builder.ast(ToString)</pre>
- * With AST transformation options:
- * <pre>builder.ast(includeNames:true, ToString)</pre>
- *
- * @author Cedric Champeau
- * @since 2.1.0
- */
-class ASTTransformationCustomizerFactory extends AbstractFactory {
-
-    @Override
-    @CompileStatic
-    public boolean isLeaf() {
-        true
-    }
-
-    @Override
-    @CompileStatic
-    public boolean onHandleNodeAttributes(final FactoryBuilderSupport builder, final Object node, final Map attributes) {
-        false
-    }
-
-    @Override
-    public Object newInstance(final FactoryBuilderSupport builder, final Object name, final Object value, final Map attributes) throws InstantiationException, IllegalAccessException {
-        ASTTransformationCustomizer customizer
-        if (attributes) {
-            customizer = new ASTTransformationCustomizer(attributes, value)
-        } else {
-            customizer = new ASTTransformationCustomizer(value)
-        }
-        customizer
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/AstBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/AstBuilder.groovy b/src/main/groovy/AstBuilder.groovy
deleted file mode 100644
index 06d027b..0000000
--- a/src/main/groovy/AstBuilder.groovy
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  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.ast.builder
-
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.control.CompilePhase
-
-/**
- * The AstBuilder provides several ways to build an abstract syntax tree (AST) of Groovy code.
- *
- * You can convert a String into AST using the buildFromString method.
- * You can convert code into AST using the buildFromCode method.
- * You can use the AST DSL with the buildFromSpec method. 
- * 
- * For more information, see the resources on the Groovy wiki pages. 
- *
- * @author Hamlet D'Arcy
- */
-
-public class AstBuilder {
-
-    /**
-     * Builds AST based on the code within the  {@link Closure}  parameter.
-     *
-     * This method <strong>must</strong> be invoked at compile time and never at runtime, because
-     * an ASTTransformation must be run to support it. If you receive an IllegalStateException then
-     * you most likely need to add stronger typing. For instance, this will not work:
-     * <code>
-     *      def builder = new AstBuilder()
-     *      builder.buildFromCode {
-     *             // some code
-     *      }
-     * </code>
-     * While this code will:
-     * <code>
-     *      new AstBuilder().buildFromCode {
-     *             // some code
-     *      }
-     * </code>
-     *
-     * The compiler rewrites buildFromCode invocations into  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
-     * invocations. An exception raised during AST generation will show a stack trace from  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
-     * and not from  {@link AstBuilder#buildFromCode(CompilePhase, boolean, Closure)} .
-     *
-     * The compiler saves the source code of the closure as a String within the Java class file. The String source
-     * of the closure will be visible and un-obfuscated within the class file. If your Closure parameter contains
-     * sensitive data such as a hard-coded password then that data is free to be seen by anyone with the class file.
-     * Do not store sensitive data within the closure parameter.
-     *
-     * @param phase
-     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
-     * @param statementsOnly
-     *      when true, only the script statements are returned. WHen false, you will
-     *      receive back a Script class node also. Default is true.
-     * @param block
-     *      the code that will be converted
-     * @returns a List of  {@link ASTNode} .
-     * @throws IllegalStateException
-     *      this method may not be invoked at runtime. It works via a compile-time transformation
-     *      of the closure source code into a String, which is sent to the  {@link AstBuilder#buildFromString(CompilePhase, boolean, String)}
-     *      method. The buildFromCode() method must be invoked against a strongly typed AstBuilder.
-     */
-    List<ASTNode> buildFromCode(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, Closure block) {
-        throw new IllegalStateException("""AstBuilder.build(CompilePhase, boolean, Closure):List<ASTNode> should never be called at runtime.
-Are you sure you are using it correctly?
-""")
-    }
-
-
-    /**
-     * Builds AST based on the code within the String parameter.
-     *
-     * @param phase
-     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
-     * @param statementsOnly
-     *      when true, only the script statements are returned. WHen false, you will
-     *      receive back a Script class node also. Default is true.
-     * @param source
-     *      The source code String that will be compiled.
-     * @returns a List of  {@link ASTNode} .
-     * @throws IllegalArgumentException
-     *      if source is null or empty
-     */
-    List<ASTNode> buildFromString(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, String source) {
-        if (!source || "" == source.trim()) throw new IllegalArgumentException("A source must be specified")
-        return new AstStringCompiler().compile(source, phase, statementsOnly);
-    }
-
-    /**
-     * Builds AST based on the code within the String parameter. The parameter is assumed to be 
-     * a code block which is not legal Groovy code. A goto label is affixed to the block, compiled, 
-     * and the resulting BlockStatement wrapper is removed before returning a result. 
-     * @param phase
-     *      the  {@link CompilePhase}  the AST will be targeted towards. Default is  {@link CompilePhase#CLASS_GENERATION}
-     * @param statementsOnly
-     *      when true, only the script statements are returned. WHen false, you will
-     *      receive back a Script class node also. Default is true.
-     * @param source
-     *      The source code String that will be compiled. The string must be a block wrapped in curly braces. 
-     * @returns a List of  {@link ASTNode} .
-     * @throws IllegalArgumentException
-     *      if source is null or empty
-     */
-    private List<ASTNode> buildFromBlock(CompilePhase phase = CompilePhase.CLASS_GENERATION, boolean statementsOnly = true, String source) {
-        if (!source || "" == source.trim()) throw new IllegalArgumentException("A source must be specified")
-        def labelledSource = "__synthesized__label__${System.currentTimeMillis()}__:" + source
-        List<ASTNode> result = new AstStringCompiler().compile(labelledSource, phase, statementsOnly)
-        // find the block statement from the result, and unwrap it from one level.
-        result.collect { node ->
-            if (node instanceof BlockStatement) {
-                ((BlockStatement)node).statements[0] //unwrap the artifact of pre-pending the goto label
-            } else {
-                node
-            }
-        }
-    }
-
-    /**
-     * Builds AST based on the DSL data within the Closure parameter.
-     * @param specification
-     *      the contents to create
-     */
-    List<ASTNode> buildFromSpec(@DelegatesTo(AstSpecificationCompiler) Closure specification) {
-        if (specification == null) throw new IllegalArgumentException('Null: specification')
-        def properties = new AstSpecificationCompiler(specification)
-        return properties.expression
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/AstHelper.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/AstHelper.groovy b/src/main/groovy/AstHelper.groovy
deleted file mode 100644
index 206b0df..0000000
--- a/src/main/groovy/AstHelper.groovy
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  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.transform.tailrec
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.ContinueStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
-import org.codehaus.groovy.ast.stmt.Statement
-import org.codehaus.groovy.ast.stmt.ThrowStatement
-
-import java.lang.reflect.Modifier
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.declS
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
-
-/**
- * Helping to create a few standard AST constructs
- *
- * @author Johannes Link
- */
-@CompileStatic
-class AstHelper {
-	static ExpressionStatement createVariableDefinition(String variableName, ClassNode variableType, Expression value, boolean variableShouldBeFinal = false ) {
-        def newVariable = varX(variableName, variableType)
-        if (variableShouldBeFinal)
-            newVariable.setModifiers(Modifier.FINAL)
-        (ExpressionStatement) declS(newVariable, value)
-	}
-
-	static ExpressionStatement createVariableAlias(String aliasName, ClassNode variableType, String variableName ) {
-		createVariableDefinition(aliasName, variableType, varX(variableName, variableType))
-	}
-
-    static VariableExpression createVariableReference(Map variableSpec) {
-        varX((String) variableSpec.name, (ClassNode) variableSpec.type)
-    }
-
-    /**
-     * This statement should make the code jump to surrounding while loop's start label
-     * Does not work from within Closures
-     */
-    static Statement recurStatement() {
-        //continue _RECUR_HERE_
-        new ContinueStatement(InWhileLoopWrapper.LOOP_LABEL)
-    }
-
-    /**
-     * This statement will throw exception which will be caught and redirected to jump to surrounding while loop's start label
-     * Also works from within Closures but is a tiny bit slower
-     */
-    static Statement recurByThrowStatement() {
-        // throw InWhileLoopWrapper.LOOP_EXCEPTION
-        new ThrowStatement(propX(classX(InWhileLoopWrapper), 'LOOP_EXCEPTION'))
-    }
-}


[37/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GrabExclude.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GrabExclude.java b/src/main/groovy/groovy/lang/GrabExclude.java
new file mode 100644
index 0000000..eb5a50d
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GrabExclude.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 groovy.lang;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to exclude an indirectly referenced artifact (a transitive dependency) from the classpath.
+ * <p>
+ * Examples:<br>
+ * {@code @GrabExclude(group='mysql', module='mysql-connector-java') // group/module form}<br>
+ * {@code @GrabExclude('mysql:mysql-connector-java') // compact form}<br>
+ * <p>
+ * Further information about customising grape behavior can be found on the Grape documentation page:
+ * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+        ElementType.CONSTRUCTOR,
+        ElementType.FIELD,
+        ElementType.LOCAL_VARIABLE,
+        ElementType.METHOD,
+        ElementType.PARAMETER,
+        ElementType.TYPE})
+public @interface GrabExclude {
+
+    /**
+     * The organisation or group, e.g.: "org.apache.ant"; required unless the compact form is used.
+     */
+    String group() default "";
+
+    /**
+     * The module or artifact, e.g.: "ant-junit"; required unless the compact form is used.
+     */
+    String module() default "";
+
+    /**
+     * Allows you to specify the group (organisation) and the module (artifact) in one of two compact convenience formats,
+     * e.g.: <code>@GrabExclude('org.apache.ant:ant-junit')</code> or <code>@GrabExclude('org.apache.ant#ant-junit')</code>
+     */
+    String value() default "";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GrabResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GrabResolver.java b/src/main/groovy/groovy/lang/GrabResolver.java
new file mode 100644
index 0000000..cf8d0ac
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GrabResolver.java
@@ -0,0 +1,86 @@
+/*
+ *  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 groovy.lang;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to add a repository for resolving Grape dependencies.
+ * <p>
+ * For example:
+ * <pre>
+ * {@code @GrabResolver}(name='restlet.org', root='http://maven.restlet.org')
+ * {@code @Grab}(group='org.restlet', module='org.restlet', version='1.1.6')
+ * class MyRestlet extends org.restlet.Restlet {
+ *   // ...
+ * }
+ * </pre>
+ * By default, the Grapes subsystem uses an Ivy chained resolver. Each resolver
+ * added using {@code @GrabResolver} is appended to the chain. By default, the grape
+ * subsystem is shared globally, so added resolvers will become available for any subsequent
+ * grab calls. Dependency resolution follows Ivy's artifact resolution which tries
+ * to resolve artifacts in the order specified in the chain of resolvers.
+ * <p>
+ * Further information about customising grape behavior can be found on the Grape documentation page:
+ * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
+ *
+ * @author Merlyn Albery-Speyer
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({
+        ElementType.CONSTRUCTOR,
+        ElementType.FIELD,
+        ElementType.LOCAL_VARIABLE,
+        ElementType.METHOD,
+        ElementType.PARAMETER,
+        ElementType.TYPE})
+public @interface GrabResolver {
+    /**
+     * Allows a shorthand form which sets the name and root to this value.
+     * Must not be used if name() or root() is non-empty.
+     */
+    String value() default "";
+
+    /**
+     * A meaningful name for a repo containing the grape/artifact.
+     * A non-empty value is required unless value() is used.
+     */
+    String name() default "";
+
+    /**
+     * The URL for a repo containing the grape/artifact.
+     * A non-empty value is required unless value() is used.
+     */
+    String root() default "";
+
+    /**
+     * Defaults to Maven2 compatibility. Set false for Ivy only compatibility.
+     */
+    boolean m2Compatible() default true;
+
+    /**
+     * By default, when a {@code @GrabResolver} annotation is used, a {@code Grape.addResolver()} call is added
+     * to the static initializers of the class the annotatable node appears in.
+     * If you wish to disable this, add {@code initClass=false} to the annotation.
+     */
+    boolean initClass() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Grapes.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Grapes.java b/src/main/groovy/groovy/lang/Grapes.java
new file mode 100644
index 0000000..8719c74
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Grapes.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 groovy.lang;
+
+/**
+ * Sometimes we will need more than one grab per class, but we can only add
+ * one annotation type per annotatable node.  This class allows for multiple
+ * grabs to be added.
+ * <p>
+ * For example:
+ * <p>
+ * <pre>
+ * {@code @Grapes([@Grab(module='m1'), @Grab(module='m2')])}
+ * class AnnotatedClass { ... }
+ * </pre>
+ * <p>
+ * You can override an implicit transitive dependency by providing an explicit one.
+ * E.g. htmlunit 2.6 normally uses xerces 2.9.1 but you can get 2.9.0 as follows:
+ * <pre>
+ * {@code @Grapes}([
+ *     {@code @Grab}('net.sourceforge.htmlunit:htmlunit:2.6'),
+ *     {@code @Grab}('xerces#xercesImpl;2.9.0')
+ * ])
+ * </pre>
+ * Obviously, only do this if you understand the consequences.
+ * <p>
+ * You can also remove transitive dependencies altogether (provided you
+ * know you don't need them) using {@code @GrabExclude}.
+ * For example, here is how we would not grab the {@code logkit} and
+ * {@code avalon-framework} transitive dependencies for Apache POI:
+ * <pre>
+ * {@code @Grapes}([
+ *   {@code @Grab}("org.apache.poi#poi;3.5-beta6"),
+ *   {@code @GrabExclude}("logkit:logkit"),
+ *   {@code @GrabExclude}("avalon-framework#avalon-framework")
+ * ])
+ * import org.apache.poi.hssf.util.CellReference
+ * assert new CellReference(0, 0, false, false).formatAsString() == 'A1'
+ * assert new CellReference(1, 3).formatAsString() == '$D$2'
+ * </pre>
+ * It is also sometimes also useful to use {@code @GrabConfig} to further adjust how dependencies
+ * are grabbed. See {@code @GrabConfig} for further information.
+ */
+public @interface Grapes {
+    Grab[] value();
+
+    /**
+     * This will be pushed into the child grab annotations if the value is not
+     * set in the child annotation already.
+     * <p>
+     * This results in an effective change in the default value, which each &#064;Grab
+     * can still override
+     */
+    boolean initClass() default true;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyCallable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyCallable.java b/src/main/groovy/groovy/lang/GroovyCallable.java
new file mode 100644
index 0000000..e425c92
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyCallable.java
@@ -0,0 +1,32 @@
+/*
+ *  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 groovy.lang;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A special "marker" style interface allowing Groovy classes to implement both
+ * Runnable and Callable yet give preference to Runnable (for backwards compatibility)
+ * for APIs having both Runnable and Callable methods. You should generally NOT use this
+ * method in your own code.
+ *
+ * @see java.util.concurrent.Callable
+ * @since 1.8.0
+ */
+public interface GroovyCallable<V> extends Callable<V> { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyClassLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyClassLoader.java b/src/main/groovy/groovy/lang/GroovyClassLoader.java
new file mode 100644
index 0000000..8581879
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyClassLoader.java
@@ -0,0 +1,1099 @@
+/*
+ *  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.
+ */
+/*
+ * @todo multi threaded compiling of the same class but with different roots
+ * for compilation... T1 compiles A, which uses B, T2 compiles B... mark A and B
+ * as parsed and then synchronize compilation. Problems: How to synchronize?
+ * How to get error messages?
+ *
+ */
+package groovy.lang;
+
+import groovy.util.CharsetToolkit;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.classgen.GeneratorContext;
+import org.codehaus.groovy.classgen.Verifier;
+import org.codehaus.groovy.control.BytecodeProcessor;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.Phases;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
+import org.codehaus.groovy.runtime.memoize.EvictableCache;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Map;
+
+/**
+ * A ClassLoader which can load Groovy classes. The loaded classes are cached,
+ * classes from other classloaders should not be cached. To be able to load a
+ * script that was asked for earlier but was created later it is essential not
+ * to keep anything like a "class not found" information for that class name.
+ * This includes possible parent loaders. Classes that are not cached are always
+ * reloaded.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Guillaume Laforge
+ * @author Steve Goetze
+ * @author Bing Ran
+ * @author <a href="mailto:scottstirling@rcn.com">Scott Stirling</a>
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ */
+public class GroovyClassLoader extends URLClassLoader {
+    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+
+    /**
+     * this cache contains the loaded classes or PARSING, if the class is currently parsed
+     */
+    protected final EvictableCache<String, Class> classCache = new ConcurrentCommonCache<String, Class>();
+
+    /**
+     * This cache contains mappings of file name to class. It is used
+     * to bypass compilation.
+     */
+    protected final ConcurrentCommonCache<String, Class> sourceCache = new ConcurrentCommonCache<String, Class>();
+
+    private final CompilerConfiguration config;
+    private String sourceEncoding;
+    private Boolean recompile;
+    // use 1000000 as offset to avoid conflicts with names form the GroovyShell
+    private static int scriptNameCounter = 1000000;
+
+    private GroovyResourceLoader resourceLoader = new GroovyResourceLoader() {
+        public URL loadGroovySource(final String filename) throws MalformedURLException {
+            return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+                public URL run() {
+                    for (String extension : config.getScriptExtensions()) {
+                        try {
+                            URL ret = getSourceFile(filename, extension);
+                            if (ret != null)
+                                return ret;
+                        } catch (Throwable t) { //
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+    };
+
+    /**
+     * creates a GroovyClassLoader using the current Thread's context
+     * Class loader as parent.
+     */
+    public GroovyClassLoader() {
+        this(Thread.currentThread().getContextClassLoader());
+    }
+
+    /**
+     * creates a GroovyClassLoader using the given ClassLoader as parent
+     */
+    public GroovyClassLoader(ClassLoader loader) {
+        this(loader, null);
+    }
+
+    /**
+     * creates a GroovyClassLoader using the given GroovyClassLoader as parent.
+     * This loader will get the parent's CompilerConfiguration
+     */
+    public GroovyClassLoader(GroovyClassLoader parent) {
+        this(parent, parent.config, false);
+    }
+
+    /**
+     * creates a GroovyClassLoader.
+     *
+     * @param parent                    the parent class loader
+     * @param config                    the compiler configuration
+     * @param useConfigurationClasspath determines if the configurations classpath should be added
+     */
+    public GroovyClassLoader(ClassLoader parent, CompilerConfiguration config, boolean useConfigurationClasspath) {
+        super(EMPTY_URL_ARRAY, parent);
+        if (config == null) config = CompilerConfiguration.DEFAULT;
+        this.config = config;
+        if (useConfigurationClasspath) {
+            for (String path : config.getClasspath()) {
+                this.addClasspath(path);
+            }
+        }
+
+        initSourceEncoding(config);
+    }
+
+    private void initSourceEncoding(CompilerConfiguration config) {
+        sourceEncoding = config.getSourceEncoding();
+        if (null ==  sourceEncoding) {
+            // Keep the same default source encoding with the one used by #parseClass(InputStream, String)
+            // TODO should we use org.codehaus.groovy.control.CompilerConfiguration.DEFAULT_SOURCE_ENCODING instead?
+            sourceEncoding = CharsetToolkit.getDefaultSystemCharset().name();
+        }
+    }
+
+    /**
+     * creates a GroovyClassLoader using the given ClassLoader as parent.
+     */
+    public GroovyClassLoader(ClassLoader loader, CompilerConfiguration config) {
+        this(loader, config, true);
+    }
+
+    public void setResourceLoader(GroovyResourceLoader resourceLoader) {
+        if (resourceLoader == null) {
+            throw new IllegalArgumentException("Resource loader must not be null!");
+        }
+        this.resourceLoader = resourceLoader;
+    }
+
+    public GroovyResourceLoader getResourceLoader() {
+        return resourceLoader;
+    }
+
+    /**
+     * Loads the given class node returning the implementation Class.
+     * <p>
+     * WARNING: this compilation is not synchronized
+     *
+     * @param classNode
+     * @return a class
+     */
+    public Class defineClass(ClassNode classNode, String file, String newCodeBase) {
+        CodeSource codeSource = null;
+        try {
+            codeSource = new CodeSource(new URL("file", "", newCodeBase), (java.security.cert.Certificate[]) null);
+        } catch (MalformedURLException e) {
+            //swallow
+        }
+
+        CompilationUnit unit = createCompilationUnit(config, codeSource);
+        ClassCollector collector = createCollector(unit, classNode.getModule().getContext());
+        try {
+            unit.addClassNode(classNode);
+            unit.setClassgenCallback(collector);
+            unit.compile(Phases.CLASS_GENERATION);
+            definePackageInternal(collector.generatedClass.getName());
+            return collector.generatedClass;
+        } catch (CompilationFailedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Parses the given file into a Java class capable of being run
+     *
+     * @param file the file name to parse
+     * @return the main class defined in the given script
+     */
+    public Class parseClass(File file) throws CompilationFailedException, IOException {
+        return parseClass(new GroovyCodeSource(file, config.getSourceEncoding()));
+    }
+
+    /**
+     * Parses the given text into a Java class capable of being run
+     *
+     * @param text     the text of the script/class to parse
+     * @param fileName the file name to use as the name of the class
+     * @return the main class defined in the given script
+     */
+    public Class parseClass(final String text, final String fileName) throws CompilationFailedException {
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                return new GroovyCodeSource(text, fileName, "/groovy/script");
+            }
+        });
+        gcs.setCachable(false);
+        return parseClass(gcs);
+    }
+
+    /**
+     * Parses the given text into a Java class capable of being run
+     *
+     * @param text the text of the script/class to parse
+     * @return the main class defined in the given script
+     */
+    public Class parseClass(String text) throws CompilationFailedException {
+        return parseClass(text, "script" + System.currentTimeMillis() +
+                Math.abs(text.hashCode()) + ".groovy");
+    }
+
+    public synchronized String generateScriptName() {
+        scriptNameCounter++;
+        return "script" + scriptNameCounter + ".groovy";
+    }
+
+    public Class parseClass(final Reader reader, final String fileName) throws CompilationFailedException {
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                try {
+                    String scriptText = IOGroovyMethods.getText(reader);
+                    return new GroovyCodeSource(scriptText, fileName, "/groovy/script");
+                } catch (IOException e) {
+                    throw new RuntimeException("Impossible to read the content of the reader for file named: " + fileName, e);
+                }
+            }
+        });
+        return parseClass(gcs);
+    }
+    
+    /**
+     * @deprecated Prefer using methods taking a Reader rather than an InputStream to avoid wrong encoding issues.
+     * Use {@link #parseClass(Reader, String) parseClass} instead
+     */
+    @Deprecated
+    public Class parseClass(final InputStream in, final String fileName) throws CompilationFailedException {
+        // For generic input streams, provide a catch-all codebase of GroovyScript
+        // Security for these classes can be administered via policy grants with
+        // a codebase of file:groovy.script
+        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
+            public GroovyCodeSource run() {
+                try {
+                    String scriptText = config.getSourceEncoding() != null ?
+                            IOGroovyMethods.getText(in, config.getSourceEncoding()) :
+                            IOGroovyMethods.getText(in);
+                    return new GroovyCodeSource(scriptText, fileName, "/groovy/script");
+                } catch (IOException e) {
+                    throw new RuntimeException("Impossible to read the content of the input stream for file named: " + fileName, e);
+                }
+            }
+        });
+        return parseClass(gcs);
+    }
+
+    public Class parseClass(GroovyCodeSource codeSource) throws CompilationFailedException {
+        return parseClass(codeSource, codeSource.isCachable());
+    }
+
+    /**
+     * Parses the given code source into a Java class. If there is a class file
+     * for the given code source, then no parsing is done, instead the cached class is returned.
+     *
+     * @param shouldCacheSource if true then the generated class will be stored in the source cache
+     * @return the main class defined in the given script
+     */
+    public Class parseClass(final GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException {
+        return sourceCache.getAndPut(
+                codeSource.getName(),
+                new EvictableCache.ValueProvider<String, Class>() {
+                    @Override
+                    public Class provide(String key) {
+                        return doParseClass(codeSource);
+                    }
+                },
+                shouldCacheSource
+        );
+    }
+
+    private Class doParseClass(GroovyCodeSource codeSource) {
+        validate(codeSource);
+        Class answer;  // Was neither already loaded nor compiling, so compile and add to cache.
+        CompilationUnit unit = createCompilationUnit(config, codeSource.getCodeSource());
+        if (recompile!=null && recompile || recompile==null && config.getRecompileGroovySource()) {
+            unit.addFirstPhaseOperation(TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber());
+        }
+        SourceUnit su = null;
+        File file = codeSource.getFile();
+        if (file != null) {
+            su = unit.addSource(file);
+        } else {
+            URL url = codeSource.getURL();
+            if (url != null) {
+                su = unit.addSource(url);
+            } else {
+                su = unit.addSource(codeSource.getName(), codeSource.getScriptText());
+            }
+        }
+
+        ClassCollector collector = createCollector(unit, su);
+        unit.setClassgenCallback(collector);
+        int goalPhase = Phases.CLASS_GENERATION;
+        if (config != null && config.getTargetDirectory() != null) goalPhase = Phases.OUTPUT;
+        unit.compile(goalPhase);
+
+        answer = collector.generatedClass;
+        String mainClass = su.getAST().getMainClassName();
+        for (Object o : collector.getLoadedClasses()) {
+            Class clazz = (Class) o;
+            String clazzName = clazz.getName();
+            definePackageInternal(clazzName);
+            setClassCacheEntry(clazz);
+            if (clazzName.equals(mainClass)) answer = clazz;
+        }
+        return answer;
+    }
+
+    private static void validate(GroovyCodeSource codeSource) {
+        if (codeSource.getFile() == null) {
+            if (codeSource.getScriptText() == null) {
+                throw new IllegalArgumentException("Script text to compile cannot be null!");
+            }
+        }
+    }
+
+    private void definePackageInternal(String className) {
+        int i = className.lastIndexOf('.');
+        if (i != -1) {
+            String pkgName = className.substring(0, i);
+            java.lang.Package pkg = getPackage(pkgName);
+            if (pkg == null) {
+                definePackage(pkgName, null, null, null, null, null, null, null);
+            }
+        }
+    }
+
+    /**
+     * gets the currently used classpath.
+     *
+     * @return a String[] containing the file information of the urls
+     * @see #getURLs()
+     */
+    protected String[] getClassPath() {
+        //workaround for Groovy-835
+        URL[] urls = getURLs();
+        String[] ret = new String[urls.length];
+        for (int i = 0; i < ret.length; i++) {
+            ret[i] = urls[i].getFile();
+        }
+        return ret;
+    }
+
+    protected PermissionCollection getPermissions(CodeSource codeSource) {
+        PermissionCollection perms;
+        try {
+            try {
+                perms = super.getPermissions(codeSource);
+            } catch (SecurityException e) {
+                // We lied about our CodeSource and that makes URLClassLoader unhappy.
+                perms = new Permissions();
+            }
+
+            ProtectionDomain myDomain = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+                public ProtectionDomain run() {
+                    return getClass().getProtectionDomain();
+                }
+            });
+            PermissionCollection myPerms = myDomain.getPermissions();
+            if (myPerms != null) {
+                for (Enumeration<Permission> elements = myPerms.elements(); elements.hasMoreElements();) {
+                    perms.add(elements.nextElement());
+                }
+            }
+        } catch (Throwable e) {
+            // We lied about our CodeSource and that makes URLClassLoader unhappy.
+            perms = new Permissions();
+        }
+        perms.setReadOnly();
+        return perms;
+    }
+
+    public static class InnerLoader extends GroovyClassLoader {
+        private final GroovyClassLoader delegate;
+        private final long timeStamp;
+
+        public InnerLoader(GroovyClassLoader delegate) {
+            super(delegate);
+            this.delegate = delegate;
+            timeStamp = System.currentTimeMillis();
+        }
+
+        public void addClasspath(String path) {
+            delegate.addClasspath(path);
+        }
+
+        public void clearCache() {
+            delegate.clearCache();
+        }
+
+        public URL findResource(String name) {
+            return delegate.findResource(name);
+        }
+
+        public Enumeration findResources(String name) throws IOException {
+            return delegate.findResources(name);
+        }
+
+        public Class[] getLoadedClasses() {
+            return delegate.getLoadedClasses();
+        }
+
+        public URL getResource(String name) {
+            return delegate.getResource(name);
+        }
+
+        public InputStream getResourceAsStream(String name) {
+            return delegate.getResourceAsStream(name);
+        }
+
+        public GroovyResourceLoader getResourceLoader() {
+            return delegate.getResourceLoader();
+        }
+
+        public URL[] getURLs() {
+            return delegate.getURLs();
+        }
+
+        public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve) throws ClassNotFoundException, CompilationFailedException {
+            Class c = findLoadedClass(name);
+            if (c != null) return c;
+            return delegate.loadClass(name, lookupScriptFiles, preferClassOverScript, resolve);
+        }
+
+        public Class parseClass(GroovyCodeSource codeSource, boolean shouldCache) throws CompilationFailedException {
+            return delegate.parseClass(codeSource, shouldCache);
+        }
+
+        public void setResourceLoader(GroovyResourceLoader resourceLoader) {
+            delegate.setResourceLoader(resourceLoader);
+        }
+
+        public void addURL(URL url) {
+            delegate.addURL(url);
+        }
+
+        public long getTimeStamp() {
+            return timeStamp;
+        }
+    }
+
+    /**
+     * creates a new CompilationUnit. If you want to add additional
+     * phase operations to the CompilationUnit (for example to inject
+     * additional methods, variables, fields), then you should overwrite
+     * this method.
+     *
+     * @param config the compiler configuration, usually the same as for this class loader
+     * @param source the source containing the initial file to compile, more files may follow during compilation
+     * @return the CompilationUnit
+     */
+    protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
+        return new CompilationUnit(config, source, this);
+    }
+
+    /**
+     * creates a ClassCollector for a new compilation.
+     *
+     * @param unit the compilationUnit
+     * @param su   the SourceUnit
+     * @return the ClassCollector
+     */
+    protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
+        InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
+            public InnerLoader run() {
+                return new InnerLoader(GroovyClassLoader.this);
+            }
+        });
+        return new ClassCollector(loader, unit, su);
+    }
+
+    public static class ClassCollector extends CompilationUnit.ClassgenCallback {
+        private Class generatedClass;
+        private final GroovyClassLoader cl;
+        private final SourceUnit su;
+        private final CompilationUnit unit;
+        private final Collection<Class> loadedClasses;
+
+        protected ClassCollector(InnerLoader cl, CompilationUnit unit, SourceUnit su) {
+            this.cl = cl;
+            this.unit = unit;
+            this.loadedClasses = new ArrayList<Class>();
+            this.su = su;
+        }
+
+        public GroovyClassLoader getDefiningClassLoader() {
+            return cl;
+        }
+
+        protected Class createClass(byte[] code, ClassNode classNode) {
+            BytecodeProcessor bytecodePostprocessor = unit.getConfiguration().getBytecodePostprocessor();
+            byte[] fcode = code;
+            if (bytecodePostprocessor!=null) {
+                fcode = bytecodePostprocessor.processBytecode(classNode.getName(), fcode);
+            }
+            GroovyClassLoader cl = getDefiningClassLoader();
+            Class theClass = cl.defineClass(classNode.getName(), fcode, 0, fcode.length, unit.getAST().getCodeSource());
+            this.loadedClasses.add(theClass);
+
+            if (generatedClass == null) {
+                ModuleNode mn = classNode.getModule();
+                SourceUnit msu = null;
+                if (mn != null) msu = mn.getContext();
+                ClassNode main = null;
+                if (mn != null) main = (ClassNode) mn.getClasses().get(0);
+                if (msu == su && main == classNode) generatedClass = theClass;
+            }
+
+            return theClass;
+        }
+
+        protected Class onClassNode(ClassWriter classWriter, ClassNode classNode) {
+            byte[] code = classWriter.toByteArray();
+            return createClass(code, classNode);
+        }
+
+        public void call(ClassVisitor classWriter, ClassNode classNode) {
+            onClassNode((ClassWriter) classWriter, classNode);
+        }
+
+        public Collection getLoadedClasses() {
+            return this.loadedClasses;
+        }
+    }
+
+    /**
+     * open up the super class define that takes raw bytes
+     */
+    public Class defineClass(String name, byte[] b) {
+        return super.defineClass(name, b, 0, b.length);
+    }
+
+    /**
+     * loads a class from a file or a parent classloader.
+     * This method does call loadClass(String, boolean, boolean, boolean)
+     * with the last parameter set to false.
+     *
+     * @throws CompilationFailedException if compilation was not successful
+     */
+    public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript)
+            throws ClassNotFoundException, CompilationFailedException {
+        return loadClass(name, lookupScriptFiles, preferClassOverScript, false);
+    }
+
+    /**
+     * gets a class from the class cache. This cache contains only classes loaded through
+     * this class loader or an InnerLoader instance. If no class is stored for a
+     * specific name, then the method should return null.
+     *
+     * @param name of the class
+     * @return the class stored for the given name
+     * @see #removeClassCacheEntry(String)
+     * @see #setClassCacheEntry(Class)
+     * @see #clearCache()
+     */
+    protected Class getClassCacheEntry(String name) {
+        return classCache.get(name);
+    }
+
+    /**
+     * sets an entry in the class cache.
+     *
+     * @param cls the class
+     * @see #removeClassCacheEntry(String)
+     * @see #getClassCacheEntry(String)
+     * @see #clearCache()
+     */
+    protected void setClassCacheEntry(Class cls) {
+        classCache.put(cls.getName(), cls);
+    }
+
+    /**
+     * removes a class from the class cache.
+     *
+     * @param name of the class
+     * @see #getClassCacheEntry(String)
+     * @see #setClassCacheEntry(Class)
+     * @see #clearCache()
+     */
+    protected void removeClassCacheEntry(String name) {
+        classCache.remove(name);
+    }
+
+    /**
+     * adds a URL to the classloader.
+     *
+     * @param url the new classpath element
+     */
+    public void addURL(URL url) {
+        super.addURL(url);
+    }
+
+    /**
+     * Indicates if a class is recompilable. Recompilable means, that the classloader
+     * will try to locate a groovy source file for this class and then compile it again,
+     * adding the resulting class as entry to the cache. Giving null as class is like a
+     * recompilation, so the method should always return true here. Only classes that are
+     * implementing GroovyObject are compilable and only if the timestamp in the class
+     * is lower than Long.MAX_VALUE.
+     * <p>
+     * NOTE: First the parent loaders will be asked and only if they don't return a
+     * class the recompilation will happen. Recompilation also only happen if the source
+     * file is newer.
+     *
+     * @param cls the class to be tested. If null the method should return true
+     * @return true if the class should be compiled again
+     * @see #isSourceNewer(URL, Class)
+     */
+    protected boolean isRecompilable(Class cls) {
+        if (cls == null) return true;
+        if (cls.getClassLoader() == this) return false;
+        if (recompile == null && !config.getRecompileGroovySource()) return false;
+        if (recompile != null && !recompile) return false;
+        if (!GroovyObject.class.isAssignableFrom(cls)) return false;
+        long timestamp = getTimeStamp(cls);
+        if (timestamp == Long.MAX_VALUE) return false;
+        return true;
+    }
+
+    /**
+     * sets if the recompilation should be enable. There are 3 possible
+     * values for this. Any value different than null overrides the
+     * value from the compiler configuration. true means to recompile if needed
+     * false means to never recompile.
+     *
+     * @param mode the recompilation mode
+     * @see CompilerConfiguration
+     */
+    public void setShouldRecompile(Boolean mode) {
+        recompile = mode;
+    }
+
+    /**
+     * gets the currently set recompilation mode. null means, the
+     * compiler configuration is used. False means no recompilation and
+     * true means that recompilation will be done if needed.
+     *
+     * @return the recompilation mode
+     */
+    public Boolean isShouldRecompile() {
+        return recompile;
+    }
+
+    /**
+     * loads a class from a file or a parent classloader.
+     *
+     * @param name                  of the class to be loaded
+     * @param lookupScriptFiles     if false no lookup at files is done at all
+     * @param preferClassOverScript if true the file lookup is only done if there is no class
+     * @param resolve               see {@link java.lang.ClassLoader#loadClass(java.lang.String, boolean)}
+     * @return the class found or the class created from a file lookup
+     * @throws ClassNotFoundException     if the class could not be found
+     * @throws CompilationFailedException if the source file could not be compiled
+     */
+    public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve)
+            throws ClassNotFoundException, CompilationFailedException {
+        // look into cache
+        Class cls = getClassCacheEntry(name);
+
+        // enable recompilation?
+        boolean recompile = isRecompilable(cls);
+        if (!recompile) return cls;
+
+        // try parent loader
+        ClassNotFoundException last = null;
+        try {
+            Class parentClassLoaderClass = super.loadClass(name, resolve);
+            // always return if the parent loader was successful
+            if (cls != parentClassLoaderClass) return parentClassLoaderClass;
+        } catch (ClassNotFoundException cnfe) {
+            last = cnfe;
+        } catch (NoClassDefFoundError ncdfe) {
+            if (ncdfe.getMessage().indexOf("wrong name") > 0) {
+                last = new ClassNotFoundException(name);
+            } else {
+                throw ncdfe;
+            }
+        }
+
+        // check security manager
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            String className = name.replace('/', '.');
+            int i = className.lastIndexOf('.');
+            // no checks on the sun.reflect classes for reflection speed-up
+            // in particular ConstructorAccessorImpl, MethodAccessorImpl, FieldAccessorImpl and SerializationConstructorAccessorImpl
+            // which are generated at runtime by the JDK
+            if (i != -1 && !className.startsWith("sun.reflect.")) {
+                sm.checkPackageAccess(className.substring(0, i));
+            }
+        }
+
+        // prefer class if no recompilation
+        if (cls != null && preferClassOverScript) return cls;
+
+        // at this point the loading from a parent loader failed
+        // and we want to recompile if needed.
+        if (lookupScriptFiles) {
+            // try groovy file
+            try {
+                // check if recompilation already happened.
+                final Class classCacheEntry = getClassCacheEntry(name);
+                if (classCacheEntry != cls) return classCacheEntry;
+                URL source = resourceLoader.loadGroovySource(name);
+                // if recompilation fails, we want cls==null
+                Class oldClass = cls;
+                cls = null;
+                cls = recompile(source, name, oldClass);
+            } catch (IOException ioe) {
+                last = new ClassNotFoundException("IOException while opening groovy source: " + name, ioe);
+            } finally {
+                if (cls == null) {
+                    removeClassCacheEntry(name);
+                } else {
+                    setClassCacheEntry(cls);
+                }
+            }
+        }
+
+        if (cls == null) {
+            // no class found, there should have been an exception before now
+            if (last == null) throw new AssertionError(true);
+            throw last;
+        }
+        return cls;
+    }
+
+    /**
+     * (Re)Compiles the given source.
+     * This method starts the compilation of a given source, if
+     * the source has changed since the class was created. For
+     * this isSourceNewer is called.
+     *
+     * @param source    the source pointer for the compilation
+     * @param className the name of the class to be generated
+     * @param oldClass  a possible former class
+     * @return the old class if the source wasn't new enough, the new class else
+     * @throws CompilationFailedException if the compilation failed
+     * @throws IOException                if the source is not readable
+     * @see #isSourceNewer(URL, Class)
+     */
+    protected Class recompile(URL source, String className, Class oldClass) throws CompilationFailedException, IOException {
+        if (source != null) {
+            // found a source, compile it if newer
+            if ((oldClass != null && isSourceNewer(source, oldClass)) || (oldClass == null)) {
+                String name = source.toExternalForm();
+
+                sourceCache.remove(name);
+
+                if (isFile(source)) {
+                    try {
+                        return parseClass(new GroovyCodeSource(new File(source.toURI()), sourceEncoding));
+                    } catch (URISyntaxException e) {
+                        // do nothing and fall back to the other version
+                    }
+                }
+                return parseClass(new InputStreamReader(source.openStream(), sourceEncoding), name);
+            }
+        }
+        return oldClass;
+    }
+
+    @Override
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+        return loadClass(name, false);
+    }
+
+    /**
+     * Implemented here to check package access prior to returning an
+     * already loaded class.
+     *
+     * @throws CompilationFailedException if the compilation failed
+     * @throws ClassNotFoundException     if the class was not found
+     * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+     */
+    protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException {
+        return loadClass(name, true, true, resolve);
+    }
+
+    /**
+     * gets the time stamp of a given class. For groovy
+     * generated classes this usually means to return the value
+     * of the static field __timeStamp. If the parameter doesn't
+     * have such a field, then Long.MAX_VALUE is returned
+     *
+     * @param cls the class
+     * @return the time stamp
+     */
+    protected long getTimeStamp(Class cls) {
+        return Verifier.getTimestamp(cls);
+    }
+
+    /**
+     * This method will take a file name and try to "decode" any URL encoded characters.  For example
+     * if the file name contains any spaces this method call will take the resulting %20 encoded values
+     * and convert them to spaces.
+     * <p>
+     * This method was added specifically to fix defect:  Groovy-1787.  The defect involved a situation
+     * where two scripts were sitting in a directory with spaces in its name.  The code would fail
+     * when the class loader tried to resolve the file name and would choke on the URLEncoded space values.
+     */
+    private static String decodeFileName(String fileName) {
+        String decodedFile = fileName;
+        try {
+            decodedFile = URLDecoder.decode(fileName, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            System.err.println("Encountered an invalid encoding scheme when trying to use URLDecoder.decode() inside of the GroovyClassLoader.decodeFileName() method.  Returning the unencoded URL.");
+            System.err.println("Please note that if you encounter this error and you have spaces in your directory you will run into issues.  Refer to GROOVY-1787 for description of this bug.");
+        }
+
+        return decodedFile;
+    }
+
+    private static boolean isFile(URL ret) {
+        return ret != null && ret.getProtocol().equals("file");
+    }
+
+    private static File getFileForUrl(URL ret, String filename) {
+        String fileWithoutPackage = filename;
+        if (fileWithoutPackage.indexOf('/') != -1) {
+            int index = fileWithoutPackage.lastIndexOf('/');
+            fileWithoutPackage = fileWithoutPackage.substring(index + 1);
+        }
+        return fileReallyExists(ret, fileWithoutPackage);
+    }
+
+    private static File fileReallyExists(URL ret, String fileWithoutPackage) {
+        File path;
+        try {
+            /* fix for GROOVY-5809 */ 
+            path = new File(ret.toURI());
+        } catch(URISyntaxException e) {
+            path = new File(decodeFileName(ret.getFile()));
+        }
+        path = path.getParentFile();
+        if (path.exists() && path.isDirectory()) {
+            File file = new File(path, fileWithoutPackage);
+            if (file.exists()) {
+                // file.exists() might be case insensitive. Let's do
+                // case sensitive match for the filename
+                File parent = file.getParentFile();
+                for (String child : parent.list()) {
+                    if (child.equals(fileWithoutPackage)) return file;
+                }
+            }
+        }
+        //file does not exist!
+        return null;
+    }
+
+    private URL getSourceFile(String name, String extension) {
+        String filename = name.replace('.', '/') + "." + extension;
+        URL ret = getResource(filename);
+        if (isFile(ret) && getFileForUrl(ret, filename) == null) return null;
+        return ret;
+    }
+
+    /**
+     * Decides if the given source is newer than a class.
+     *
+     * @param source the source we may want to compile
+     * @param cls    the former class
+     * @return true if the source is newer, false else
+     * @throws IOException if it is not possible to open an
+     *                     connection for the given source
+     * @see #getTimeStamp(Class)
+     */
+    protected boolean isSourceNewer(URL source, Class cls) throws IOException {
+        long lastMod;
+
+        // Special handling for file:// protocol, as getLastModified() often reports
+        // incorrect results (-1)
+        if (isFile(source)) {
+            // Coerce the file URL to a File
+            // See ClassNodeResolver.isSourceNewer for another method that replaces '|' with ':'.
+            // WTF: Why is this done and where is it documented?
+            String path = source.getPath().replace('/', File.separatorChar).replace('|', ':');
+            File file = new File(path);
+            lastMod = file.lastModified();
+        } else {
+            URLConnection conn = source.openConnection();
+            lastMod = conn.getLastModified();
+            conn.getInputStream().close();
+        }
+        long classTime = getTimeStamp(cls);
+        return classTime + config.getMinimumRecompilationInterval() < lastMod;
+    }
+
+    /**
+     * adds a classpath to this classloader.
+     *
+     * @param path is a jar file or a directory.
+     * @see #addURL(URL)
+     */
+    public void addClasspath(final String path) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+
+                URI newURI;
+                try {
+                    newURI = new URI(path);
+                    // check if we can create a URL from that URI
+                    newURI.toURL();
+                } catch (URISyntaxException e) {
+                    // the URI has a false format, so lets try it with files ...
+                    newURI=new File(path).toURI();
+                } catch (MalformedURLException e) {
+                    // the URL has a false format, so lets try it with files ...
+                    newURI=new File(path).toURI();
+                } catch (IllegalArgumentException e) {
+                    // the URL is not absolute, so lets try it with files ...
+                    newURI=new File(path).toURI();
+                }
+
+                URL[] urls = getURLs();
+                for (URL url : urls) {
+                    // Do not use URL.equals.  It uses the network to resolve names and compares ip addresses!
+                    // That is a violation of RFC and just plain evil.
+                    // http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html
+                    // http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#equals(java.lang.Object)
+                    // "Since hosts comparison requires name resolution, this operation is a blocking operation.
+                    // Note: The defined behavior for equals is known to be inconsistent with virtual hosting in HTTP."
+                    try {
+                        if (newURI.equals(url.toURI())) return null;
+                    } catch (URISyntaxException e) {
+                        // fail fast! if we got a malformed URI the Classloader has to tell it
+                        throw new RuntimeException( e );
+                    }
+                }
+                try {
+                    addURL(newURI.toURL());
+                } catch (MalformedURLException e) {
+                    // fail fast! if we got a malformed URL the Classloader has to tell it
+                    throw new RuntimeException( e );
+                }
+                return null;
+            }
+        });
+    }
+
+    /**
+     * <p>Returns all Groovy classes loaded by this class loader.
+     *
+     * @return all classes loaded by this class loader
+     */
+    public Class[] getLoadedClasses() {
+        return classCache.values().toArray(EMPTY_CLASS_ARRAY);
+    }
+
+    /**
+     * Removes all classes from the class cache.
+     * <p>
+     * In addition to internal caches this method also clears any
+     * previously set MetaClass information for the given set of
+     * classes being removed.
+     *
+     * @see #getClassCacheEntry(String)
+     * @see #setClassCacheEntry(Class)
+     * @see #removeClassCacheEntry(String)
+     */
+    public void clearCache() {
+        Map<String, Class> clearedClasses = classCache.clear();
+
+        sourceCache.clear();
+
+        for (Map.Entry<String, Class> entry : clearedClasses.entrySet()) {
+            // Another Thread may be using an instance of this class
+            // (for the first time) requiring a ClassInfo lock and
+            // classloading which would require a lock on classCache.
+            // The following locks on ClassInfo and to avoid deadlock
+            // should not be done with a classCache lock.
+            InvokerHelper.removeClass(entry.getValue());
+        }
+    }
+
+    /**
+     * Closes this GroovyClassLoader and clears any caches it maintains.
+     * <p>
+     * No use should be made of this instance after this method is
+     * invoked. Any classes that are already loaded are still accessible.
+     *
+     * @throws IOException
+     * @see URLClassLoader#close()
+     * @see #clearCache()
+     * @since 2.5.0
+     */
+    @Override
+    public void close() throws IOException {
+        super.close();
+        clearCache();
+    }
+
+    private static class TimestampAdder extends CompilationUnit.PrimaryClassNodeOperation implements Opcodes {
+        private static final TimestampAdder INSTANCE = new TimestampAdder();
+
+        private TimestampAdder() {}
+
+        protected void addTimeStamp(ClassNode node) {
+            if (node.getDeclaredField(Verifier.__TIMESTAMP) == null) { // in case if verifier visited the call already
+                FieldNode timeTagField = new FieldNode(
+                        Verifier.__TIMESTAMP,
+                        ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
+                        ClassHelper.long_TYPE,
+                        //"",
+                        node,
+                        new ConstantExpression(System.currentTimeMillis()));
+                // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L");
+                timeTagField.setSynthetic(true);
+                node.addField(timeTagField);
+
+                timeTagField = new FieldNode(
+                        Verifier.__TIMESTAMP__ + String.valueOf(System.currentTimeMillis()),
+                        ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
+                        ClassHelper.long_TYPE,
+                        //"",
+                        node,
+                        new ConstantExpression((long) 0));
+                // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L");
+                timeTagField.setSynthetic(true);
+                node.addField(timeTagField);
+            }
+        }
+
+        @Override
+        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
+            if ((classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) {
+                // does not apply on interfaces
+                return;
+            }
+            if (!(classNode instanceof InnerClassNode)) {
+                addTimeStamp(classNode);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyCodeSource.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyCodeSource.java b/src/main/groovy/groovy/lang/GroovyCodeSource.java
new file mode 100644
index 0000000..a5a2bb1
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyCodeSource.java
@@ -0,0 +1,266 @@
+/*
+ *  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 groovy.lang;
+
+import groovy.security.GroovyCodeSourcePermission;
+import groovy.util.CharsetToolkit;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+import org.codehaus.groovy.runtime.ResourceGroovyMethods;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.cert.Certificate;
+import java.util.Objects;
+
+/**
+ * CodeSource wrapper class that allows specific security policies to be associated with a class
+ * compiled from groovy source.
+ *
+ * @author Steve Goetze
+ * @author Guillaume Laforge
+ * @author Merlyn Albery-Speyer
+ */
+public class GroovyCodeSource {
+
+    /**
+     * The codeSource to be given the generated class.  This can be used by policy file
+     * grants to administer security.
+     */
+    private CodeSource codeSource;
+
+    /**
+     * The name given to the generated class
+     */
+    private String name;
+
+    /**
+     * The groovy source to be compiled and turned into a class
+     */
+    private String scriptText;
+
+    /**
+     * The certificates used to sign the items from the codesource
+     */
+    Certificate[] certs;
+
+    private boolean cachable;
+
+    private File file;
+
+    private URL url;
+
+    public GroovyCodeSource(String script, String name, String codeBase) {
+        this.name = name;
+        this.scriptText = script;
+        this.codeSource = createCodeSource(codeBase);
+        this.cachable = true;
+    }
+
+    /**
+     * Construct a GroovyCodeSource for an inputStream of groovyCode that has an
+     * unknown provenance -- meaning it didn't come from a File or a URL (e.g.&#160;a String).
+     * The supplied codeBase will be used to construct a File URL that should match up
+     * with a java Policy entry that determines the grants to be associated with the
+     * class that will be built from the InputStream.
+     * <p>
+     * The permission groovy.security.GroovyCodeSourcePermission will be used to determine if the given codeBase
+     * may be specified.  That is, the current Policy set must have a GroovyCodeSourcePermission that implies
+     * the codeBase, or an exception will be thrown.  This is to prevent callers from hijacking
+     * existing codeBase policy entries unless explicitly authorized by the user.
+     */
+    public GroovyCodeSource(Reader reader, String name, String codeBase) {
+        this.name = name;
+        this.codeSource = createCodeSource(codeBase);
+
+        try {
+            this.scriptText = IOGroovyMethods.getText(reader);
+        } catch (IOException e) {
+            throw new RuntimeException("Impossible to read the text content from that reader, for script: " + name + " with codeBase: " + codeBase, e);
+        }
+    }
+
+    public GroovyCodeSource(final File infile, final String encoding) throws IOException {
+        // avoid files which confuse us like ones with .. in path
+        final File file = new File(infile.getCanonicalPath());
+        if (!file.exists()) {
+            throw new FileNotFoundException(file.toString() + " (" + file.getAbsolutePath() + ")");
+        }
+        if (file.isDirectory()) {
+            throw new IllegalArgumentException(file.toString() + " (" + file.getAbsolutePath() + ") is a directory not a Groovy source file.");
+        }
+        try {
+            if (!file.canRead())
+                throw new RuntimeException(file.toString() + " can not be read. Check the read permission of the file \"" + file.toString() + "\" (" + file.getAbsolutePath() + ").");
+        }
+        catch (SecurityException e) {
+            throw e;
+        }
+
+        this.file = file;
+        this.cachable = true;
+        //The calls below require access to user.dir - allow here since getName() and getCodeSource() are
+        //package private and used only by the GroovyClassLoader.
+        try {
+            Object[] info = AccessController.doPrivileged(new PrivilegedExceptionAction<Object[]>() {
+                public Object[] run() throws IOException {
+                    // retrieve the content of the file using the provided encoding
+                    if (encoding != null) {
+                        scriptText = ResourceGroovyMethods.getText(infile, encoding);
+                    } else {
+                        scriptText = ResourceGroovyMethods.getText(infile);
+                    }
+
+                    Object[] info = new Object[2];
+                    URL url = file.toURI().toURL();
+                    info[0] = url.toExternalForm();
+                    //toURI().toURL() will encode, but toURL() will not.
+                    info[1] = new CodeSource(url, (Certificate[]) null);
+                    return info;
+                }
+            });
+
+            this.name = (String) info[0];
+            this.codeSource = (CodeSource) info[1];
+        } catch (PrivilegedActionException pae) {
+            Throwable cause = pae.getCause();
+            if (cause != null && cause instanceof IOException) {
+                throw (IOException) cause;
+            }
+            throw new RuntimeException("Could not construct CodeSource for file: " + file, cause);
+        }
+    }
+
+    /**
+     * @param infile the file to create a GroovyCodeSource for.
+     * @throws IOException if an issue arises opening and reading the file.
+     */
+    public GroovyCodeSource(final File infile) throws IOException {
+        this(infile, CharsetToolkit.getDefaultSystemCharset().name());
+    }
+
+    public GroovyCodeSource(URI uri) throws IOException {
+        this(uri.toURL());
+    }
+
+    public GroovyCodeSource(URL url) {
+        if (url == null) {
+            throw new RuntimeException("Could not construct a GroovyCodeSource from a null URL");
+        }
+        this.url = url;
+        // TODO: GROOVY-6561: GroovyMain got the name this way: script.substring(script.lastIndexOf("/") + 1)
+        this.name = url.toExternalForm();
+        this.codeSource = new CodeSource(url, (java.security.cert.Certificate[]) null);
+        try {
+            String contentEncoding = getContentEncoding(url);
+            if (contentEncoding != null) {
+                this.scriptText = ResourceGroovyMethods.getText(url, contentEncoding);
+            } else {
+                this.scriptText = ResourceGroovyMethods.getText(url); // falls-back on default encoding
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Impossible to read the text content from " + name, e);
+        }
+    }
+
+    /**
+     * TODO(jwagenleitner): remove or fix in future release
+     *
+     * According to the spec getContentEncoding() returns the Content-Encoding
+     * HTTP Header which typically carries values such as 'gzip' or 'deflate'
+     * and is not the character set encoding. For compatibility in 2.4.x,
+     * this behavior is retained but should be removed or fixed (parse
+     * charset from Content-Type header) in future releases.
+     *
+     * see GROOVY-8056 and https://github.com/apache/groovy/pull/500
+     */
+    private static String getContentEncoding(URL url) throws IOException {
+        URLConnection urlConnection = url.openConnection();
+        String encoding = urlConnection.getContentEncoding();
+        try {
+            IOGroovyMethods.closeQuietly(urlConnection.getInputStream());
+        } catch (IOException ignore) {
+            // For compatibility, ignore exceptions from getInputStream() call
+        }
+        return encoding;
+    }
+
+    CodeSource getCodeSource() {
+        return codeSource;
+    }
+
+    public String getScriptText() {
+        return scriptText;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public URL getURL() {
+        return url;
+    }
+
+    public void setCachable(boolean b) {
+        cachable = b;
+    }
+
+    public boolean isCachable() {
+        return cachable;
+    }
+
+    private static CodeSource createCodeSource(final String codeBase) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
+        }
+        try {
+            return new CodeSource(new URL("file", "", codeBase), (java.security.cert.Certificate[]) null);
+        }
+        catch (MalformedURLException e) {
+            throw new RuntimeException("A CodeSource file URL cannot be constructed from the supplied codeBase: " + codeBase);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        GroovyCodeSource that = (GroovyCodeSource) o;
+        return Objects.equals(codeSource, that.codeSource);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(codeSource);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyInterceptable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyInterceptable.java b/src/main/groovy/groovy/lang/GroovyInterceptable.java
new file mode 100644
index 0000000..8f83354
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyInterceptable.java
@@ -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.
+ */
+package groovy.lang;
+
+/**
+ * Marker interface used to notify that all methods should be intercepted through the <code>invokeMethod</code> mechanism
+ * of <code>GroovyObject</code>.
+ *
+ * @author Guillaume Laforge
+ */
+public interface GroovyInterceptable extends GroovyObject {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyObject.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyObject.java b/src/main/groovy/groovy/lang/GroovyObject.java
new file mode 100644
index 0000000..5f271e3
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyObject.java
@@ -0,0 +1,68 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * The interface implemented by all Groovy objects.
+ * <p>
+ * Especially handy for using Groovy objects when in the Java world.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public interface GroovyObject {
+
+    /**
+     * Invokes the given method.
+     *
+     * @param name the name of the method to call
+     * @param args the arguments to use for the method call
+     * @return the result of invoking the method
+     */
+    Object invokeMethod(String name, Object args);
+
+    /**
+     * Retrieves a property value.
+     *
+     * @param propertyName the name of the property of interest
+     * @return the given property
+     */
+    Object getProperty(String propertyName);
+
+    /**
+     * Sets the given property to the new value.
+     *
+     * @param propertyName the name of the property of interest
+     * @param newValue     the new value for the property
+     */
+    void setProperty(String propertyName, Object newValue);
+
+    /**
+     * Returns the metaclass for a given class.
+     *
+     * @return the metaClass of this instance
+     */
+    MetaClass getMetaClass();
+
+    /**
+     * Allows the MetaClass to be replaced with a derived implementation.
+     *
+     * @param metaClass the new metaclass
+     */
+    void setMetaClass(MetaClass metaClass);
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyObjectSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyObjectSupport.java b/src/main/groovy/groovy/lang/GroovyObjectSupport.java
new file mode 100644
index 0000000..cf7a77f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyObjectSupport.java
@@ -0,0 +1,63 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * A useful base class for Java objects wishing to be Groovy objects
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public abstract class GroovyObjectSupport implements GroovyObject {
+
+    // never persist the MetaClass
+    private transient MetaClass metaClass;
+
+    public GroovyObjectSupport() {
+        this.metaClass = getDefaultMetaClass();
+    }
+
+    public Object getProperty(String property) {
+        return getMetaClass().getProperty(this, property);
+    }
+
+    public void setProperty(String property, Object newValue) {
+        getMetaClass().setProperty(this, property, newValue);
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        return getMetaClass().invokeMethod(this, name, args);
+    }
+
+    public MetaClass getMetaClass() {
+        return this.metaClass;
+    }
+
+    public void setMetaClass(MetaClass metaClass) {
+        this.metaClass =
+                null == metaClass
+                    ? getDefaultMetaClass()
+                    : metaClass;
+    }
+
+    private MetaClass getDefaultMetaClass() {
+        return InvokerHelper.getMetaClass(this.getClass());
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyResourceLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyResourceLoader.java b/src/main/groovy/groovy/lang/GroovyResourceLoader.java
new file mode 100644
index 0000000..7abe202
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyResourceLoader.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 groovy.lang;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Allows frameworks that integrate with Groovy to determine how Groovy files are resolved.
+ * 
+ * @author Steven Devijver
+ */
+public interface GroovyResourceLoader {
+
+    /**
+     * Loads a Groovy source file given its name.
+     *
+     * @param filename name of the file
+     * @return a URL
+     * @throws java.net.MalformedURLException if the URL is invalid
+     */
+    URL loadGroovySource(String filename) throws MalformedURLException;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/GroovyRuntimeException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/GroovyRuntimeException.java b/src/main/groovy/groovy/lang/GroovyRuntimeException.java
new file mode 100644
index 0000000..33eb51c
--- /dev/null
+++ b/src/main/groovy/groovy/lang/GroovyRuntimeException.java
@@ -0,0 +1,88 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ModuleNode;
+
+/**
+ * An exception thrown by the interpreter
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class GroovyRuntimeException extends RuntimeException {
+
+    private ModuleNode module;
+    private ASTNode node;
+
+    public GroovyRuntimeException() {
+    }
+
+    public GroovyRuntimeException(String message) {
+        super(message);
+    }
+
+    public GroovyRuntimeException(String message, ASTNode node) {
+        super(message);
+        this.node = node;
+    }
+
+    public GroovyRuntimeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public GroovyRuntimeException(Throwable t) {
+        super();
+        initCause(t);
+    }
+
+    public void setModule(ModuleNode module) {
+        this.module = module;
+    }
+
+    public ModuleNode getModule() {
+        return module;
+    }
+
+    public String getMessage() {
+        return getMessageWithoutLocationText() + getLocationText();
+    }
+
+    public ASTNode getNode() {
+        return node;
+    }
+
+    public String getMessageWithoutLocationText() {
+        return super.getMessage();
+    }
+
+    protected String getLocationText() {
+        String answer = ". ";
+        if (node != null) {
+            answer += "At [" + node.getLineNumber() + ":" + node.getColumnNumber() + "] ";
+        }
+        if (module != null) {
+            answer += module.getDescription();
+        }
+        if (answer.equals(". ")) {
+            return "";
+        }
+        return answer;
+    }
+}


[28/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/builder/SimpleStrategy.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/builder/SimpleStrategy.java b/src/main/groovy/groovy/transform/builder/SimpleStrategy.java
new file mode 100644
index 0000000..7956ac6
--- /dev/null
+++ b/src/main/groovy/groovy/transform/builder/SimpleStrategy.java
@@ -0,0 +1,132 @@
+/*
+ *  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 groovy.transform.builder;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.codehaus.groovy.transform.BuilderASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.getInstancePropertyFields;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
+import static org.codehaus.groovy.transform.AbstractASTTransformation.getMemberStringValue;
+import static org.codehaus.groovy.transform.BuilderASTTransformation.NO_EXCEPTIONS;
+
+/**
+ * This strategy is used with the {@link Builder} AST transform to modify your Groovy objects so that the
+ * setter methods for properties return the original object, thus allowing chained usage of the setters.
+ *
+ * You use it as follows:
+ * <pre class="groovyTestCase">
+ * import groovy.transform.builder.*
+ *
+ * {@code @Builder}(builderStrategy=SimpleStrategy)
+ * class Person {
+ *     String firstName
+ *     String lastName
+ *     int age
+ * }
+ * def person = new Person().setFirstName("Robert").setLastName("Lewandowski").setAge(21)
+ * assert person.firstName == "Robert"
+ * assert person.lastName == "Lewandowski"
+ * assert person.age == 21
+ * </pre>
+ * The {@code prefix} annotation attribute can be used to create setters with a different naming convention, e.g. with the prefix set to the empty String, you would use your setters as follows:
+ * <pre>
+ * def p1 = new Person().firstName("Robert").lastName("Lewandowski").age(21)
+ * </pre>
+ * or using a prefix of 'with':
+ * <pre>
+ * def p2 = new Person().withFirstName("Robert").withLastName("Lewandowski").withAge(21)
+ * </pre>
+ * When using the default prefix of "set", Groovy's normal setters will be replaced by the chained versions. When using
+ * a custom prefix, Groovy's unchained setters will still be available for use in the normal unchained fashion.
+ *
+ * The 'useSetters' annotation attribute can be used for writable properties as per the {@code Builder} transform documentation.
+ * The other annotation attributes for the {@code @Builder} transform for configuring the building process aren't applicable for this strategy.
+ *
+ * @author Paul King
+ */
+public class SimpleStrategy extends BuilderASTTransformation.AbstractBuilderStrategy {
+    public void build(BuilderASTTransformation transform, AnnotatedNode annotatedNode, AnnotationNode anno) {
+        if (!(annotatedNode instanceof ClassNode)) {
+            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: building for " +
+                    annotatedNode.getClass().getSimpleName() + " not supported by " + getClass().getSimpleName(), annotatedNode);
+            return;
+        }
+        ClassNode buildee = (ClassNode) annotatedNode;
+        if (unsupportedAttribute(transform, anno, "builderClassName")) return;
+        if (unsupportedAttribute(transform, anno, "buildMethodName")) return;
+        if (unsupportedAttribute(transform, anno, "builderMethodName")) return;
+        if (unsupportedAttribute(transform, anno, "forClass")) return;
+        if (unsupportedAttribute(transform, anno, "includeSuperProperties")) return;
+        if (unsupportedAttribute(transform, anno, "allProperties")) return;
+        boolean useSetters = transform.memberHasValue(anno, "useSetters", true);
+        boolean allNames = transform.memberHasValue(anno, "allNames", true);
+
+        List<String> excludes = new ArrayList<String>();
+        List<String> includes = new ArrayList<String>();
+        includes.add(Undefined.STRING);
+        if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
+        if (includes.size() == 1 && Undefined.isUndefined(includes.get(0))) includes = null;
+        String prefix = getMemberStringValue(anno, "prefix", "set");
+        List<FieldNode> fields = getFields(transform, anno, buildee);
+        if (includes != null) {
+            for (String name : includes) {
+                checkKnownField(transform, anno, name, fields);
+            }
+        }
+        for (FieldNode field : fields) {
+            String fieldName = field.getName();
+            if (!AbstractASTTransformation.shouldSkipUndefinedAware(fieldName, excludes, includes, allNames)) {
+                String methodName = getSetterName(prefix, fieldName);
+                Parameter parameter = param(field.getType(), fieldName);
+                buildee.addMethod(methodName, Opcodes.ACC_PUBLIC, newClass(buildee), params(parameter), NO_EXCEPTIONS, block(
+                                stmt(useSetters && !field.isFinal()
+                                                ? callThisX(getSetterName("set", fieldName), varX(parameter))
+                                                : assignX(fieldX(field), varX(parameter))
+                                ),
+                                returnS(varX("this")))
+                );
+            }
+        }
+    }
+
+    @Override
+    protected List<FieldNode> getFields(BuilderASTTransformation transform, AnnotationNode anno, ClassNode buildee) {
+        return getInstancePropertyFields(buildee);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/ClosureParams.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/ClosureParams.java b/src/main/groovy/groovy/transform/stc/ClosureParams.java
new file mode 100644
index 0000000..e788d44
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/ClosureParams.java
@@ -0,0 +1,64 @@
+/*
+ *  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 groovy.transform.stc;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Parameter annotation aimed at helping IDEs or the static type checker to infer the
+ * parameter types of a closure. Without this annotation, a method signature may look like
+ * this:<p>
+ * <code>public &lt;T,R&gt; List&lt;R&gt; doSomething(List&lt;T&gt; source, Closure&lt;R&gt; consumer)</code>
+ * <p>
+ * <p>The problem this annotation tries to solve is to define the expected parameter types of the
+ * <i>consumer</i> closure. The generics type defined in <code>Closure&lt;R&gt;</code> correspond to the
+ * result type of the closure, but tell nothing about what the closure must accept as arguments.</p>
+ * <p></p>
+ * <p>There's no way in Java or Groovy to express the type signature of the expected closure call method from
+ * outside the closure itself, so we rely on an annotation here. Unfortunately, annotations also have limitations
+ * (like not being able to use generics placeholder as annotation values) that prevent us from expressing the
+ * type directly.</p>
+ * <p>Additionally, closures are polymorphic. This means that a single closure can be used with different, valid,
+ * parameter signatures. A typical use case can be found when a closure accepts either a {@link java.util.Map.Entry}
+ * or a (key,value) pair, like the {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#each(java.util.Map, groovy.lang.Closure)}
+ * method.</p>
+ * <p>For those reasons, the {@link ClosureParams} annotation takes these arguments:
+ * <ul>
+ *     <li>{@link ClosureParams#value()} defines a {@link groovy.transform.stc.ClosureSignatureHint} hint class
+ *     that the compiler will use to infer the parameter types</li>
+ *     <li>{@link ClosureParams#conflictResolutionStrategy()} defines a {@link groovy.transform.stc.ClosureSignatureConflictResolver} resolver
+ *     class that the compiler will use to potentially reduce ambiguities remaining after initial inference calculations</li>
+ *     <li>{@link ClosureParams#options()}, a set of options that are passed to the hint when the type is inferred (and also available to the resolver)</li>
+ * </ul>
+ * </p>
+ * <p>As a result, the previous signature can be written like this:</p>
+ * <code>public &lt;T,R&gt; List&lt;R&gt; doSomething(List&lt;T&gt; source, @ClosureParams(FirstParam.FirstGenericType.class) Closure&lt;R&gt; consumer)</code>
+ * <p>Which uses the {@link FirstParam.FirstGenericType} first generic type of the first argument</p> hint to tell that the only expected
+ * argument type corresponds to the type of the first generic argument type of the first method parameter.
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ClosureParams {
+    Class<? extends ClosureSignatureHint> value();
+    Class<? extends ClosureSignatureConflictResolver> conflictResolutionStrategy() default ClosureSignatureConflictResolver.class;
+    String[] options() default {};
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/ClosureSignatureConflictResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/ClosureSignatureConflictResolver.java b/src/main/groovy/groovy/transform/stc/ClosureSignatureConflictResolver.java
new file mode 100644
index 0000000..d727958
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/ClosureSignatureConflictResolver.java
@@ -0,0 +1,54 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.List;
+
+/**
+ * If multiple candidate signatures are found after applying type hints,
+ * a conflict resolver can attempt to resolve the ambiguity.
+ *
+ * @since 2.5.0
+ */
+public class ClosureSignatureConflictResolver {
+    /**
+     *
+     * @param candidates the list of signatures as determined after applying type hints and performing initial inference calculations
+     * @param receiver the receiver the method is being called on
+     * @param arguments the arguments for the closure
+     * @param closure the closure expression under analysis
+     * @param methodNode the method for which a {@link groovy.lang.Closure} parameter was annotated with {@link ClosureParams}
+     * @param sourceUnit the source unit of the file being compiled
+     * @param compilationUnit the compilation unit of the file being compiled
+     * @param options the options, corresponding to the {@link ClosureParams#options()} found on the annotation
+     * @return a non-null list of signatures, where a signature corresponds to an array of class nodes, each of them matching a parameter. A list with more than one element indicates that all ambiguities haven't yet been resolved.
+     */
+    public List<ClassNode[]> resolve(List<ClassNode[]> candidates, ClassNode receiver, Expression arguments, ClosureExpression closure,
+                                     MethodNode methodNode, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options) {
+        // do nothing by default
+        return candidates;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/ClosureSignatureHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/ClosureSignatureHint.java b/src/main/groovy/groovy/transform/stc/ClosureSignatureHint.java
new file mode 100644
index 0000000..9a77d20
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/ClosureSignatureHint.java
@@ -0,0 +1,144 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.List;
+
+/**
+ * <p>A closure signature hint class is always used in conjunction with the {@link ClosureParams} annotation. It is
+ * called at compile time (or may be used by IDEs) to infer the types of the parameters of a {@link groovy.lang.Closure}.</p>
+
+ * <p>A closure hint class is responsible for generating the list of arguments that a closure accepts. Since closures
+ * may accept several signatures, {@link #getClosureSignatures(org.codehaus.groovy.ast.MethodNode, org.codehaus.groovy.control.SourceUnit, org.codehaus.groovy.control.CompilationUnit, String[], org.codehaus.groovy.ast.ASTNode)} should
+ * return a list.</p>
+ *
+ * <p>Whenever the type checker encounters a method call that targets a method accepting a closure, it will search
+ * for the {@link ClosureParams} annotation on the {@link groovy.lang.Closure} argument. If it is found, then it
+ * creates an instance of the hint class and calls the {@link #getClosureSignatures(org.codehaus.groovy.ast.MethodNode, org.codehaus.groovy.control.SourceUnit, org.codehaus.groovy.control.CompilationUnit, String[], org.codehaus.groovy.ast.ASTNode)}
+ * method, which will in turn return the list of signatures.</p>
+ *
+ * <p><i>Note that the signature concept here is used only to describe the parameter types, not the result type, which
+ * is found in the generic type argument of the {@link groovy.lang.Closure} class.</i></p>
+ *
+ * <p>Several predefined hints can be found, which should cover most of the use cases.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ *
+ */
+public abstract class ClosureSignatureHint {
+
+    /**
+     * A helper method which will extract the n-th generic type from a class node.
+     * @param type the class node from which to pick a generic type
+     * @param gtIndex the index of the generic type to extract
+     * @return the n-th generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
+     */
+    public static ClassNode pickGenericType(ClassNode type, int gtIndex) {
+        final GenericsType[] genericsTypes = type.getGenericsTypes();
+        if (genericsTypes==null || genericsTypes.length<gtIndex) {
+            return ClassHelper.OBJECT_TYPE;
+        }
+        return genericsTypes[gtIndex].getType();
+    }
+
+    /**
+     * A helper method which will extract the n-th generic type from the n-th parameter of a method node.
+     * @param node the method node from which the generic type should be picked
+     * @param parameterIndex the index of the parameter in the method parameter list
+     * @param gtIndex the index of the generic type to extract
+     * @return the generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
+     */
+    public static ClassNode pickGenericType(MethodNode node, int parameterIndex, int gtIndex) {
+        final Parameter[] parameters = node.getParameters();
+        final ClassNode type = parameters[parameterIndex].getOriginType();
+        return pickGenericType(type, gtIndex);
+    }
+
+    /**
+     * <p>Subclasses should implement this method, which returns the list of accepted closure signatures.</p>
+     *
+     * <p>The compiler will call this method each time, in a source file, a method call using a closure
+     * literal is encountered and that the target method has the corresponding {@link groovy.lang.Closure} parameter
+     * annotated with {@link groovy.transform.stc.ClosureParams}. So imagine the following code needs to be compiled:</p>
+     *
+     * <code>@groovy.transform.TypeChecked
+     * void doSomething() {
+     *     println ['a','b'].collect { it.toUpperCase() }
+     * }</code>
+     *
+     * <p>The <i>collect</i> method accepts a closure, but normally, the type checker doesn't have enough type information
+     * in the sole {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#collect(java.util.Collection, groovy.lang.Closure)} method
+     * signature to infer the type of <i>it</i>. With the annotation, it will now try to find an annotation on the closure parameter.
+     * If it finds it, then an instance of the hint class is created and the type checker calls it with the following arguments:</p>
+     * <ul>
+     *     <li>the method node corresponding to the target method (here, the {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#collect(java.util.Collection, groovy.lang.Closure)} method</li>
+     *     <li>the (optional) list of options found in the annotation</li>
+     * </ul>
+     *
+     * <p>Now, the hint instance can return the list of expected parameters. Here, it would have to say that the collect method accepts
+     * a closure for which the only argument is of the type of the first generic type of the first argument.</p>
+     * <p>With that type information, the type checker can now infer that the type of <i>it</i> is <i>String</i>, because the first argument (here the receiver of the collect method)
+     * is a <i>List&lt;String&gt;</i></p>
+     *
+     * <p></p>
+     *
+     * <p>Subclasses are therefore expected to return the signatures according to the available context, which is only the target method and the potential options.</p>
+     *
+     *
+     * @param node the method node for which a {@link groovy.lang.Closure} parameter was annotated with
+     *             {@link ClosureParams}
+     * @param sourceUnit the source unit of the file being compiled
+     * @param compilationUnit the compilation unit of the file being compiled
+     * @param options the options, corresponding to the {@link ClosureParams#options()} found on the annotation  @return a non-null list of signature, where a signature corresponds to an array of class nodes, each of them matching a parameter.
+     * @param usage the AST node, in the compiled file, which triggered a call to this method. Normally only used for logging/error handling
+     */
+    public abstract List<ClassNode[]> getClosureSignatures(MethodNode node, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options, ASTNode usage);
+
+    /**
+     * Finds a class node given a string representing the type. Performs a lookup in the compilation unit to check if it is done in the same source unit.
+     * @param sourceUnit source unit
+     * @param compilationUnit compilation unit
+     * @param className the name of the class we want to get a {@link org.codehaus.groovy.ast.ClassNode} for
+     * @return a ClassNode representing the type
+     */
+    protected ClassNode findClassNode(final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String className) {
+        if (className.endsWith("[]")) {
+            return findClassNode(sourceUnit, compilationUnit, className.substring(0, className.length() - 2)).makeArray();
+        }
+        ClassNode cn = compilationUnit.getClassNode(className);
+        if (cn == null) {
+            try {
+                cn = ClassHelper.make(Class.forName(className, false, sourceUnit.getClassLoader()));
+            } catch (ClassNotFoundException e) {
+                cn = ClassHelper.make(className);
+            }
+        }
+        return cn;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/FirstParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/FirstParam.java b/src/main/groovy/groovy/transform/stc/FirstParam.java
new file mode 100644
index 0000000..81eb0e7
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/FirstParam.java
@@ -0,0 +1,93 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+/**
+ * <p>A hint used to instruct the type checker to pick the first parameter type. For example:</p>
+ * <code>public &lt;T&gt; def doWith(T src, @ClosureParams(FirstParam.class) Closure c) { c.call(src); }</code>
+ *
+ * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class FirstParam extends PickAnyArgumentHint {
+    public FirstParam() {
+        super(0,-1);
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the first generic type of the first parameter type. For example:</p>
+     * <code>void &lt;T&gt; doWithElements(List&lt;T&gt; src, @ClosureParams(FirstParam.FirstGenericType.class) Closure c) { src.each { c.call(it) } }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class FirstGenericType extends PickAnyArgumentHint {
+        public FirstGenericType() {
+            super(0,0);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the second generic type of the first parameter type. For example:</p>
+     * <code>void &lt;T,U&gt; doWithElements(Tuple&lt;T,U&gt; src, @ClosureParams(FirstParam.SecondGenericType.class) Closure c) { src.each { c.call(it) } }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class SecondGenericType extends PickAnyArgumentHint {
+        public SecondGenericType() {
+            super(0,1);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the third generic type of the first parameter type. For example:</p>
+     * <code>void &lt;T,U,V&gt; doWithElements(Triple&lt;T,U,V&gt; src, @ClosureParams(FirstParam.ThirdGenericType.class) Closure c) { src.each { c.call(it) } }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class ThirdGenericType extends PickAnyArgumentHint {
+        public ThirdGenericType() {
+            super(0,2);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the type of the component of the first parameter type, which is therefore
+     * expected to be an array, like in this example:</p>
+     * <code>void &lt;T&gt; doWithArray(T[] array, @ClosureParams(FirstParam.Component.class) Closure c) { array.each { c.call(it)} }</code>
+     */
+    public static class Component extends FirstParam {
+        @Override
+        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
+            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
+            parameterTypes[0] = parameterTypes[0].getComponentType();
+            return parameterTypes;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/FromAbstractTypeMethods.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/FromAbstractTypeMethods.java b/src/main/groovy/groovy/transform/stc/FromAbstractTypeMethods.java
new file mode 100644
index 0000000..e5125f1
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/FromAbstractTypeMethods.java
@@ -0,0 +1,68 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.transform.trait.Traits;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This signature hint uses abstract methods from some type (abstract class or interface) in order
+ * to infer the expected parameter types. This is especially useful for closure parameter type
+ * inference when implicit closure coercion is in action.
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class FromAbstractTypeMethods extends ClosureSignatureHint {
+    @Override
+    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
+        String className = options[0];
+        ClassNode cn = findClassNode(sourceUnit, compilationUnit, className);
+        return extractSignaturesFromMethods(cn);
+    }
+
+    private static List<ClassNode[]> extractSignaturesFromMethods(final ClassNode cn) {
+        List<MethodNode> methods = cn.getAllDeclaredMethods();
+        List<ClassNode[]> signatures = new LinkedList<ClassNode[]>();
+        for (MethodNode method : methods) {
+            if (!method.isSynthetic() && method.isAbstract()) {
+                extractParametersFromMethod(signatures, method);
+            }
+        }
+        return signatures;
+    }
+
+    private static void extractParametersFromMethod(final List<ClassNode[]> signatures, final MethodNode method) {
+        if (Traits.hasDefaultImplementation(method)) return;
+        Parameter[] parameters = method.getParameters();
+        ClassNode[] typeParams = new ClassNode[parameters.length];
+        for (int i = 0; i < parameters.length; i++) {
+            typeParams[i] = parameters[i].getOriginType();
+        }
+        signatures.add(typeParams);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/FromString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/FromString.java b/src/main/groovy/groovy/transform/stc/FromString.java
new file mode 100644
index 0000000..12f9371
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/FromString.java
@@ -0,0 +1,80 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.tools.GenericsUtils;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * <p>A closure parameter hint class that is convenient if you want to use a String representation
+ * of the signature. It makes use of the {@link ClosureParams#options() option strings}, where
+ * each string corresponds to a single signature.</p>
+ *
+ * <p>The following example describes a closure as accepting a single signature (List&lt;T&gt; list -&gt;):</p>
+ *
+ * <code>public &lt;T&gt; T apply(T src, @ClosureParams(value=FromString.class, options="List&lt;T&gt;" Closure&lt;T&gt; cl)</code>
+ *
+ * <p>The next example describes a closure as accepting two signatures (List&lt;T&gt; list -&gt;) and (T t -&gt;):</p>
+ *
+ * <code>public &lt;T&gt; T apply(T src, @ClosureParams(value=FromString.class, options={"List&lt;T&gt;","T"} Closure&lt;T&gt; cl)</code>
+ *
+ * <p>It is advisable not to use this hint as a replacement for the various {@link FirstParam}, {@link SimpleType},
+ * ... hints because it is actually much slower. Using this hint should therefore be limited
+ * to cases where it's not possible to express the signature using the existing hints.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class FromString extends ClosureSignatureHint {
+
+    @Override
+    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
+        List<ClassNode[]> list = new ArrayList<ClassNode[]>(options.length);
+        for (String option : options) {
+            list.add(parseOption(option, sourceUnit, compilationUnit, node, usage));
+        }
+        return list;
+    }
+
+    /**
+     * Parses a string representing a type, that must be aligned with the current context.
+     * For example, <i>"List&lt;T&gt;"</i> must be converted into the appropriate ClassNode
+     * for which <i>T</i> matches the appropriate placeholder.
+     *
+     *
+     * @param option a string representing a type
+     * @param sourceUnit the source unit (of the file being compiled)
+     * @param compilationUnit the compilation unit (of the file being compiled)
+     * @param mn the method node
+     * @param usage
+     * @return a class node if it could be parsed and resolved, null otherwise
+     */
+    private static ClassNode[] parseOption(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) {
+        return GenericsUtils.parseClassNodesFromString(option, sourceUnit, compilationUnit, mn, usage);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/IncorrectTypeHintException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/IncorrectTypeHintException.java b/src/main/groovy/groovy/transform/stc/IncorrectTypeHintException.java
new file mode 100644
index 0000000..aed167a
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/IncorrectTypeHintException.java
@@ -0,0 +1,32 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.syntax.SyntaxException;
+
+public class IncorrectTypeHintException extends SyntaxException {
+    public IncorrectTypeHintException(final MethodNode mn, final Throwable e, int line, int column) {
+        super("Incorrect type hint in @ClosureParams in class "+mn.getDeclaringClass().getName()+" method "+mn.getTypeDescriptor()+" : "+e.getMessage(), e, line, column);
+    }
+
+    public IncorrectTypeHintException(final MethodNode mn, final String msg, final int line, final int column) {
+        super("Incorrect type hint in @ClosureParams in class "+mn.getDeclaringClass().getName()+" method "+mn.getTypeDescriptor()+" : "+msg, line, column);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/MapEntryOrKeyValue.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/MapEntryOrKeyValue.java b/src/main/groovy/groovy/transform/stc/MapEntryOrKeyValue.java
new file mode 100644
index 0000000..9316ef8
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/MapEntryOrKeyValue.java
@@ -0,0 +1,119 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>A special hint which handles a common use case in the Groovy methods that work on maps. In case of an
+ * iteration on a list of map entries, you often want the user to be able to work either on a {@link java.util.Map.Entry} map entry
+ * or on a key,value pair.</p>
+ * <p>The result is a closure which can have the following forms:</p>
+ * <ul>
+ *     <li><code>{ key, value -> ...}</code> where key is the key of a map entry, and value the corresponding value</li>
+ *     <li><code>{ entry -> ... }</code> where entry is a {@link java.util.Map.Entry} map entry</li>
+ *     <li><code>{ ...}</code> where <i>it</i> is an implicit {@link java.util.Map.Entry} map entry</li>
+ * </ul>
+ * <p>This hint handles all those cases by picking the generics from the first argument of the method (by default).</p>
+ * <p>The options array is used to modify the behavior of this hint. Each string in the option array consists of
+ * a key=value pair.</p>
+ * <ul>
+ *     <li><i>argNum=index</i> of the parameter representing the map (by default, 0)</li>
+ *     <li><i>index=true or false</i>, by default false. If true, then an additional "int" parameter is added,
+ *     for "withIndex" variants</li>
+ * </ul>
+ * <code>void doSomething(String str, Map&lt;K,&gt;V map, @ClosureParams(value=MapEntryOrKeyValue.class,options="argNum=1") Closure c) { ... }</code>
+ */
+public class MapEntryOrKeyValue extends ClosureSignatureHint {
+    private static final ClassNode MAPENTRY_TYPE = ClassHelper.make(Map.Entry.class);
+
+    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
+        Options opt;
+        try {
+            opt = Options.parse(node, usage, options);
+        } catch (IncorrectTypeHintException e) {
+            sourceUnit.addError(e);
+            return Collections.emptyList();
+        }
+        GenericsType[] genericsTypes = node.getParameters()[opt.parameterIndex].getOriginType().getGenericsTypes();
+        if (genericsTypes==null) {
+            // would happen if you have a raw Map type for example
+            genericsTypes = new GenericsType[] {
+                new GenericsType(ClassHelper.OBJECT_TYPE),
+                new GenericsType(ClassHelper.OBJECT_TYPE)
+            };
+        }
+        ClassNode[] firstSig;
+        ClassNode[] secondSig;
+        ClassNode mapEntry = MAPENTRY_TYPE.getPlainNodeReference();
+        mapEntry.setGenericsTypes(genericsTypes);
+        if (opt.generateIndex) {
+            firstSig = new ClassNode[] {genericsTypes[0].getType(), genericsTypes[1].getType(), ClassHelper.int_TYPE};
+            secondSig = new ClassNode[] {mapEntry, ClassHelper.int_TYPE};
+
+        } else {
+            firstSig = new ClassNode[] {genericsTypes[0].getType(), genericsTypes[1].getType()};
+            secondSig = new ClassNode[] {mapEntry};
+        }
+        return Arrays.asList(firstSig, secondSig);
+    }
+    
+    private static final class Options {
+        final int parameterIndex;
+        final boolean generateIndex;
+
+        private Options(final int parameterIndex, final boolean generateIndex) {
+            this.parameterIndex = parameterIndex;
+            this.generateIndex = generateIndex;
+        }
+        
+        static Options parse(MethodNode mn, ASTNode source, String[] options) throws IncorrectTypeHintException {
+            int pIndex = 0;
+            boolean generateIndex = false;
+            for (String option : options) {
+                String[] keyValue = option.split("=");
+                if (keyValue.length==2) {
+                    String key = keyValue[0];
+                    String value = keyValue[1];
+                    if ("argNum".equals(key)) {
+                        pIndex = Integer.parseInt(value);
+                    } else if ("index".equals(key)) {
+                        generateIndex = Boolean.valueOf(value);
+                    } else {
+                        throw new IncorrectTypeHintException(mn, "Unrecognized option: "+key, source.getLineNumber(), source.getColumnNumber());
+                    }
+                } else {
+                    throw new IncorrectTypeHintException(mn, "Incorrect option format. Should be argNum=<num> or index=<boolean> ", source.getLineNumber(), source.getColumnNumber());
+                }
+            }
+            return new Options(pIndex, generateIndex);
+        }
+    } 
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/PickAnyArgumentHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/PickAnyArgumentHint.java b/src/main/groovy/groovy/transform/stc/PickAnyArgumentHint.java
new file mode 100644
index 0000000..6a5463f
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/PickAnyArgumentHint.java
@@ -0,0 +1,75 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+/**
+ * <p>Base class for hints which use the type of a parameter of the annotated method as the signature.
+ * This can optionally use a generic type of the selected parameter as the hint. For example, imagine the following
+ * method:</p>
+ * <code>void foo(A firstArg, B secondArg, Closure c) {...}</code>
+ * <p>If the <i>c</i> closure should be <code>{ B it -> ...}</code>, then we can see that the parameter type
+ * should be picked from the second parameter of the foo method, which is what {@link groovy.transform.stc.PickAnyArgumentHint}
+ * lets you do.</p>
+ * <p>Alternatively, the method may look like this:</p>
+ * <code>void &lt;T&gt; foo(A&lt;T&gt; firstArg, B secondArg, Closure c) {...}</code>
+ * <p>in which case if you want to express the fact that <i>c</i> should accept a &lt;T&gt; then you can use the
+ * {@link #genericTypeIndex} value.</p>
+ * <p></p>
+ * <p>This class is extended by several hint providers that make it easier to use as annotation values.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class PickAnyArgumentHint extends SingleSignatureClosureHint {
+    private final int parameterIndex;
+    private final int genericTypeIndex;
+
+    /**
+     * Creates the an argument picker which extracts the type of the first parameter.
+     */
+    public PickAnyArgumentHint() {
+        this(0,-1);
+    }
+
+    /**
+     * Creates a picker which will extract the parameterIndex-th parameter type, or its
+     * genericTypeIndex-th generic type genericTypeIndex is &gt;=0.
+     * @param parameterIndex the index of the parameter from which to extract the type
+     * @param genericTypeIndex if &gt;=0, then returns the corresponding generic type instead of the parameter type.
+     */
+    public PickAnyArgumentHint(final int parameterIndex, final int genericTypeIndex) {
+        this.parameterIndex = parameterIndex;
+        this.genericTypeIndex = genericTypeIndex;
+    }
+
+    @Override
+    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
+        ClassNode type = node.getParameters()[parameterIndex].getOriginType();
+        if (genericTypeIndex>=0) {
+            type = pickGenericType(type, genericTypeIndex);
+        }
+        return new ClassNode[]{type};
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/PickFirstResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/PickFirstResolver.java b/src/main/groovy/groovy/transform/stc/PickFirstResolver.java
new file mode 100644
index 0000000..0bebb3e
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/PickFirstResolver.java
@@ -0,0 +1,45 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Returns the first of several candidates found.
+ * This is useful if several types should be supported but only the first
+ * should be the default/inferred type. Other options in the list are
+ * obtained through explicitly typing the parameter(s).
+ *
+ * @since 2.5.0
+ */
+public class PickFirstResolver extends ClosureSignatureConflictResolver {
+    @Override
+    public List<ClassNode[]> resolve(List<ClassNode[]> candidates, ClassNode receiver, Expression arguments, ClosureExpression closure,
+                                     MethodNode methodNode, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options) {
+        return Collections.singletonList(candidates.get(0));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/SecondParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/SecondParam.java b/src/main/groovy/groovy/transform/stc/SecondParam.java
new file mode 100644
index 0000000..c077750
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/SecondParam.java
@@ -0,0 +1,93 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+/**
+ * <p>A hint used to instruct the type checker to pick the second parameter type. For example:</p>
+ * <code>public &lt;T,U&gt; def doWith(T first, U second, @ClosureParams(SecondParam.class) Closure c) { c.call(src); }</code>
+ *
+ * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class SecondParam extends PickAnyArgumentHint {
+    public SecondParam() {
+        super(1,-1);
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the first generic type of the second parameter type. For example:</p>
+     * <code>void &lt;T&gt; doWithElements(String base, List&lt;T&gt; src, @ClosureParams(SecondParam.FirstGenericType.class) Closure c) { ... } }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class FirstGenericType extends PickAnyArgumentHint {
+        public FirstGenericType() {
+            super(1,0);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the second generic type of the second parameter type. For example:</p>
+     * <code>void &lt;T,U&gt; doWithElements(String base, Tuple&lt;T,U&gt; src, @ClosureParams(SecondParam.SecondGenericType.class) Closure c) { ... }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class SecondGenericType extends PickAnyArgumentHint {
+        public SecondGenericType() {
+            super(1,1);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the second generic type of the second parameter type. For example:</p>
+     * <code>void &lt;T,U,V&gt; doWithElements(String base, Triple&lt;T,U,V&gt; src, @ClosureParams(SecondParam.ThirdGenericType.class) Closure c) { ... }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class ThirdGenericType extends PickAnyArgumentHint {
+        public ThirdGenericType() {
+            super(1,2);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the type of the component of the second parameter type, which is therefore
+     * expected to be an array, like in this example:</p>
+     * <code>void &lt;T&gt; doWithArray(String first, T[] array, @ClosureParams(FirstParam.Component.class) Closure c) { ... }</code>
+     */
+    public static class Component extends SecondParam {
+        @Override
+        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
+            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
+            parameterTypes[0] = parameterTypes[0].getComponentType();
+            return parameterTypes;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/SimpleType.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/SimpleType.java b/src/main/groovy/groovy/transform/stc/SimpleType.java
new file mode 100644
index 0000000..8866e3b
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/SimpleType.java
@@ -0,0 +1,36 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+public class SimpleType extends SingleSignatureClosureHint {
+    @Override
+    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
+        ClassNode[] result = new ClassNode[options.length];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = findClassNode(sourceUnit, unit, options[i]);
+        }
+        return result;
+    }
+ }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/SingleSignatureClosureHint.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/SingleSignatureClosureHint.java b/src/main/groovy/groovy/transform/stc/SingleSignatureClosureHint.java
new file mode 100644
index 0000000..3db66ff
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/SingleSignatureClosureHint.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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A simplified version of a {@link groovy.transform.stc.ClosureSignatureHint} which is suitable
+ * for monomorphic closures, that is to say closures which only respond to a single signature.
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public abstract class SingleSignatureClosureHint extends ClosureSignatureHint {
+
+    public abstract ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage);
+
+    public List<ClassNode[]> getClosureSignatures(final MethodNode node, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String[] options, final ASTNode usage) {
+        return Collections.singletonList(getParameterTypes(node, options, sourceUnit, compilationUnit, usage));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/transform/stc/ThirdParam.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/transform/stc/ThirdParam.java b/src/main/groovy/groovy/transform/stc/ThirdParam.java
new file mode 100644
index 0000000..c493e36
--- /dev/null
+++ b/src/main/groovy/groovy/transform/stc/ThirdParam.java
@@ -0,0 +1,94 @@
+/*
+ *  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 groovy.transform.stc;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+/**
+ * <p>A hint used to instruct the type checker to pick the third parameter type. For example:</p>
+ * <code>public &lt;T,U,V&gt; def doWith(T first, U second, V third, @ClosureParams(ThirdParam.class) Closure c) { ... }</code>
+ *
+ * <p>This class has several inner classes that also helps picking generic argument types instead of the parameter type.</p>
+ *
+ * @author Cédric Champeau
+ * @since 2.3.0
+ */
+public class ThirdParam extends PickAnyArgumentHint {
+    public ThirdParam() {
+        super(2,-1);
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the first generic type of the third parameter type. For example:</p>
+     * <code>void &lt;T&gt; doWithElements(String first, Integer second, List&lt;T&gt; third, @ClosureParams(SecondParam.FirstGenericType.class) Closure c) { ... } }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class FirstGenericType extends PickAnyArgumentHint {
+        public FirstGenericType() {
+            super(2,0);
+        }
+    }
+
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the second generic type of the third parameter type. For example:</p>
+     * <code>void &lt;T,U&gt; doWithElements(String first, Integer second, Tuple&lt;T,U&gt; third, @ClosureParams(SecondParam.SecondGenericType.class) Closure c) { ... }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class SecondGenericType extends PickAnyArgumentHint {
+        public SecondGenericType() {
+            super(2,1);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the second generic type of the third parameter type. For example:</p>
+     * <code>void &lt;T,U,V&gt; doWithElements(String first, Integer second, Triple&lt;T,U,V&gt; src, @ClosureParams(SecondParam.ThirdGenericType.class) Closure c) { ... }</code>
+     *
+     * @author Cédric Champeau
+     * @since 2.3.0
+     */
+    public static class ThirdGenericType extends PickAnyArgumentHint {
+        public ThirdGenericType() {
+            super(2,2);
+        }
+    }
+
+    /**
+     * <p>A hint used to instruct the type checker to pick the type of the component of the third parameter type, which is therefore
+     * expected to be an array, like in this example:</p>
+     * <code>void &lt;T&gt; doWithArray(String first, int second, T[] third, @ClosureParams(FirstParam.Component.class) Closure c) { ... }</code>
+     */
+    public static class Component extends ThirdParam {
+        @Override
+        public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
+            final ClassNode[] parameterTypes = super.getParameterTypes(node, options, sourceUnit, unit, usage);
+            parameterTypes[0] = parameterTypes[0].getComponentType();
+            return parameterTypes;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/ui/GroovyMain.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/ui/GroovyMain.java b/src/main/groovy/groovy/ui/GroovyMain.java
new file mode 100644
index 0000000..cedb8fb
--- /dev/null
+++ b/src/main/groovy/groovy/ui/GroovyMain.java
@@ -0,0 +1,597 @@
+/*
+ *  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 groovy.ui;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyCodeSource;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.GroovyShell;
+import groovy.lang.GroovySystem;
+import groovy.lang.MissingMethodException;
+import groovy.lang.Script;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.customizers.ImportCustomizer;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+import org.codehaus.groovy.runtime.ResourceGroovyMethods;
+import org.codehaus.groovy.runtime.StackTraceUtils;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import static org.apache.commons.cli.Option.builder;
+
+/**
+ * A Command line to execute groovy.
+ */
+public class GroovyMain {
+
+    // arguments to the script
+    private List args;
+
+    // is this a file on disk
+    private boolean isScriptFile;
+
+    // filename or content of script
+    private String script;
+
+    // process args as input files
+    private boolean processFiles;
+
+    // edit input files in place
+    private boolean editFiles;
+
+    // automatically output the result of each script
+    private boolean autoOutput;
+
+    // automatically split each line using the splitpattern
+    private boolean autoSplit;
+
+    // The pattern used to split the current line
+    private String splitPattern = " ";
+
+    // process sockets
+    private boolean processSockets;
+
+    // port to listen on when processing sockets
+    private int port;
+
+    // backup input files with extension
+    private String backupExtension;
+
+    // do you want full stack traces in script exceptions?
+    private boolean debug = false;
+
+    // Compiler configuration, used to set the encodings of the scripts/classes
+    private CompilerConfiguration conf = new CompilerConfiguration(System.getProperties());
+
+    /**
+     * Main CLI interface.
+     *
+     * @param args all command line args.
+     */
+    public static void main(String args[]) {
+        processArgs(args, System.out);
+    }
+
+    // package-level visibility for testing purposes (just usage/errors at this stage)
+    // TODO: should we have an 'err' printstream too for ParseException?
+    static void processArgs(String[] args, final PrintStream out) {
+        Options options = buildOptions();
+
+        try {
+            CommandLine cmd = parseCommandLine(options, args);
+
+            if (cmd.hasOption('h')) {
+                printHelp(out, options);
+            } else if (cmd.hasOption('v')) {
+                String version = GroovySystem.getVersion();
+                out.println("Groovy Version: " + version + " JVM: " + System.getProperty("java.version") + 
+                        " Vendor: " + System.getProperty("java.vm.vendor")  + " OS: " + System.getProperty("os.name"));
+            } else {
+                // If we fail, then exit with an error so scripting frameworks can catch it
+                // TODO: pass printstream(s) down through process
+                if (!process(cmd)) {
+                    System.exit(1);
+                }
+            }
+        } catch (ParseException pe) {
+            out.println("error: " + pe.getMessage());
+            printHelp(out, options);
+        } catch (IOException ioe) {
+            out.println("error: " + ioe.getMessage());
+        }
+    }
+
+    private static void printHelp(PrintStream out, Options options) {
+        HelpFormatter formatter = new HelpFormatter();
+        PrintWriter pw = new PrintWriter(out);
+
+        formatter.printHelp(
+            pw,
+            80,
+            "groovy [options] [filename] [args]",
+            "The Groovy command line processor.\nOptions:",
+            options,
+            2,
+            4,
+            null, // footer
+            false);
+       
+        pw.flush();
+    }
+
+    /**
+     * Parse the command line.
+     *
+     * @param options the options parser.
+     * @param args    the command line args.
+     * @return parsed command line.
+     * @throws ParseException if there was a problem.
+     */
+    private static CommandLine parseCommandLine(Options options, String[] args) throws ParseException {
+        CommandLineParser parser = new DefaultParser();
+        return parser.parse(options, args, true);
+    }
+
+    /**
+     * Build the options parser.
+     *
+     * @return an options parser.
+     */
+    private static Options buildOptions() {
+        return new Options()
+                .addOption(builder("classpath").hasArg().argName("path").desc("Specify where to find the class files - must be first argument").build())
+                .addOption(builder("cp").longOpt("classpath").hasArg().argName("path").desc("Aliases for '-classpath'").build())
+                .addOption(builder("D").longOpt("define").desc("Define a system property").numberOfArgs(2).valueSeparator().argName("name=value").build())
+                .addOption(
+                        builder().longOpt("disableopt")
+                                .desc("Disables one or all optimization elements; " +
+                                        "optlist can be a comma separated list with the elements: " +
+                                        "all (disables all optimizations), " +
+                                        "int (disable any int based optimizations)")
+                                .hasArg().argName("optlist").build())
+                .addOption(builder("h").hasArg(false).desc("Usage information").longOpt("help").build())
+                .addOption(builder("d").hasArg(false).desc("Debug mode will print out full stack traces").longOpt("debug").build())
+                .addOption(builder("v").hasArg(false).desc("Display the Groovy and JVM versions").longOpt("version").build())
+                .addOption(builder("c").argName("charset").hasArg().desc("Specify the encoding of the files").longOpt("encoding").build())
+                .addOption(builder("e").argName("script").hasArg().desc("Specify a command line script").build())
+                .addOption(builder("i").argName("extension").optionalArg(true).desc("Modify files in place; create backup if extension is given (e.g. \'.bak\')").build())
+                .addOption(builder("n").hasArg(false).desc("Process files line by line using implicit 'line' variable").build())
+                .addOption(builder("p").hasArg(false).desc("Process files line by line and print result (see also -n)").build())
+                .addOption(builder("pa").hasArg(false).desc("Generate metadata for reflection on method parameter names (jdk8+ only)").longOpt("parameters").build())
+                .addOption(builder("l").argName("port").optionalArg(true).desc("Listen on a port and process inbound lines (default: 1960)").build())
+                .addOption(builder("a").argName("splitPattern").optionalArg(true).desc("Split lines using splitPattern (default '\\s') using implicit 'split' variable").longOpt("autosplit").build())
+                .addOption(builder().longOpt("indy").desc("Enables compilation using invokedynamic").build())
+                .addOption(builder().longOpt("configscript").hasArg().desc("A script for tweaking the configuration options").build())
+                .addOption(builder("b").longOpt("basescript").hasArg().argName("class").desc("Base class name for scripts (must derive from Script)").build());
+    }
+
+    /**
+     * Process the users request.
+     *
+     * @param line the parsed command line.
+     * @throws ParseException if invalid options are chosen
+     */
+     private static boolean process(CommandLine line) throws ParseException, IOException {
+        List args = line.getArgList();
+        
+        if (line.hasOption('D')) {
+            Properties optionProperties = line.getOptionProperties("D");
+            Enumeration<String> propertyNames = (Enumeration<String>) optionProperties.propertyNames();
+            while (propertyNames.hasMoreElements()) {
+                String nextName = propertyNames.nextElement();
+                System.setProperty(nextName, optionProperties.getProperty(nextName));
+            }
+        }
+
+        GroovyMain main = new GroovyMain();
+        
+        // add the ability to parse scripts with a specified encoding
+        main.conf.setSourceEncoding(line.getOptionValue('c',main.conf.getSourceEncoding()));
+
+        main.isScriptFile = !line.hasOption('e');
+        main.debug = line.hasOption('d');
+        main.conf.setDebug(main.debug);
+        main.conf.setParameters(line.hasOption("pa"));
+        main.processFiles = line.hasOption('p') || line.hasOption('n');
+        main.autoOutput = line.hasOption('p');
+        main.editFiles = line.hasOption('i');
+        if (main.editFiles) {
+            main.backupExtension = line.getOptionValue('i');
+        }
+        main.autoSplit = line.hasOption('a');
+        String sp = line.getOptionValue('a');
+        if (sp != null)
+            main.splitPattern = sp;
+
+        if (main.isScriptFile) {
+            if (args.isEmpty())
+                throw new ParseException("neither -e or filename provided");
+
+            main.script = (String) args.remove(0);
+            if (main.script.endsWith(".java"))
+                throw new ParseException("error: cannot compile file with .java extension: " + main.script);
+        } else {
+            main.script = line.getOptionValue('e');
+        }
+
+        main.processSockets = line.hasOption('l');
+        if (main.processSockets) {
+            String p = line.getOptionValue('l', "1960"); // default port to listen to
+            main.port = Integer.parseInt(p);
+        }
+        
+        // we use "," as default, because then split will create
+        // an empty array if no option is set
+        String disabled = line.getOptionValue("disableopt", ",");
+        String[] deopts = disabled.split(",");
+        for (String deopt_i : deopts) {
+            main.conf.getOptimizationOptions().put(deopt_i,false);
+        }
+        
+        if (line.hasOption("indy")) {
+            CompilerConfiguration.DEFAULT.getOptimizationOptions().put("indy", true);
+            main.conf.getOptimizationOptions().put("indy", true);
+        }
+
+         if (line.hasOption("basescript")) {
+             main.conf.setScriptBaseClass(line.getOptionValue("basescript"));
+         }
+
+        String configScripts = System.getProperty("groovy.starter.configscripts", null);
+        if (line.hasOption("configscript") || (configScripts != null && !configScripts.isEmpty())) {
+            List<String> scripts = new ArrayList<String>();
+            if (line.hasOption("configscript")) {
+                scripts.add(line.getOptionValue("configscript"));
+            }
+            if (configScripts != null) {
+                scripts.addAll(StringGroovyMethods.tokenize((CharSequence) configScripts, ','));
+            }
+            processConfigScripts(scripts, main.conf);
+        }
+
+        main.args = args;
+        return main.run();
+    }
+
+    public static void processConfigScripts(List<String> scripts, CompilerConfiguration conf) throws IOException {
+        if (scripts.isEmpty()) return;
+        Binding binding = new Binding();
+        binding.setVariable("configuration", conf);
+        CompilerConfiguration configuratorConfig = new CompilerConfiguration();
+        ImportCustomizer customizer = new ImportCustomizer();
+        customizer.addStaticStars("org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder");
+        configuratorConfig.addCompilationCustomizers(customizer);
+        GroovyShell shell = new GroovyShell(binding, configuratorConfig);
+        for (String script : scripts) {
+            shell.evaluate(new File(script));
+        }
+    }
+
+
+    /**
+     * Run the script.
+     */
+    private boolean run() {
+        try {
+            if (processSockets) {
+                processSockets();
+            } else if (processFiles) {
+                processFiles();
+            } else {
+                processOnce();
+            }
+            return true;
+        } catch (CompilationFailedException e) {
+            System.err.println(e);
+            return false;
+        } catch (Throwable e) {
+            if (e instanceof InvokerInvocationException) {
+                InvokerInvocationException iie = (InvokerInvocationException) e;
+                e = iie.getCause();
+            }
+            System.err.println("Caught: " + e);
+            if (!debug) {
+                StackTraceUtils.deepSanitize(e);
+            }
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * Process Sockets.
+     */
+    private void processSockets() throws CompilationFailedException, IOException, URISyntaxException {
+        GroovyShell groovy = new GroovyShell(conf);
+        new GroovySocketServer(groovy, getScriptSource(isScriptFile, script), autoOutput, port);
+    }
+
+    /**
+     * Get the text of the Groovy script at the given location.
+     * If the location is a file path and it does not exist as given,
+     * then {@link GroovyMain#huntForTheScriptFile(String)} is called to try
+     * with some Groovy extensions appended.
+     *
+     * This method is not used to process scripts and is retained for backward
+     * compatibility.  If you want to modify how GroovyMain processes scripts
+     * then use {@link GroovyMain#getScriptSource(boolean, String)}.
+     *
+     * @param uriOrFilename
+     * @return the text content at the location
+     * @throws IOException
+     * @deprecated
+     */
+    @Deprecated
+    public String getText(String uriOrFilename) throws IOException {
+        if (URI_PATTERN.matcher(uriOrFilename).matches()) {
+            try {
+                return ResourceGroovyMethods.getText(new URL(uriOrFilename));
+            } catch (Exception e) {
+                throw new GroovyRuntimeException("Unable to get script from URL: ", e);
+            }
+        }
+        return ResourceGroovyMethods.getText(huntForTheScriptFile(uriOrFilename));
+    }
+
+    /**
+     * Get a new GroovyCodeSource for a script which may be given as a location
+     * (isScript is true) or as text (isScript is false).
+     *
+     * @param isScriptFile indicates whether the script parameter is a location or content
+     * @param script the location or context of the script
+     * @return a new GroovyCodeSource for the given script
+     * @throws IOException
+     * @throws URISyntaxException
+     * @since 2.3.0
+     */
+    protected GroovyCodeSource getScriptSource(boolean isScriptFile, String script) throws IOException, URISyntaxException {
+        //check the script is currently valid before starting a server against the script
+        if (isScriptFile) {
+            // search for the file and if it exists don't try to use URIs ...
+            File scriptFile = huntForTheScriptFile(script);
+            if (!scriptFile.exists() && URI_PATTERN.matcher(script).matches()) {
+                return new GroovyCodeSource(new URI(script));
+            }
+            return new GroovyCodeSource( scriptFile );
+        }
+        return new GroovyCodeSource(script, "script_from_command_line", GroovyShell.DEFAULT_CODE_BASE);
+    }
+
+    // RFC2396
+    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+    // match URIs but not Windows filenames, e.g.: http://cnn.com but not C:\xxx\file.ext
+    private static final Pattern URI_PATTERN = Pattern.compile("\\p{Alpha}[-+.\\p{Alnum}]*:[^\\\\]*");
+
+    /**
+     * Search for the script file, doesn't bother if it is named precisely.
+     *
+     * Tries in this order:
+     * - actual supplied name
+     * - name.groovy
+     * - name.gvy
+     * - name.gy
+     * - name.gsh
+     *
+     * @since 2.3.0
+     */
+    public static File searchForGroovyScriptFile(String input) {
+        String scriptFileName = input.trim();
+        File scriptFile = new File(scriptFileName);
+        // TODO: Shouldn't these extensions be kept elsewhere?  What about CompilerConfiguration?
+        // This method probably shouldn't be in GroovyMain either.
+        String[] standardExtensions = {".groovy",".gvy",".gy",".gsh"};
+        int i = 0;
+        while (i < standardExtensions.length && !scriptFile.exists()) {
+            scriptFile = new File(scriptFileName + standardExtensions[i]);
+            i++;
+        }
+        // if we still haven't found the file, point back to the originally specified filename
+        if (!scriptFile.exists()) {
+            scriptFile = new File(scriptFileName);
+        }
+        return scriptFile;
+    }
+
+    /**
+     * Hunt for the script file by calling searchForGroovyScriptFile(String).
+     *
+     * @see GroovyMain#searchForGroovyScriptFile(String)
+     */
+    public File huntForTheScriptFile(String input) {
+        return GroovyMain.searchForGroovyScriptFile(input);
+    }
+
+    // GROOVY-6771
+    private static void setupContextClassLoader(GroovyShell shell) {
+        final Thread current = Thread.currentThread();
+        class DoSetContext implements PrivilegedAction {
+            ClassLoader classLoader;
+
+            public DoSetContext(ClassLoader loader) {
+                classLoader = loader;
+            }
+
+            public Object run() {
+                current.setContextClassLoader(classLoader);
+                return null;
+            }
+        }
+
+        AccessController.doPrivileged(new DoSetContext(shell.getClassLoader()));
+    }
+
+    /**
+     * Process the input files.
+     */
+    private void processFiles() throws CompilationFailedException, IOException, URISyntaxException {
+        GroovyShell groovy = new GroovyShell(conf);
+        setupContextClassLoader(groovy);
+
+        Script s = groovy.parse(getScriptSource(isScriptFile, script));
+
+        if (args.isEmpty()) {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+            PrintWriter writer = new PrintWriter(System.out);
+
+            try {
+                processReader(s, reader, writer);
+            } finally {
+                reader.close();
+                writer.close();
+            }
+
+        } else {
+            Iterator i = args.iterator();
+            while (i.hasNext()) {
+                String filename = (String) i.next();
+                //TODO: These are the arguments for -p and -i.  Why are we searching using Groovy script extensions?
+                // Where is this documented?
+                File file = huntForTheScriptFile(filename);
+                processFile(s, file);
+            }
+        }
+    }
+
+    /**
+     * Process a single input file.
+     *
+     * @param s    the script to execute.
+     * @param file the input file.
+     */
+    private void processFile(Script s, File file) throws IOException {
+        if (!file.exists())
+            throw new FileNotFoundException(file.getName());
+
+        if (!editFiles) {
+            BufferedReader reader = new BufferedReader(new FileReader(file));
+            try {
+                PrintWriter writer = new PrintWriter(System.out);
+                processReader(s, reader, writer);
+                writer.flush();
+            } finally {
+                reader.close();
+            }
+        } else {
+            File backup;
+            if (backupExtension == null) {
+                backup = File.createTempFile("groovy_", ".tmp");
+                backup.deleteOnExit();
+            } else {
+                backup = new File(file.getPath() + backupExtension);
+            }
+            backup.delete();
+            if (!file.renameTo(backup))
+                throw new IOException("unable to rename " + file + " to " + backup);
+
+            BufferedReader reader = new BufferedReader(new FileReader(backup));
+            try {
+                PrintWriter writer = new PrintWriter(new FileWriter(file));
+                try {
+                    processReader(s, reader, writer);
+                } finally {
+                    writer.close();
+                }
+            } finally {
+                reader.close();
+            }
+        }
+    }
+
+    /**
+     * Process a script against a single input file.
+     *
+     * @param s      script to execute.
+     * @param reader input file.
+     * @param pw     output sink.
+     */
+    private void processReader(Script s, BufferedReader reader, PrintWriter pw) throws IOException {
+        String line;
+        String lineCountName = "count";
+        s.setProperty(lineCountName, BigInteger.ZERO);
+        String autoSplitName = "split";
+        s.setProperty("out", pw);
+
+        try {
+            InvokerHelper.invokeMethod(s, "begin", null);
+        } catch (MissingMethodException mme) {
+            // ignore the missing method exception
+            // as it means no begin() method is present
+        }
+
+        while ((line = reader.readLine()) != null) {
+            s.setProperty("line", line);
+            s.setProperty(lineCountName, ((BigInteger)s.getProperty(lineCountName)).add(BigInteger.ONE));
+
+            if(autoSplit) {
+                s.setProperty(autoSplitName, line.split(splitPattern));
+            }
+
+            Object o = s.run();
+
+            if (autoOutput && o != null) {
+                pw.println(o);
+            }
+        }
+
+        try {
+            InvokerHelper.invokeMethod(s, "end", null);
+        } catch (MissingMethodException mme) {
+            // ignore the missing method exception
+            // as it means no end() method is present
+        }
+    }
+
+    /**
+     * Process the standard, single script with args.
+     */
+    private void processOnce() throws CompilationFailedException, IOException, URISyntaxException {
+        GroovyShell groovy = new GroovyShell(conf);
+        setupContextClassLoader(groovy);
+        groovy.run(getScriptSource(isScriptFile, script), args);
+    }
+}


[32/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
new file mode 100644
index 0000000..b6de965
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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 groovy.lang;
+
+public class SpreadListEvaluatingException extends GroovyRuntimeException {
+    public SpreadListEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/SpreadMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMap.java b/src/main/groovy/groovy/lang/SpreadMap.java
new file mode 100644
index 0000000..7ba9e4f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMap.java
@@ -0,0 +1,120 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper to turn a list with an even number of elements into a Map.
+ * 
+ * @author Pilho Kim
+ * @author Tim Tiemens
+ */
+public class SpreadMap extends HashMap {
+    private int hashCode;
+
+    public SpreadMap(Object[] values) {
+        int i = 0;
+        while (i < values.length) {
+            super.put(values[i++], values[i++]);
+        }
+    }
+
+    public SpreadMap(Map map) {
+        super(map);
+    }
+
+    /**
+     * @since 1.8.0
+     * @param list the list to make spreadable
+     */
+    public SpreadMap(List list) {
+        this(list.toArray());
+    }
+
+    public Object put(Object key, Object value) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so ("
+                                   + key + ": " + value + ") cannot be added.");
+    }
+
+    public Object remove(Object key) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the key ("
+                                   + key + ") cannot be deleted.");
+    }
+
+    public void putAll(Map t) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the map ("
+                                   + t + ") cannot be put in this spreadMap.");
+    }
+
+    public boolean equals(Object that) {
+        if (that instanceof SpreadMap) {
+            return equals((SpreadMap) that);
+        }
+        return false;
+    }
+
+    public boolean equals(SpreadMap that) {
+        if (that == null) return false;        
+
+        if (size() == that.size()) {
+            for (Object key : keySet()) {
+                if (!DefaultTypeTransformation.compareEqual(get(key), that.get(key))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        if (hashCode == 0) {
+            for (Object key : keySet()) {
+                int hash = (key != null) ? key.hashCode() : 0xbabe;
+                hashCode ^= hash;
+            }
+        }
+        return hashCode;
+    }
+
+    /**
+     * @return the string expression of <code>this</code>
+     */
+    public String toString() {
+        if (isEmpty()) {
+            return "*:[:]";
+        }
+        StringBuilder sb = new StringBuilder("*:[");
+        Iterator iter = keySet().iterator();
+        while (iter.hasNext()) {
+            Object key = iter.next();
+            sb.append(key).append(":").append(get(key));
+            if (iter.hasNext())
+                sb.append(", ");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
new file mode 100644
index 0000000..408a223
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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 groovy.lang;
+
+public class SpreadMapEvaluatingException extends GroovyRuntimeException {
+    public SpreadMapEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/StringWriterIOException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/StringWriterIOException.java b/src/main/groovy/groovy/lang/StringWriterIOException.java
new file mode 100644
index 0000000..0372399
--- /dev/null
+++ b/src/main/groovy/groovy/lang/StringWriterIOException.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 groovy.lang;
+
+import java.io.IOException;
+
+/**
+ * An IO exception occurred trying to append to a StringWriter which should never happen.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class StringWriterIOException extends RuntimeException {
+
+    public StringWriterIOException(IOException e) {
+        super(e);
+    }
+
+    public IOException getIOException() {
+        return (IOException) getCause();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/TracingInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TracingInterceptor.java b/src/main/groovy/groovy/lang/TracingInterceptor.java
new file mode 100644
index 0000000..f67de11
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TracingInterceptor.java
@@ -0,0 +1,120 @@
+/*
+ *  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 groovy.lang;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/*
+ * This {@link Interceptor} traces method calls on the proxied object to a log. 
+ * By default, the log is simply <pre>System.out</pre>; however, that can be 
+ * changed with the <pre>setWriter(Writer)</pre> method.
+ * <p>
+ * A message will be written to output before a method is invoked and after a method
+ * is invoked. If methods are nested, and invoke one another, then indentation 
+ * of two spaces is written.
+ * <p>
+ * Here is an example usage on the ArrayList object: <br>
+ * <pre class="groovyTestCase">
+ * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
+ * proxy.interceptor = new TracingInterceptor()
+ * proxy.use {
+ *     def list = [1, 2, 3]
+ *     assert 3 == list.size()
+ *     assert list.contains(1)
+ * }
+ * </pre>
+ * Running this code produces this output: 
+ * <pre>
+ * before java.util.ArrayList.size()
+ * after  java.util.ArrayList.size()
+ * before java.util.ArrayList.contains(java.lang.Integer)
+ * after  java.util.ArrayList.contains(java.lang.Integer)
+ * </pre>
+ */
+public class TracingInterceptor implements Interceptor {
+
+    protected Writer writer = new PrintWriter(System.out);
+    private int indent = 0;
+
+    /**
+    * Returns the writer associated with this interceptor. 
+    */ 
+    public Writer getWriter() {
+        return writer;
+    }
+
+    /**
+    * Changes the writer associated with this interceptor. 
+    */ 
+    public void setWriter(Writer writer) {
+        this.writer = writer;
+    }
+
+    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
+        write(object, methodName, arguments, "before");
+        indent++ ;
+        return null;
+    }
+
+    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
+        indent--;
+        write(object, methodName, arguments, "after ");
+        return result;
+    }
+
+    public boolean doInvoke() {
+        return true;
+    }
+    private String indent(){
+        StringBuilder result = new StringBuilder();
+        for (int i=0; i<indent;i++){
+            result.append("  ");
+        }
+        return result.toString();
+    }
+
+    protected void write(Object object, String methodName, Object[] arguments, final String origin) {
+        try {
+            writer.write(indent());
+            writer.write(origin);
+            writer.write(" ");
+            Class theClass = object instanceof Class ? (Class) object: object.getClass();
+            writeInfo(theClass, methodName, arguments);
+            writer.write("\n");
+            writer.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    protected void writeInfo(final Class aClass, String methodName, Object[] arguments) throws IOException {
+        writer.write(aClass.getName());
+        writer.write(".");
+        writer.write(methodName);
+        writer.write("(");
+        for (int i = 0; i < arguments.length; i++) {
+            if (i > 0) writer.write(", ");
+            Object argument = arguments[i];
+            writer.write(argument.getClass().getName());
+        }
+        writer.write(")");
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/TrampolineClosure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TrampolineClosure.java b/src/main/groovy/groovy/lang/TrampolineClosure.java
new file mode 100644
index 0000000..ed68f00
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TrampolineClosure.java
@@ -0,0 +1,111 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * A TrampolineClosure wraps a closure that needs to be executed on a functional trampoline.
+ * Upon calling, a TrampolineClosure will call the original closure waiting for its result.
+ * If the outcome of the call is another instance of a TrampolineClosure, created perhaps as a result to a call to the TrampolineClosure.trampoline()
+ * method, the TrampolineClosure will again be invoked. This repetitive invocation of returned TrampolineClosure instances will continue
+ * until a value other than TrampolineClosure is returned.
+ * That value will become the final result of the trampoline.
+ *
+ * @author Vaclav Pech
+ */
+final class TrampolineClosure<V> extends Closure<V> {
+
+    private final Closure<V> original;
+
+    TrampolineClosure(final Closure<V> original) {
+        super(original.getOwner(), original.getDelegate());
+        this.original = original;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public int getMaximumNumberOfParameters() {
+        return original.maximumNumberOfParameters;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public Class[] getParameterTypes() {
+        return original.parameterTypes;
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call() {
+        return loop(original.call());
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object arguments) {
+        return loop(original.call(arguments));
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object... args) {
+        return loop(original.call(args));
+    }
+
+    private V loop(final Object lastResult) {
+        Object result = lastResult;
+
+        for (;;) {
+            if (result instanceof TrampolineClosure) {
+                result = ((TrampolineClosure)result).original.call();
+            } else return (V) result;
+        }
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * @param args Parameters to curry to the underlying closure.
+     * @return An instance of TrampolineClosure wrapping the original closure after currying.
+     */
+    @Override
+   public Closure<V> trampoline(final Object... args) {
+        return new TrampolineClosure<V>(original.curry(args));
+    }
+
+    /**
+     * Returns itself, since it is a good enough trampolined variant of the current closure.
+     * @return An instance of TrampolineClosure wrapping the original closure.
+     */
+    @Override
+    public Closure<V> trampoline() {
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple.java b/src/main/groovy/groovy/lang/Tuple.java
new file mode 100644
index 0000000..036d13e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple.java
@@ -0,0 +1,85 @@
+/*
+ *  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 groovy.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a list of Objects.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Tuple<E> extends AbstractList<E> implements Serializable {
+    private static final long serialVersionUID = -6707770506387821031L;
+    private final E[] contents;
+
+    public Tuple(E... contents) {
+        if (contents == null) throw new NullPointerException();
+        this.contents = contents;
+    }
+
+    @Override
+    public E get(int index) {
+        return contents[index];
+    }
+
+    @Override
+    public int size() {
+        return contents.length;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        int size = toIndex - fromIndex;
+        E[] newContent = (E[]) new Object[size];
+        System.arraycopy(contents, fromIndex, newContent, 0, size);
+        return new Tuple<>(newContent);
+    }
+
+    public Tuple<E> subTuple(int fromIndex, int toIndex) {
+        return (Tuple<E>) subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof Tuple)) return false;
+
+        Tuple that = (Tuple) o;
+        int size = size();
+        if (size != that.size()) return false;
+        for (int i = 0; i < size; i++) {
+            if (!DefaultTypeTransformation.compareEqual(get(i), that.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(contents);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple1.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple1.java b/src/main/groovy/groovy/lang/Tuple1.java
new file mode 100644
index 0000000..9b8d6bd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple1.java
@@ -0,0 +1,54 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 1 typed Object.
+ *
+ * @since 2.5.0
+ */
+public class Tuple1<T1> extends Tuple {
+    private static final long serialVersionUID = -4647790147461409603L;
+    private final T1 first;
+
+    public Tuple1(T1 first) {
+        super(first);
+
+        this.first = first;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 1;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple2.java b/src/main/groovy/groovy/lang/Tuple2.java
new file mode 100644
index 0000000..b096aee
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple2.java
@@ -0,0 +1,60 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 2 typed Objects.
+ */
+public class Tuple2<T1, T2> extends Tuple {
+    private static final long serialVersionUID = 9006144674906325597L;
+    private final T1 first;
+    private final T2 second;
+
+    public Tuple2(T1 first, T2 second) {
+        super(first, second);
+
+        this.first = first;
+        this.second = second;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 2;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple3.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple3.java b/src/main/groovy/groovy/lang/Tuple3.java
new file mode 100644
index 0000000..b5fe7d9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple3.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 groovy.lang;
+
+/**
+ * Represents a list of 3 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple3<T1, T2, T3> extends Tuple {
+    private static final long serialVersionUID = 8469774237154310687L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+
+    public Tuple3(T1 first, T2 second, T3 third) {
+        super(first, second, third);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 3;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple4.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple4.java b/src/main/groovy/groovy/lang/Tuple4.java
new file mode 100644
index 0000000..04f414e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple4.java
@@ -0,0 +1,79 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 4 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple4<T1, T2, T3, T4> extends Tuple {
+    private static final long serialVersionUID = -7788878731471377207L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+
+    public Tuple4(T1 first, T2 second, T3 third, T4 fourth) {
+        super(first, second, third, fourth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 4;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple5.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple5.java b/src/main/groovy/groovy/lang/Tuple5.java
new file mode 100644
index 0000000..ee9c802
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple5.java
@@ -0,0 +1,87 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 5 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple5<T1, T2, T3, T4, T5> extends Tuple {
+    private static final long serialVersionUID = 6722094358774027115L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+
+    public Tuple5(T1 first, T2 second, T3 third, T4 fourth, T5 fifth) {
+        super(first, second, third, fourth, fifth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 5;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple6.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple6.java b/src/main/groovy/groovy/lang/Tuple6.java
new file mode 100644
index 0000000..76d12ca
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple6.java
@@ -0,0 +1,95 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 6 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple6<T1, T2, T3, T4, T5, T6> extends Tuple {
+    private static final long serialVersionUID = -7848588473093102288L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+
+    public Tuple6(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth) {
+        super(first, second, third, fourth, fifth, sixth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 6;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple7.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple7.java b/src/main/groovy/groovy/lang/Tuple7.java
new file mode 100644
index 0000000..05046e7
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple7.java
@@ -0,0 +1,103 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 7 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple7<T1, T2, T3, T4, T5, T6, T7> extends Tuple {
+    private static final long serialVersionUID = 4226144828786865766L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+
+    public Tuple7(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh) {
+        super(first, second, third, fourth, fifth, sixth, seventh);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 7;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple8.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple8.java b/src/main/groovy/groovy/lang/Tuple8.java
new file mode 100644
index 0000000..1f38ca9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple8.java
@@ -0,0 +1,111 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 8 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple8<T1, T2, T3, T4, T5, T6, T7, T8> extends Tuple {
+    private static final long serialVersionUID = -8895822084644138566L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+
+    public Tuple8(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 8;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Tuple9.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple9.java b/src/main/groovy/groovy/lang/Tuple9.java
new file mode 100644
index 0000000..3189c10
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple9.java
@@ -0,0 +1,120 @@
+/*
+ *  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 groovy.lang;
+
+/**
+ * Represents a list of 9 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends Tuple {
+    private static final long serialVersionUID = -5181196675351911769L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+    private final T9 ninth;
+
+    public Tuple9(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth, T9 ninth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+        this.ninth = ninth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            case 8:
+                return ninth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 9;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+
+    public T9 getNinth() {
+        return ninth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Writable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Writable.java b/src/main/groovy/groovy/lang/Writable.java
new file mode 100644
index 0000000..ec135cd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Writable.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 groovy.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+/**
+ * Represents an object which is capable of writing itself to a text stream
+ * in a more efficient format than just creating a toString() representation
+ * of itself. This mechanism is particularly useful for templates and such like.
+ * <p>
+ * It is worth noting that writable implementations often override their
+ * toString() implementation as well to allow rendering the same result 
+ * directly to a String; however this is not required.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public interface Writable {
+
+    /**
+     * Writes this object to the given writer.
+     * <p>
+     * This is used to defer content creation until the point when it is
+     * streamed to the output destination.  Oftentimes, content will be defined 
+     * but not necessarily created (as is may be the case with a Closure 
+     * definition.)  In that case, the output is then 'deferred' to the point 
+     * when it is serialized to the writer. This class may be used whenever an 
+     * object should be responsible for creating its own textual representation, 
+     * but creating the entire output as a single String would be inefficient
+     * (such as outputting a multi-gigabyte XML document.)
+     * 
+     * @param out the Writer to which this Writable should output its data.
+     * @return the Writer that was passed
+     * @throws IOException if an error occurred while outputting data to the writer
+     */
+    Writer writeTo(Writer out) throws IOException;
+        
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/package.html b/src/main/groovy/groovy/lang/package.html
new file mode 100644
index 0000000..1ea84fc
--- /dev/null
+++ b/src/main/groovy/groovy/lang/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 groovy.lang.*</title>
+  </head>
+  <body>
+    <p>Core Groovy language classes for implementing data structures, closures, metadata and so forth.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java b/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
new file mode 100644
index 0000000..e723e0b
--- /dev/null
+++ b/src/main/groovy/groovy/security/GroovyCodeSourcePermission.java
@@ -0,0 +1,40 @@
+/*
+ *  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 groovy.security;
+
+import java.security.BasicPermission;
+
+/**
+ * Permission required to explicitly specify a codebase for a groovy script whose
+ * codebase cannot be determined.  Typically this permission is only
+ * required by clients that want to associate a code source with a script which
+ * is a String or an InputStream.
+ *
+ * @author Steve Goetze
+ */
+public final class GroovyCodeSourcePermission extends BasicPermission {
+
+    public GroovyCodeSourcePermission(String name) {
+        super(name);
+    }
+
+    public GroovyCodeSourcePermission(String name, String actions) {
+        super(name, actions);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/security/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/security/package.html b/src/main/groovy/groovy/security/package.html
new file mode 100644
index 0000000..cb094ff
--- /dev/null
+++ b/src/main/groovy/groovy/security/package.html
@@ -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.
+
+-->
+<html>
+  <head>
+    <title>package groovy.security.*</title>
+  </head>
+  <body>
+    <p>
+      Security-related classes
+    </p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/BaseDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/BaseDuration.java b/src/main/groovy/groovy/time/BaseDuration.java
new file mode 100644
index 0000000..e2cc023
--- /dev/null
+++ b/src/main/groovy/groovy/time/BaseDuration.java
@@ -0,0 +1,141 @@
+/*
+ *  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 groovy.time;
+
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Base class for date and time durations.
+ *
+ * @author John Wilson tug@wilson.co.uk
+ * @see Duration
+ */
+public abstract class BaseDuration implements Comparable<BaseDuration> {
+    protected final int years;
+    protected final int months;
+    protected final int days;
+    protected final int hours;
+    protected final int minutes;
+    protected final int seconds;
+    protected final int millis;
+
+    protected BaseDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        this.years = years;
+        this.months = months;
+        this.days = days;
+        this.hours = hours;
+        this.minutes = minutes;
+        this.seconds = seconds;
+        this.millis = millis;
+    }
+
+    protected BaseDuration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        this(0, 0, days, hours, minutes, seconds, millis);
+    }
+
+    public int getYears() {
+        return this.years;
+    }
+
+    public int getMonths() {
+        return this.months;
+    }
+
+    public int getDays() {
+        return this.days;
+    }
+
+    public int getHours() {
+        return this.hours;
+    }
+
+    public int getMinutes() {
+        return this.minutes;
+    }
+
+    public int getSeconds() {
+        return this.seconds;
+    }
+
+    public int getMillis() {
+        return this.millis;
+    }
+
+    public Date plus(final Date date) {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, this.years);
+        cal.add(Calendar.MONTH, this.months);
+        cal.add(Calendar.DAY_OF_YEAR, this.days);
+        cal.add(Calendar.HOUR_OF_DAY, this.hours);
+        cal.add(Calendar.MINUTE, this.minutes);
+        cal.add(Calendar.SECOND, this.seconds);
+        cal.add(Calendar.MILLISECOND, this.millis);
+
+        return cal.getTime();
+    }
+
+    public String toString() {
+        List buffer = new ArrayList();
+
+        if (this.years != 0) buffer.add(this.years + " years");
+        if (this.months != 0) buffer.add(this.months + " months");
+        if (this.days != 0) buffer.add(this.days + " days");
+        if (this.hours != 0) buffer.add(this.hours + " hours");
+        if (this.minutes != 0) buffer.add(this.minutes + " minutes");
+
+        if (this.seconds != 0 || this.millis != 0) {
+            int norm_millis = this.millis % 1000;
+            int norm_seconds = this.seconds + DefaultGroovyMethods.intdiv(this.millis - norm_millis, 1000).intValue();
+            CharSequence millisToPad = "" + Math.abs(norm_millis);
+            buffer.add((norm_seconds == 0 ? (norm_millis < 0 ? "-0" : "0") : norm_seconds) + "." + StringGroovyMethods.padLeft(millisToPad, 3, "0") + " seconds");
+        }
+
+        if (!buffer.isEmpty()) {
+            return DefaultGroovyMethods.join(buffer.iterator(), ", ");
+        } else {
+            return "0";
+        }
+    }
+
+    public abstract long toMilliseconds();
+
+    public abstract Date getAgo();
+
+    public abstract From getFrom();
+
+    public int compareTo(BaseDuration otherDuration) {
+        return Long.signum(toMilliseconds() - otherDuration.toMilliseconds());
+    }
+
+    public abstract static class From {
+        public abstract Date getNow();
+
+        public Date getToday() {
+            return getNow();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/DatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/DatumDependentDuration.java b/src/main/groovy/groovy/time/DatumDependentDuration.java
new file mode 100644
index 0000000..c73d9aa
--- /dev/null
+++ b/src/main/groovy/groovy/time/DatumDependentDuration.java
@@ -0,0 +1,141 @@
+/*
+ *  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 groovy.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * DatumDependentDuration represents durations whose length in milliseconds 
+ * cannot be determined without knowing the datum point.
+ * <p>
+ * I don't know how many days in a year unless I know if it's a leap year or not.
+ * <p>
+ * I don't know how many days in a month unless I know the name of the month 
+ * (and if it's a leap year if the month is February)
+ *
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class DatumDependentDuration extends BaseDuration {
+    public DatumDependentDuration(final int years, final int months, final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        super(years, months, days, hours, minutes, seconds, millis);
+    }
+
+    public int getMonths() {
+        return this.months;
+    }
+
+    public int getYears() {
+        return this.years;
+    }
+
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
+                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                this.getMillis() + rhs.getMillis());
+    }
+
+    public DatumDependentDuration plus(final TimeDatumDependentDuration rhs) {
+        return rhs.plus(this);
+    }
+
+    public DatumDependentDuration plus(final Duration rhs) {
+        return new DatumDependentDuration(this.getYears(), this.getMonths(),
+                this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                this.getMillis() + rhs.getMillis());
+
+    }
+
+    public DatumDependentDuration plus(final TimeDuration rhs) {
+        return rhs.plus(this);
+
+    }
+
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
+                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                this.getMillis() - rhs.getMillis());
+
+    }
+
+    public DatumDependentDuration minus(final Duration rhs) {
+        return new DatumDependentDuration(this.getYears(), this.getMonths(),
+                this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                this.getMillis() - rhs.getMillis());
+
+    }
+
+    /**
+     * @see groovy.time.BaseDuration#toMilliseconds()
+     *
+     * Change the duration into milliseconds, relative to 'now.'  Therefore
+     * things like timezone and time of year will affect how this conversion 
+     * occurs.
+     */
+    public long toMilliseconds() {
+        final Date now = new Date();
+        return TimeCategory.minus(plus(now), now).toMilliseconds();
+    }
+
+    public Date getAgo() {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.add(Calendar.YEAR, -this.getYears());
+        cal.add(Calendar.MONTH, -this.getMonths());
+        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
+        cal.add(Calendar.MINUTE, -this.getMinutes());
+        cal.add(Calendar.SECOND, -this.getSeconds());
+        cal.add(Calendar.MILLISECOND, -this.getMillis());
+
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+
+        return new Date(cal.getTimeInMillis());
+    }
+
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+                final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.YEAR, DatumDependentDuration.this.getYears());
+                cal.add(Calendar.MONTH, DatumDependentDuration.this.getMonths());
+                cal.add(Calendar.DAY_OF_YEAR, DatumDependentDuration.this.getDays());
+                cal.add(Calendar.HOUR_OF_DAY, DatumDependentDuration.this.getHours());
+                cal.add(Calendar.MINUTE, DatumDependentDuration.this.getMinutes());
+                cal.add(Calendar.SECOND, DatumDependentDuration.this.getSeconds());
+                cal.add(Calendar.MILLISECOND, DatumDependentDuration.this.getMillis());
+
+                cal.set(Calendar.HOUR_OF_DAY, 0);
+                cal.set(Calendar.MINUTE, 0);
+                cal.set(Calendar.SECOND, 0);
+                cal.set(Calendar.MILLISECOND, 0);
+
+                return new Date(cal.getTimeInMillis());
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/Duration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/Duration.java b/src/main/groovy/groovy/time/Duration.java
new file mode 100644
index 0000000..e187957
--- /dev/null
+++ b/src/main/groovy/groovy/time/Duration.java
@@ -0,0 +1,119 @@
+/*
+ *  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 groovy.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Duration represents time periods which have values independent of the context.
+ * So, whilst we can't say how long a month is without knowing the year and the name of the month,
+ * we know how long a day is independent of the date.
+ * <p>
+ * This is not 100% true for days.
+ * Days can actually be 23, 24 or 25 hours long (due to daylight saving adjustments.)
+ * <p>
+ * If you ask Duration to convert itself to milliseconds then it will work on the basis of 24 hours
+ * in a day. If you add or subtract it from a date it will take daylight saving into account.
+ *
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class Duration extends BaseDuration {
+    public Duration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        super(days, hours, minutes, seconds, millis);
+    }
+    
+    public Duration plus(final Duration rhs) {
+        return new Duration(this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                            this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                            this.getMillis() + rhs.getMillis());
+    }
+
+    public Duration plus(final TimeDuration rhs) {
+        return rhs.plus(this);
+    }
+    
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return rhs.plus(this);
+    }
+    
+    public Duration minus(final Duration rhs) {
+        return new Duration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                            this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                            this.getMillis() - rhs.getMillis());
+    }
+    
+    public TimeDuration minus(final TimeDuration rhs) {
+        return new TimeDuration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                this.getMillis() - rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new DatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
+                                          this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                          this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                          this.getMillis() - rhs.getMillis());
+    }
+    
+    public TimeDatumDependentDuration minus(final TimeDatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public long toMilliseconds() {
+        return ((((((long)(this.getDays() * 24 ) + this.getHours()) * 60 + this.getMinutes()) * 60) + this.getSeconds()) * 1000) + this.getMillis();
+    }
+    
+    public Date getAgo() {
+    final Calendar cal = Calendar.getInstance();
+
+        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
+        cal.add(Calendar.MINUTE, -this.getMinutes());
+        cal.add(Calendar.SECOND, -this.getSeconds());
+        cal.add(Calendar.MILLISECOND, -this.getMillis());
+
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        
+        return new Date(cal.getTimeInMillis());
+    }
+     
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+            final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.DAY_OF_YEAR, Duration.this.getDays());
+
+                cal.set(Calendar.HOUR_OF_DAY, 0);
+                cal.set(Calendar.MINUTE, 0);
+                cal.set(Calendar.SECOND, 0);
+                cal.set(Calendar.MILLISECOND, 0);
+
+                return new Date(cal.getTimeInMillis());
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/TimeCategory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/TimeCategory.java b/src/main/groovy/groovy/time/TimeCategory.java
new file mode 100644
index 0000000..dbc08cd
--- /dev/null
+++ b/src/main/groovy/groovy/time/TimeCategory.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 groovy.time;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Apply a number of methods to allow convenient Date/Time manipulation,such as:
+ * <pre class="groovyTestCase">
+ * use (groovy.time.TimeCategory) {
+ *     // application on numbers:
+ *     println 1.minute.from.now
+ *     println 10.hours.ago
+ *
+ *     // application on dates
+ *     def someDate = new Date()
+ *     println someDate - 3.months
+ * }
+ * </pre>
+ *
+ * @see BaseDuration
+ */
+public class TimeCategory {
+    /*
+     * Methods to allow Date Duration arithmetic
+     */
+
+    public static Date plus(final Date date, final BaseDuration duration) {
+        return duration.plus(date);
+    }
+
+    public static Date minus(final Date date, final BaseDuration duration) {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, -duration.getYears());
+        cal.add(Calendar.MONTH, -duration.getMonths());
+        cal.add(Calendar.DAY_OF_YEAR, -duration.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -duration.getHours());
+        cal.add(Calendar.MINUTE, -duration.getMinutes());
+        cal.add(Calendar.SECOND, -duration.getSeconds());
+        cal.add(Calendar.MILLISECOND, -duration.getMillis());
+
+        return cal.getTime();
+    }
+
+    /**
+     * Retrieves the default TimeZone for a date by using the default Locale
+     * settings. Recommended that you use {@code TimeZone.getDefault()} instead.
+     *
+     * @param self a Date
+     * @return the TimeZone
+     */
+    @Deprecated
+    public static TimeZone getTimeZone(Date self) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(self);
+        return calendar.getTimeZone();
+    }
+
+    /**
+     * Get the DST offset (if any) for the default locale and the given date.
+     *
+     * @param self a Date
+     * @return the DST offset as a Duration.
+     */
+    public static Duration getDaylightSavingsOffset(Date self) {
+        TimeZone timeZone = getTimeZone(self);
+        int millis = (timeZone.useDaylightTime() && timeZone.inDaylightTime(self))
+                ? timeZone.getDSTSavings() : 0;
+        return new TimeDuration(0, 0, 0, millis);
+    }
+
+    public static Duration getDaylightSavingsOffset(BaseDuration self) {
+        return getDaylightSavingsOffset(new Date(self.toMilliseconds() + 1));
+    }
+
+    /**
+     * Return a Duration representing the DST difference (if any) between two
+     * dates.  i.e. if one date is before the DST changeover, and the other
+     * date is after, the resulting duration will represent the DST offset.
+     *
+     * @param self  a Date
+     * @param other another Date
+     * @return a Duration
+     */
+    public static Duration getRelativeDaylightSavingsOffset(Date self, Date other) {
+        Duration d1 = getDaylightSavingsOffset(self);
+        Duration d2 = getDaylightSavingsOffset(other);
+        return new TimeDuration(0, 0, 0, (int) (d2.toMilliseconds() - d1.toMilliseconds()));
+    }
+
+    /**
+     * Subtract one date from the other.
+     *
+     * @param lhs a Date
+     * @param rhs another Date
+     * @return a Duration
+     */
+    public static TimeDuration minus(final Date lhs, final Date rhs) {
+        long milliseconds = lhs.getTime() - rhs.getTime();
+        long days = milliseconds / (24 * 60 * 60 * 1000);
+        milliseconds -= days * 24 * 60 * 60 * 1000;
+        int hours = (int) (milliseconds / (60 * 60 * 1000));
+        milliseconds -= hours * 60 * 60 * 1000;
+        int minutes = (int) (milliseconds / (60 * 1000));
+        milliseconds -= minutes * 60 * 1000;
+        int seconds = (int) (milliseconds / 1000);
+        milliseconds -= seconds * 1000;
+
+        return new TimeDuration((int) days, hours, minutes, seconds, (int) milliseconds);
+    }
+
+    /*
+    * Methods on Integer to implement 1.month, 4.years etc.
+    */
+
+    public static DatumDependentDuration getMonths(final Integer self) {
+        return new DatumDependentDuration(0, self, 0, 0, 0, 0, 0);
+    }
+
+    public static DatumDependentDuration getMonth(final Integer self) {
+        return getMonths(self);
+    }
+
+    public static DatumDependentDuration getYears(final Integer self) {
+        return new DatumDependentDuration(self, 0, 0, 0, 0, 0, 0);
+    }
+
+    public static DatumDependentDuration getYear(final Integer self) {
+        return getYears(self);
+    }
+
+    /*
+    * Methods on Integer to implement 1.week, 4.days etc.
+    */
+
+    public static Duration getWeeks(final Integer self) {
+        return new Duration(self * 7, 0, 0, 0, 0);
+    }
+
+    public static Duration getWeek(final Integer self) {
+        return getWeeks(self);
+    }
+
+    public static Duration getDays(final Integer self) {
+        return new Duration(self, 0, 0, 0, 0);
+    }
+
+    public static Duration getDay(final Integer self) {
+        return getDays(self);
+    }
+
+    public static TimeDuration getHours(final Integer self) {
+        return new TimeDuration(0, self, 0, 0, 0);
+    }
+
+    public static TimeDuration getHour(final Integer self) {
+        return getHours(self);
+    }
+
+    public static TimeDuration getMinutes(final Integer self) {
+        return new TimeDuration(0, 0, self, 0, 0);
+    }
+
+    public static TimeDuration getMinute(final Integer self) {
+        return getMinutes(self);
+    }
+
+    public static TimeDuration getSeconds(final Integer self) {
+        return new TimeDuration(0, 0, 0, self, 0);
+    }
+
+    public static TimeDuration getSecond(final Integer self) {
+        return getSeconds(self);
+    }
+
+    public static TimeDuration getMilliseconds(final Integer self) {
+        return new TimeDuration(0, 0, 0, 0, self);
+    }
+
+    public static TimeDuration getMillisecond(final Integer self) {
+        return getMilliseconds(self);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/TimeDatumDependentDuration.java b/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
new file mode 100644
index 0000000..eead45a
--- /dev/null
+++ b/src/main/groovy/groovy/time/TimeDatumDependentDuration.java
@@ -0,0 +1,81 @@
+/*
+ *  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 groovy.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * TimeDatumDuration represents a time period which results from an
+ * arithmetic operation between a TimeDuration object and a DatumDuration object
+ * 
+ * @author John Wilson tug@wilson.co.uk
+ */
+public class TimeDatumDependentDuration extends DatumDependentDuration {
+    public TimeDatumDependentDuration(int years, int months, int days, int hours, int minutes, int seconds, int millis) {
+        super(years, months, days, hours, minutes, seconds, millis);
+    }
+    
+    public DatumDependentDuration plus(final Duration rhs) {
+        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
+                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                              this.getMillis() + rhs.getMillis());
+    }
+    
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(this.getYears() + rhs.getYears(), this.getMonths() + rhs.getMonths(),
+                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                              this.getMillis() + rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final Duration rhs) {
+        return new TimeDatumDependentDuration(this.getYears(), this.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(this.getYears() - rhs.getYears(), this.getMonths() - rhs.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+            final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.YEAR, TimeDatumDependentDuration.this.getYears());
+                cal.add(Calendar.MONTH, TimeDatumDependentDuration.this.getMonths());
+                cal.add(Calendar.DAY_OF_YEAR, TimeDatumDependentDuration.this.getDays());
+                cal.add(Calendar.HOUR_OF_DAY, TimeDatumDependentDuration.this.getHours());
+                cal.add(Calendar.MINUTE, TimeDatumDependentDuration.this.getMinutes());
+                cal.add(Calendar.SECOND, TimeDatumDependentDuration.this.getSeconds());
+                cal.add(Calendar.MILLISECOND, TimeDatumDependentDuration.this.getMillis());
+                
+                return cal.getTime();
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/TimeDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/TimeDuration.java b/src/main/groovy/groovy/time/TimeDuration.java
new file mode 100644
index 0000000..767b8e6
--- /dev/null
+++ b/src/main/groovy/groovy/time/TimeDuration.java
@@ -0,0 +1,102 @@
+/*
+ *  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 groovy.time;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * TimeDuration represents time periods expressed in units of hours, minutes,
+ * seconds and milliseconds.
+ * <p>
+ * Whilst we can't say how long a month is without knowing the year and the name of the month,
+ * we know how long a second is independent of the date.
+ * <p>
+ * This is not 100% true for minutes.
+ * Minutes can be 59, 60 or 61 seconds long (due to leap seconds.)
+ * <p>
+ * If you ask Duration to convert itself to milliseconds then it will work on the basis of 60 seconds in a minute.
+ * If you add or subtract it from a date it will take leap seconds into account.
+ *
+ * @author John Wilson tug@wilson.co.uk
+ */
+
+public class TimeDuration extends Duration {
+    public TimeDuration(final int hours, final int minutes, final int seconds, final int millis) {
+        super(0, hours, minutes, seconds, millis);
+     }
+    
+    public TimeDuration(final int days, final int hours, final int minutes, final int seconds, final int millis) {
+        super(days, hours, minutes, seconds, millis);
+     }
+    
+    public Duration plus(final Duration rhs) {
+        return new TimeDuration(this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                this.getMillis() + rhs.getMillis());
+    }
+    
+    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(rhs.getYears(), rhs.getMonths(),
+                                              this.getDays() + rhs.getDays(), this.getHours() + rhs.getHours(),
+                                              this.getMinutes() + rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
+                                              this.getMillis() + rhs.getMillis());
+    }
+    
+    public Duration minus(final Duration rhs) {
+        return new TimeDuration(this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                this.getMillis() - rhs.getMillis());
+    }
+    
+    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
+        return new TimeDatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
+                                              this.getDays() - rhs.getDays(), this.getHours() - rhs.getHours(),
+                                              this.getMinutes() - rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
+                                              this.getMillis() - rhs.getMillis());
+    }
+    
+    public Date getAgo() {
+        final Calendar cal = Calendar.getInstance();
+
+        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
+        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
+        cal.add(Calendar.MINUTE, -this.getMinutes());
+        cal.add(Calendar.SECOND, -this.getSeconds());
+        cal.add(Calendar.MILLISECOND, -this.getMillis());
+        
+        return cal.getTime();
+    }        
+
+    public From getFrom() {
+        return new From() {
+            public Date getNow() {
+                final Calendar cal = Calendar.getInstance();
+
+                cal.add(Calendar.DAY_OF_YEAR, TimeDuration.this.getDays());
+                cal.add(Calendar.HOUR_OF_DAY, TimeDuration.this.getHours());
+                cal.add(Calendar.MINUTE, TimeDuration.this.getMinutes());
+                cal.add(Calendar.SECOND, TimeDuration.this.getSeconds());
+                cal.add(Calendar.MILLISECOND, TimeDuration.this.getMillis());
+                
+                return cal.getTime();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/time/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/time/package.html b/src/main/groovy/groovy/time/package.html
new file mode 100644
index 0000000..94fb458
--- /dev/null
+++ b/src/main/groovy/groovy/time/package.html
@@ -0,0 +1,47 @@
+<!--
+
+     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 groovy.time.*</title>
+  </head>
+  <body>
+    <p>
+      Classes for easily manipulating Dates and times.  While 
+      <code>java.util.Date</code> has GDK methods for adding or subtracting days,
+      this is not so useful for different durations of time.  
+      {@link groovy.time.TimeCategory TimeCategory} creates a simple internal DSL
+      for manipulating dates and times in a clean and precise fashion.  
+    </p>
+    <h3>Examples</h3>
+    <pre>
+  use ( TimeCategory ) {
+  	// application on numbers:
+  	println 1.minute.from.now
+  	println 10.days.ago
+  
+  	// application on dates
+  	def someDate = new Date()
+  	println someDate - 3.months 
+  }</pre>
+     
+    @see groovy.time.TimeCategory
+  </body>
+</html>


[18/47] groovy git commit: Move source files to proper packages

Posted by su...@apache.org.
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GrabExclude.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GrabExclude.java b/src/main/groovy/lang/GrabExclude.java
deleted file mode 100644
index 327cb43..0000000
--- a/src/main/groovy/lang/GrabExclude.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to exclude an indirectly referenced artifact (a transitive dependency) from the classpath.
- * <p>
- * Examples:<br>
- * {@code @GrabExclude(group='mysql', module='mysql-connector-java') // group/module form}<br>
- * {@code @GrabExclude('mysql:mysql-connector-java') // compact form}<br>
- * <p>
- * Further information about customising grape behavior can be found on the Grape documentation page:
- * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target({
-        ElementType.CONSTRUCTOR,
-        ElementType.FIELD,
-        ElementType.LOCAL_VARIABLE,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.TYPE})
-public @interface GrabExclude {
-
-    /**
-     * The organisation or group, e.g.: "org.apache.ant"; required unless the compact form is used.
-     */
-    String group() default "";
-
-    /**
-     * The module or artifact, e.g.: "ant-junit"; required unless the compact form is used.
-     */
-    String module() default "";
-
-    /**
-     * Allows you to specify the group (organisation) and the module (artifact) in one of two compact convenience formats,
-     * e.g.: <code>@GrabExclude('org.apache.ant:ant-junit')</code> or <code>@GrabExclude('org.apache.ant#ant-junit')</code>
-     */
-    String value() default "";
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GrabResolver.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GrabResolver.java b/src/main/groovy/lang/GrabResolver.java
deleted file mode 100644
index 6512cb3..0000000
--- a/src/main/groovy/lang/GrabResolver.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to add a repository for resolving Grape dependencies.
- * <p>
- * For example:
- * <pre>
- * {@code @GrabResolver}(name='restlet.org', root='http://maven.restlet.org')
- * {@code @Grab}(group='org.restlet', module='org.restlet', version='1.1.6')
- * class MyRestlet extends org.restlet.Restlet {
- *   // ...
- * }
- * </pre>
- * By default, the Grapes subsystem uses an Ivy chained resolver. Each resolver
- * added using {@code @GrabResolver} is appended to the chain. By default, the grape
- * subsystem is shared globally, so added resolvers will become available for any subsequent
- * grab calls. Dependency resolution follows Ivy's artifact resolution which tries
- * to resolve artifacts in the order specified in the chain of resolvers.
- * <p>
- * Further information about customising grape behavior can be found on the Grape documentation page:
- * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>.
- *
- * @author Merlyn Albery-Speyer
- */
-@Retention(RetentionPolicy.SOURCE)
-@Target({
-        ElementType.CONSTRUCTOR,
-        ElementType.FIELD,
-        ElementType.LOCAL_VARIABLE,
-        ElementType.METHOD,
-        ElementType.PARAMETER,
-        ElementType.TYPE})
-public @interface GrabResolver {
-    /**
-     * Allows a shorthand form which sets the name and root to this value.
-     * Must not be used if name() or root() is non-empty.
-     */
-    String value() default "";
-
-    /**
-     * A meaningful name for a repo containing the grape/artifact.
-     * A non-empty value is required unless value() is used.
-     */
-    String name() default "";
-
-    /**
-     * The URL for a repo containing the grape/artifact.
-     * A non-empty value is required unless value() is used.
-     */
-    String root() default "";
-
-    /**
-     * Defaults to Maven2 compatibility. Set false for Ivy only compatibility.
-     */
-    boolean m2Compatible() default true;
-
-    /**
-     * By default, when a {@code @GrabResolver} annotation is used, a {@code Grape.addResolver()} call is added
-     * to the static initializers of the class the annotatable node appears in.
-     * If you wish to disable this, add {@code initClass=false} to the annotation.
-     */
-    boolean initClass() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/Grapes.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/Grapes.java b/src/main/groovy/lang/Grapes.java
deleted file mode 100644
index 1255529..0000000
--- a/src/main/groovy/lang/Grapes.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Sometimes we will need more than one grab per class, but we can only add
- * one annotation type per annotatable node.  This class allows for multiple
- * grabs to be added.
- * <p>
- * For example:
- * <p>
- * <pre>
- * {@code @Grapes([@Grab(module='m1'), @Grab(module='m2')])}
- * class AnnotatedClass { ... }
- * </pre>
- * <p>
- * You can override an implicit transitive dependency by providing an explicit one.
- * E.g. htmlunit 2.6 normally uses xerces 2.9.1 but you can get 2.9.0 as follows:
- * <pre>
- * {@code @Grapes}([
- *     {@code @Grab}('net.sourceforge.htmlunit:htmlunit:2.6'),
- *     {@code @Grab}('xerces#xercesImpl;2.9.0')
- * ])
- * </pre>
- * Obviously, only do this if you understand the consequences.
- * <p>
- * You can also remove transitive dependencies altogether (provided you
- * know you don't need them) using {@code @GrabExclude}.
- * For example, here is how we would not grab the {@code logkit} and
- * {@code avalon-framework} transitive dependencies for Apache POI:
- * <pre>
- * {@code @Grapes}([
- *   {@code @Grab}("org.apache.poi#poi;3.5-beta6"),
- *   {@code @GrabExclude}("logkit:logkit"),
- *   {@code @GrabExclude}("avalon-framework#avalon-framework")
- * ])
- * import org.apache.poi.hssf.util.CellReference
- * assert new CellReference(0, 0, false, false).formatAsString() == 'A1'
- * assert new CellReference(1, 3).formatAsString() == '$D$2'
- * </pre>
- * It is also sometimes also useful to use {@code @GrabConfig} to further adjust how dependencies
- * are grabbed. See {@code @GrabConfig} for further information.
- */
-public @interface Grapes {
-    Grab[] value();
-
-    /**
-     * This will be pushed into the child grab annotations if the value is not
-     * set in the child annotation already.
-     * <p>
-     * This results in an effective change in the default value, which each &#064;Grab
-     * can still override
-     */
-    boolean initClass() default true;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyCallable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyCallable.java b/src/main/groovy/lang/GroovyCallable.java
deleted file mode 100644
index 1966289..0000000
--- a/src/main/groovy/lang/GroovyCallable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.util.concurrent.Callable;
-
-/**
- * A special "marker" style interface allowing Groovy classes to implement both
- * Runnable and Callable yet give preference to Runnable (for backwards compatibility)
- * for APIs having both Runnable and Callable methods. You should generally NOT use this
- * method in your own code.
- *
- * @see java.util.concurrent.Callable
- * @since 1.8.0
- */
-public interface GroovyCallable<V> extends Callable<V> { }

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyClassLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyClassLoader.java b/src/main/groovy/lang/GroovyClassLoader.java
deleted file mode 100644
index 8581879..0000000
--- a/src/main/groovy/lang/GroovyClassLoader.java
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- *  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.
- */
-/*
- * @todo multi threaded compiling of the same class but with different roots
- * for compilation... T1 compiles A, which uses B, T2 compiles B... mark A and B
- * as parsed and then synchronize compilation. Problems: How to synchronize?
- * How to get error messages?
- *
- */
-package groovy.lang;
-
-import groovy.util.CharsetToolkit;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.InnerClassNode;
-import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.classgen.GeneratorContext;
-import org.codehaus.groovy.classgen.Verifier;
-import org.codehaus.groovy.control.BytecodeProcessor;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.runtime.IOGroovyMethods;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
-import org.codehaus.groovy.runtime.memoize.EvictableCache;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Opcodes;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLConnection;
-import java.net.URLDecoder;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Map;
-
-/**
- * A ClassLoader which can load Groovy classes. The loaded classes are cached,
- * classes from other classloaders should not be cached. To be able to load a
- * script that was asked for earlier but was created later it is essential not
- * to keep anything like a "class not found" information for that class name.
- * This includes possible parent loaders. Classes that are not cached are always
- * reloaded.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Guillaume Laforge
- * @author Steve Goetze
- * @author Bing Ran
- * @author <a href="mailto:scottstirling@rcn.com">Scott Stirling</a>
- * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
- */
-public class GroovyClassLoader extends URLClassLoader {
-    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
-    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-
-    /**
-     * this cache contains the loaded classes or PARSING, if the class is currently parsed
-     */
-    protected final EvictableCache<String, Class> classCache = new ConcurrentCommonCache<String, Class>();
-
-    /**
-     * This cache contains mappings of file name to class. It is used
-     * to bypass compilation.
-     */
-    protected final ConcurrentCommonCache<String, Class> sourceCache = new ConcurrentCommonCache<String, Class>();
-
-    private final CompilerConfiguration config;
-    private String sourceEncoding;
-    private Boolean recompile;
-    // use 1000000 as offset to avoid conflicts with names form the GroovyShell
-    private static int scriptNameCounter = 1000000;
-
-    private GroovyResourceLoader resourceLoader = new GroovyResourceLoader() {
-        public URL loadGroovySource(final String filename) throws MalformedURLException {
-            return AccessController.doPrivileged(new PrivilegedAction<URL>() {
-                public URL run() {
-                    for (String extension : config.getScriptExtensions()) {
-                        try {
-                            URL ret = getSourceFile(filename, extension);
-                            if (ret != null)
-                                return ret;
-                        } catch (Throwable t) { //
-                        }
-                    }
-                    return null;
-                }
-            });
-        }
-    };
-
-    /**
-     * creates a GroovyClassLoader using the current Thread's context
-     * Class loader as parent.
-     */
-    public GroovyClassLoader() {
-        this(Thread.currentThread().getContextClassLoader());
-    }
-
-    /**
-     * creates a GroovyClassLoader using the given ClassLoader as parent
-     */
-    public GroovyClassLoader(ClassLoader loader) {
-        this(loader, null);
-    }
-
-    /**
-     * creates a GroovyClassLoader using the given GroovyClassLoader as parent.
-     * This loader will get the parent's CompilerConfiguration
-     */
-    public GroovyClassLoader(GroovyClassLoader parent) {
-        this(parent, parent.config, false);
-    }
-
-    /**
-     * creates a GroovyClassLoader.
-     *
-     * @param parent                    the parent class loader
-     * @param config                    the compiler configuration
-     * @param useConfigurationClasspath determines if the configurations classpath should be added
-     */
-    public GroovyClassLoader(ClassLoader parent, CompilerConfiguration config, boolean useConfigurationClasspath) {
-        super(EMPTY_URL_ARRAY, parent);
-        if (config == null) config = CompilerConfiguration.DEFAULT;
-        this.config = config;
-        if (useConfigurationClasspath) {
-            for (String path : config.getClasspath()) {
-                this.addClasspath(path);
-            }
-        }
-
-        initSourceEncoding(config);
-    }
-
-    private void initSourceEncoding(CompilerConfiguration config) {
-        sourceEncoding = config.getSourceEncoding();
-        if (null ==  sourceEncoding) {
-            // Keep the same default source encoding with the one used by #parseClass(InputStream, String)
-            // TODO should we use org.codehaus.groovy.control.CompilerConfiguration.DEFAULT_SOURCE_ENCODING instead?
-            sourceEncoding = CharsetToolkit.getDefaultSystemCharset().name();
-        }
-    }
-
-    /**
-     * creates a GroovyClassLoader using the given ClassLoader as parent.
-     */
-    public GroovyClassLoader(ClassLoader loader, CompilerConfiguration config) {
-        this(loader, config, true);
-    }
-
-    public void setResourceLoader(GroovyResourceLoader resourceLoader) {
-        if (resourceLoader == null) {
-            throw new IllegalArgumentException("Resource loader must not be null!");
-        }
-        this.resourceLoader = resourceLoader;
-    }
-
-    public GroovyResourceLoader getResourceLoader() {
-        return resourceLoader;
-    }
-
-    /**
-     * Loads the given class node returning the implementation Class.
-     * <p>
-     * WARNING: this compilation is not synchronized
-     *
-     * @param classNode
-     * @return a class
-     */
-    public Class defineClass(ClassNode classNode, String file, String newCodeBase) {
-        CodeSource codeSource = null;
-        try {
-            codeSource = new CodeSource(new URL("file", "", newCodeBase), (java.security.cert.Certificate[]) null);
-        } catch (MalformedURLException e) {
-            //swallow
-        }
-
-        CompilationUnit unit = createCompilationUnit(config, codeSource);
-        ClassCollector collector = createCollector(unit, classNode.getModule().getContext());
-        try {
-            unit.addClassNode(classNode);
-            unit.setClassgenCallback(collector);
-            unit.compile(Phases.CLASS_GENERATION);
-            definePackageInternal(collector.generatedClass.getName());
-            return collector.generatedClass;
-        } catch (CompilationFailedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Parses the given file into a Java class capable of being run
-     *
-     * @param file the file name to parse
-     * @return the main class defined in the given script
-     */
-    public Class parseClass(File file) throws CompilationFailedException, IOException {
-        return parseClass(new GroovyCodeSource(file, config.getSourceEncoding()));
-    }
-
-    /**
-     * Parses the given text into a Java class capable of being run
-     *
-     * @param text     the text of the script/class to parse
-     * @param fileName the file name to use as the name of the class
-     * @return the main class defined in the given script
-     */
-    public Class parseClass(final String text, final String fileName) throws CompilationFailedException {
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                return new GroovyCodeSource(text, fileName, "/groovy/script");
-            }
-        });
-        gcs.setCachable(false);
-        return parseClass(gcs);
-    }
-
-    /**
-     * Parses the given text into a Java class capable of being run
-     *
-     * @param text the text of the script/class to parse
-     * @return the main class defined in the given script
-     */
-    public Class parseClass(String text) throws CompilationFailedException {
-        return parseClass(text, "script" + System.currentTimeMillis() +
-                Math.abs(text.hashCode()) + ".groovy");
-    }
-
-    public synchronized String generateScriptName() {
-        scriptNameCounter++;
-        return "script" + scriptNameCounter + ".groovy";
-    }
-
-    public Class parseClass(final Reader reader, final String fileName) throws CompilationFailedException {
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                try {
-                    String scriptText = IOGroovyMethods.getText(reader);
-                    return new GroovyCodeSource(scriptText, fileName, "/groovy/script");
-                } catch (IOException e) {
-                    throw new RuntimeException("Impossible to read the content of the reader for file named: " + fileName, e);
-                }
-            }
-        });
-        return parseClass(gcs);
-    }
-    
-    /**
-     * @deprecated Prefer using methods taking a Reader rather than an InputStream to avoid wrong encoding issues.
-     * Use {@link #parseClass(Reader, String) parseClass} instead
-     */
-    @Deprecated
-    public Class parseClass(final InputStream in, final String fileName) throws CompilationFailedException {
-        // For generic input streams, provide a catch-all codebase of GroovyScript
-        // Security for these classes can be administered via policy grants with
-        // a codebase of file:groovy.script
-        GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
-            public GroovyCodeSource run() {
-                try {
-                    String scriptText = config.getSourceEncoding() != null ?
-                            IOGroovyMethods.getText(in, config.getSourceEncoding()) :
-                            IOGroovyMethods.getText(in);
-                    return new GroovyCodeSource(scriptText, fileName, "/groovy/script");
-                } catch (IOException e) {
-                    throw new RuntimeException("Impossible to read the content of the input stream for file named: " + fileName, e);
-                }
-            }
-        });
-        return parseClass(gcs);
-    }
-
-    public Class parseClass(GroovyCodeSource codeSource) throws CompilationFailedException {
-        return parseClass(codeSource, codeSource.isCachable());
-    }
-
-    /**
-     * Parses the given code source into a Java class. If there is a class file
-     * for the given code source, then no parsing is done, instead the cached class is returned.
-     *
-     * @param shouldCacheSource if true then the generated class will be stored in the source cache
-     * @return the main class defined in the given script
-     */
-    public Class parseClass(final GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException {
-        return sourceCache.getAndPut(
-                codeSource.getName(),
-                new EvictableCache.ValueProvider<String, Class>() {
-                    @Override
-                    public Class provide(String key) {
-                        return doParseClass(codeSource);
-                    }
-                },
-                shouldCacheSource
-        );
-    }
-
-    private Class doParseClass(GroovyCodeSource codeSource) {
-        validate(codeSource);
-        Class answer;  // Was neither already loaded nor compiling, so compile and add to cache.
-        CompilationUnit unit = createCompilationUnit(config, codeSource.getCodeSource());
-        if (recompile!=null && recompile || recompile==null && config.getRecompileGroovySource()) {
-            unit.addFirstPhaseOperation(TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber());
-        }
-        SourceUnit su = null;
-        File file = codeSource.getFile();
-        if (file != null) {
-            su = unit.addSource(file);
-        } else {
-            URL url = codeSource.getURL();
-            if (url != null) {
-                su = unit.addSource(url);
-            } else {
-                su = unit.addSource(codeSource.getName(), codeSource.getScriptText());
-            }
-        }
-
-        ClassCollector collector = createCollector(unit, su);
-        unit.setClassgenCallback(collector);
-        int goalPhase = Phases.CLASS_GENERATION;
-        if (config != null && config.getTargetDirectory() != null) goalPhase = Phases.OUTPUT;
-        unit.compile(goalPhase);
-
-        answer = collector.generatedClass;
-        String mainClass = su.getAST().getMainClassName();
-        for (Object o : collector.getLoadedClasses()) {
-            Class clazz = (Class) o;
-            String clazzName = clazz.getName();
-            definePackageInternal(clazzName);
-            setClassCacheEntry(clazz);
-            if (clazzName.equals(mainClass)) answer = clazz;
-        }
-        return answer;
-    }
-
-    private static void validate(GroovyCodeSource codeSource) {
-        if (codeSource.getFile() == null) {
-            if (codeSource.getScriptText() == null) {
-                throw new IllegalArgumentException("Script text to compile cannot be null!");
-            }
-        }
-    }
-
-    private void definePackageInternal(String className) {
-        int i = className.lastIndexOf('.');
-        if (i != -1) {
-            String pkgName = className.substring(0, i);
-            java.lang.Package pkg = getPackage(pkgName);
-            if (pkg == null) {
-                definePackage(pkgName, null, null, null, null, null, null, null);
-            }
-        }
-    }
-
-    /**
-     * gets the currently used classpath.
-     *
-     * @return a String[] containing the file information of the urls
-     * @see #getURLs()
-     */
-    protected String[] getClassPath() {
-        //workaround for Groovy-835
-        URL[] urls = getURLs();
-        String[] ret = new String[urls.length];
-        for (int i = 0; i < ret.length; i++) {
-            ret[i] = urls[i].getFile();
-        }
-        return ret;
-    }
-
-    protected PermissionCollection getPermissions(CodeSource codeSource) {
-        PermissionCollection perms;
-        try {
-            try {
-                perms = super.getPermissions(codeSource);
-            } catch (SecurityException e) {
-                // We lied about our CodeSource and that makes URLClassLoader unhappy.
-                perms = new Permissions();
-            }
-
-            ProtectionDomain myDomain = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
-                public ProtectionDomain run() {
-                    return getClass().getProtectionDomain();
-                }
-            });
-            PermissionCollection myPerms = myDomain.getPermissions();
-            if (myPerms != null) {
-                for (Enumeration<Permission> elements = myPerms.elements(); elements.hasMoreElements();) {
-                    perms.add(elements.nextElement());
-                }
-            }
-        } catch (Throwable e) {
-            // We lied about our CodeSource and that makes URLClassLoader unhappy.
-            perms = new Permissions();
-        }
-        perms.setReadOnly();
-        return perms;
-    }
-
-    public static class InnerLoader extends GroovyClassLoader {
-        private final GroovyClassLoader delegate;
-        private final long timeStamp;
-
-        public InnerLoader(GroovyClassLoader delegate) {
-            super(delegate);
-            this.delegate = delegate;
-            timeStamp = System.currentTimeMillis();
-        }
-
-        public void addClasspath(String path) {
-            delegate.addClasspath(path);
-        }
-
-        public void clearCache() {
-            delegate.clearCache();
-        }
-
-        public URL findResource(String name) {
-            return delegate.findResource(name);
-        }
-
-        public Enumeration findResources(String name) throws IOException {
-            return delegate.findResources(name);
-        }
-
-        public Class[] getLoadedClasses() {
-            return delegate.getLoadedClasses();
-        }
-
-        public URL getResource(String name) {
-            return delegate.getResource(name);
-        }
-
-        public InputStream getResourceAsStream(String name) {
-            return delegate.getResourceAsStream(name);
-        }
-
-        public GroovyResourceLoader getResourceLoader() {
-            return delegate.getResourceLoader();
-        }
-
-        public URL[] getURLs() {
-            return delegate.getURLs();
-        }
-
-        public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve) throws ClassNotFoundException, CompilationFailedException {
-            Class c = findLoadedClass(name);
-            if (c != null) return c;
-            return delegate.loadClass(name, lookupScriptFiles, preferClassOverScript, resolve);
-        }
-
-        public Class parseClass(GroovyCodeSource codeSource, boolean shouldCache) throws CompilationFailedException {
-            return delegate.parseClass(codeSource, shouldCache);
-        }
-
-        public void setResourceLoader(GroovyResourceLoader resourceLoader) {
-            delegate.setResourceLoader(resourceLoader);
-        }
-
-        public void addURL(URL url) {
-            delegate.addURL(url);
-        }
-
-        public long getTimeStamp() {
-            return timeStamp;
-        }
-    }
-
-    /**
-     * creates a new CompilationUnit. If you want to add additional
-     * phase operations to the CompilationUnit (for example to inject
-     * additional methods, variables, fields), then you should overwrite
-     * this method.
-     *
-     * @param config the compiler configuration, usually the same as for this class loader
-     * @param source the source containing the initial file to compile, more files may follow during compilation
-     * @return the CompilationUnit
-     */
-    protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
-        return new CompilationUnit(config, source, this);
-    }
-
-    /**
-     * creates a ClassCollector for a new compilation.
-     *
-     * @param unit the compilationUnit
-     * @param su   the SourceUnit
-     * @return the ClassCollector
-     */
-    protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
-        InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
-            public InnerLoader run() {
-                return new InnerLoader(GroovyClassLoader.this);
-            }
-        });
-        return new ClassCollector(loader, unit, su);
-    }
-
-    public static class ClassCollector extends CompilationUnit.ClassgenCallback {
-        private Class generatedClass;
-        private final GroovyClassLoader cl;
-        private final SourceUnit su;
-        private final CompilationUnit unit;
-        private final Collection<Class> loadedClasses;
-
-        protected ClassCollector(InnerLoader cl, CompilationUnit unit, SourceUnit su) {
-            this.cl = cl;
-            this.unit = unit;
-            this.loadedClasses = new ArrayList<Class>();
-            this.su = su;
-        }
-
-        public GroovyClassLoader getDefiningClassLoader() {
-            return cl;
-        }
-
-        protected Class createClass(byte[] code, ClassNode classNode) {
-            BytecodeProcessor bytecodePostprocessor = unit.getConfiguration().getBytecodePostprocessor();
-            byte[] fcode = code;
-            if (bytecodePostprocessor!=null) {
-                fcode = bytecodePostprocessor.processBytecode(classNode.getName(), fcode);
-            }
-            GroovyClassLoader cl = getDefiningClassLoader();
-            Class theClass = cl.defineClass(classNode.getName(), fcode, 0, fcode.length, unit.getAST().getCodeSource());
-            this.loadedClasses.add(theClass);
-
-            if (generatedClass == null) {
-                ModuleNode mn = classNode.getModule();
-                SourceUnit msu = null;
-                if (mn != null) msu = mn.getContext();
-                ClassNode main = null;
-                if (mn != null) main = (ClassNode) mn.getClasses().get(0);
-                if (msu == su && main == classNode) generatedClass = theClass;
-            }
-
-            return theClass;
-        }
-
-        protected Class onClassNode(ClassWriter classWriter, ClassNode classNode) {
-            byte[] code = classWriter.toByteArray();
-            return createClass(code, classNode);
-        }
-
-        public void call(ClassVisitor classWriter, ClassNode classNode) {
-            onClassNode((ClassWriter) classWriter, classNode);
-        }
-
-        public Collection getLoadedClasses() {
-            return this.loadedClasses;
-        }
-    }
-
-    /**
-     * open up the super class define that takes raw bytes
-     */
-    public Class defineClass(String name, byte[] b) {
-        return super.defineClass(name, b, 0, b.length);
-    }
-
-    /**
-     * loads a class from a file or a parent classloader.
-     * This method does call loadClass(String, boolean, boolean, boolean)
-     * with the last parameter set to false.
-     *
-     * @throws CompilationFailedException if compilation was not successful
-     */
-    public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript)
-            throws ClassNotFoundException, CompilationFailedException {
-        return loadClass(name, lookupScriptFiles, preferClassOverScript, false);
-    }
-
-    /**
-     * gets a class from the class cache. This cache contains only classes loaded through
-     * this class loader or an InnerLoader instance. If no class is stored for a
-     * specific name, then the method should return null.
-     *
-     * @param name of the class
-     * @return the class stored for the given name
-     * @see #removeClassCacheEntry(String)
-     * @see #setClassCacheEntry(Class)
-     * @see #clearCache()
-     */
-    protected Class getClassCacheEntry(String name) {
-        return classCache.get(name);
-    }
-
-    /**
-     * sets an entry in the class cache.
-     *
-     * @param cls the class
-     * @see #removeClassCacheEntry(String)
-     * @see #getClassCacheEntry(String)
-     * @see #clearCache()
-     */
-    protected void setClassCacheEntry(Class cls) {
-        classCache.put(cls.getName(), cls);
-    }
-
-    /**
-     * removes a class from the class cache.
-     *
-     * @param name of the class
-     * @see #getClassCacheEntry(String)
-     * @see #setClassCacheEntry(Class)
-     * @see #clearCache()
-     */
-    protected void removeClassCacheEntry(String name) {
-        classCache.remove(name);
-    }
-
-    /**
-     * adds a URL to the classloader.
-     *
-     * @param url the new classpath element
-     */
-    public void addURL(URL url) {
-        super.addURL(url);
-    }
-
-    /**
-     * Indicates if a class is recompilable. Recompilable means, that the classloader
-     * will try to locate a groovy source file for this class and then compile it again,
-     * adding the resulting class as entry to the cache. Giving null as class is like a
-     * recompilation, so the method should always return true here. Only classes that are
-     * implementing GroovyObject are compilable and only if the timestamp in the class
-     * is lower than Long.MAX_VALUE.
-     * <p>
-     * NOTE: First the parent loaders will be asked and only if they don't return a
-     * class the recompilation will happen. Recompilation also only happen if the source
-     * file is newer.
-     *
-     * @param cls the class to be tested. If null the method should return true
-     * @return true if the class should be compiled again
-     * @see #isSourceNewer(URL, Class)
-     */
-    protected boolean isRecompilable(Class cls) {
-        if (cls == null) return true;
-        if (cls.getClassLoader() == this) return false;
-        if (recompile == null && !config.getRecompileGroovySource()) return false;
-        if (recompile != null && !recompile) return false;
-        if (!GroovyObject.class.isAssignableFrom(cls)) return false;
-        long timestamp = getTimeStamp(cls);
-        if (timestamp == Long.MAX_VALUE) return false;
-        return true;
-    }
-
-    /**
-     * sets if the recompilation should be enable. There are 3 possible
-     * values for this. Any value different than null overrides the
-     * value from the compiler configuration. true means to recompile if needed
-     * false means to never recompile.
-     *
-     * @param mode the recompilation mode
-     * @see CompilerConfiguration
-     */
-    public void setShouldRecompile(Boolean mode) {
-        recompile = mode;
-    }
-
-    /**
-     * gets the currently set recompilation mode. null means, the
-     * compiler configuration is used. False means no recompilation and
-     * true means that recompilation will be done if needed.
-     *
-     * @return the recompilation mode
-     */
-    public Boolean isShouldRecompile() {
-        return recompile;
-    }
-
-    /**
-     * loads a class from a file or a parent classloader.
-     *
-     * @param name                  of the class to be loaded
-     * @param lookupScriptFiles     if false no lookup at files is done at all
-     * @param preferClassOverScript if true the file lookup is only done if there is no class
-     * @param resolve               see {@link java.lang.ClassLoader#loadClass(java.lang.String, boolean)}
-     * @return the class found or the class created from a file lookup
-     * @throws ClassNotFoundException     if the class could not be found
-     * @throws CompilationFailedException if the source file could not be compiled
-     */
-    public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve)
-            throws ClassNotFoundException, CompilationFailedException {
-        // look into cache
-        Class cls = getClassCacheEntry(name);
-
-        // enable recompilation?
-        boolean recompile = isRecompilable(cls);
-        if (!recompile) return cls;
-
-        // try parent loader
-        ClassNotFoundException last = null;
-        try {
-            Class parentClassLoaderClass = super.loadClass(name, resolve);
-            // always return if the parent loader was successful
-            if (cls != parentClassLoaderClass) return parentClassLoaderClass;
-        } catch (ClassNotFoundException cnfe) {
-            last = cnfe;
-        } catch (NoClassDefFoundError ncdfe) {
-            if (ncdfe.getMessage().indexOf("wrong name") > 0) {
-                last = new ClassNotFoundException(name);
-            } else {
-                throw ncdfe;
-            }
-        }
-
-        // check security manager
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            String className = name.replace('/', '.');
-            int i = className.lastIndexOf('.');
-            // no checks on the sun.reflect classes for reflection speed-up
-            // in particular ConstructorAccessorImpl, MethodAccessorImpl, FieldAccessorImpl and SerializationConstructorAccessorImpl
-            // which are generated at runtime by the JDK
-            if (i != -1 && !className.startsWith("sun.reflect.")) {
-                sm.checkPackageAccess(className.substring(0, i));
-            }
-        }
-
-        // prefer class if no recompilation
-        if (cls != null && preferClassOverScript) return cls;
-
-        // at this point the loading from a parent loader failed
-        // and we want to recompile if needed.
-        if (lookupScriptFiles) {
-            // try groovy file
-            try {
-                // check if recompilation already happened.
-                final Class classCacheEntry = getClassCacheEntry(name);
-                if (classCacheEntry != cls) return classCacheEntry;
-                URL source = resourceLoader.loadGroovySource(name);
-                // if recompilation fails, we want cls==null
-                Class oldClass = cls;
-                cls = null;
-                cls = recompile(source, name, oldClass);
-            } catch (IOException ioe) {
-                last = new ClassNotFoundException("IOException while opening groovy source: " + name, ioe);
-            } finally {
-                if (cls == null) {
-                    removeClassCacheEntry(name);
-                } else {
-                    setClassCacheEntry(cls);
-                }
-            }
-        }
-
-        if (cls == null) {
-            // no class found, there should have been an exception before now
-            if (last == null) throw new AssertionError(true);
-            throw last;
-        }
-        return cls;
-    }
-
-    /**
-     * (Re)Compiles the given source.
-     * This method starts the compilation of a given source, if
-     * the source has changed since the class was created. For
-     * this isSourceNewer is called.
-     *
-     * @param source    the source pointer for the compilation
-     * @param className the name of the class to be generated
-     * @param oldClass  a possible former class
-     * @return the old class if the source wasn't new enough, the new class else
-     * @throws CompilationFailedException if the compilation failed
-     * @throws IOException                if the source is not readable
-     * @see #isSourceNewer(URL, Class)
-     */
-    protected Class recompile(URL source, String className, Class oldClass) throws CompilationFailedException, IOException {
-        if (source != null) {
-            // found a source, compile it if newer
-            if ((oldClass != null && isSourceNewer(source, oldClass)) || (oldClass == null)) {
-                String name = source.toExternalForm();
-
-                sourceCache.remove(name);
-
-                if (isFile(source)) {
-                    try {
-                        return parseClass(new GroovyCodeSource(new File(source.toURI()), sourceEncoding));
-                    } catch (URISyntaxException e) {
-                        // do nothing and fall back to the other version
-                    }
-                }
-                return parseClass(new InputStreamReader(source.openStream(), sourceEncoding), name);
-            }
-        }
-        return oldClass;
-    }
-
-    @Override
-    public Class<?> loadClass(String name) throws ClassNotFoundException {
-        return loadClass(name, false);
-    }
-
-    /**
-     * Implemented here to check package access prior to returning an
-     * already loaded class.
-     *
-     * @throws CompilationFailedException if the compilation failed
-     * @throws ClassNotFoundException     if the class was not found
-     * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
-     */
-    protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException {
-        return loadClass(name, true, true, resolve);
-    }
-
-    /**
-     * gets the time stamp of a given class. For groovy
-     * generated classes this usually means to return the value
-     * of the static field __timeStamp. If the parameter doesn't
-     * have such a field, then Long.MAX_VALUE is returned
-     *
-     * @param cls the class
-     * @return the time stamp
-     */
-    protected long getTimeStamp(Class cls) {
-        return Verifier.getTimestamp(cls);
-    }
-
-    /**
-     * This method will take a file name and try to "decode" any URL encoded characters.  For example
-     * if the file name contains any spaces this method call will take the resulting %20 encoded values
-     * and convert them to spaces.
-     * <p>
-     * This method was added specifically to fix defect:  Groovy-1787.  The defect involved a situation
-     * where two scripts were sitting in a directory with spaces in its name.  The code would fail
-     * when the class loader tried to resolve the file name and would choke on the URLEncoded space values.
-     */
-    private static String decodeFileName(String fileName) {
-        String decodedFile = fileName;
-        try {
-            decodedFile = URLDecoder.decode(fileName, "UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            System.err.println("Encountered an invalid encoding scheme when trying to use URLDecoder.decode() inside of the GroovyClassLoader.decodeFileName() method.  Returning the unencoded URL.");
-            System.err.println("Please note that if you encounter this error and you have spaces in your directory you will run into issues.  Refer to GROOVY-1787 for description of this bug.");
-        }
-
-        return decodedFile;
-    }
-
-    private static boolean isFile(URL ret) {
-        return ret != null && ret.getProtocol().equals("file");
-    }
-
-    private static File getFileForUrl(URL ret, String filename) {
-        String fileWithoutPackage = filename;
-        if (fileWithoutPackage.indexOf('/') != -1) {
-            int index = fileWithoutPackage.lastIndexOf('/');
-            fileWithoutPackage = fileWithoutPackage.substring(index + 1);
-        }
-        return fileReallyExists(ret, fileWithoutPackage);
-    }
-
-    private static File fileReallyExists(URL ret, String fileWithoutPackage) {
-        File path;
-        try {
-            /* fix for GROOVY-5809 */ 
-            path = new File(ret.toURI());
-        } catch(URISyntaxException e) {
-            path = new File(decodeFileName(ret.getFile()));
-        }
-        path = path.getParentFile();
-        if (path.exists() && path.isDirectory()) {
-            File file = new File(path, fileWithoutPackage);
-            if (file.exists()) {
-                // file.exists() might be case insensitive. Let's do
-                // case sensitive match for the filename
-                File parent = file.getParentFile();
-                for (String child : parent.list()) {
-                    if (child.equals(fileWithoutPackage)) return file;
-                }
-            }
-        }
-        //file does not exist!
-        return null;
-    }
-
-    private URL getSourceFile(String name, String extension) {
-        String filename = name.replace('.', '/') + "." + extension;
-        URL ret = getResource(filename);
-        if (isFile(ret) && getFileForUrl(ret, filename) == null) return null;
-        return ret;
-    }
-
-    /**
-     * Decides if the given source is newer than a class.
-     *
-     * @param source the source we may want to compile
-     * @param cls    the former class
-     * @return true if the source is newer, false else
-     * @throws IOException if it is not possible to open an
-     *                     connection for the given source
-     * @see #getTimeStamp(Class)
-     */
-    protected boolean isSourceNewer(URL source, Class cls) throws IOException {
-        long lastMod;
-
-        // Special handling for file:// protocol, as getLastModified() often reports
-        // incorrect results (-1)
-        if (isFile(source)) {
-            // Coerce the file URL to a File
-            // See ClassNodeResolver.isSourceNewer for another method that replaces '|' with ':'.
-            // WTF: Why is this done and where is it documented?
-            String path = source.getPath().replace('/', File.separatorChar).replace('|', ':');
-            File file = new File(path);
-            lastMod = file.lastModified();
-        } else {
-            URLConnection conn = source.openConnection();
-            lastMod = conn.getLastModified();
-            conn.getInputStream().close();
-        }
-        long classTime = getTimeStamp(cls);
-        return classTime + config.getMinimumRecompilationInterval() < lastMod;
-    }
-
-    /**
-     * adds a classpath to this classloader.
-     *
-     * @param path is a jar file or a directory.
-     * @see #addURL(URL)
-     */
-    public void addClasspath(final String path) {
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            public Void run() {
-
-                URI newURI;
-                try {
-                    newURI = new URI(path);
-                    // check if we can create a URL from that URI
-                    newURI.toURL();
-                } catch (URISyntaxException e) {
-                    // the URI has a false format, so lets try it with files ...
-                    newURI=new File(path).toURI();
-                } catch (MalformedURLException e) {
-                    // the URL has a false format, so lets try it with files ...
-                    newURI=new File(path).toURI();
-                } catch (IllegalArgumentException e) {
-                    // the URL is not absolute, so lets try it with files ...
-                    newURI=new File(path).toURI();
-                }
-
-                URL[] urls = getURLs();
-                for (URL url : urls) {
-                    // Do not use URL.equals.  It uses the network to resolve names and compares ip addresses!
-                    // That is a violation of RFC and just plain evil.
-                    // http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html
-                    // http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#equals(java.lang.Object)
-                    // "Since hosts comparison requires name resolution, this operation is a blocking operation.
-                    // Note: The defined behavior for equals is known to be inconsistent with virtual hosting in HTTP."
-                    try {
-                        if (newURI.equals(url.toURI())) return null;
-                    } catch (URISyntaxException e) {
-                        // fail fast! if we got a malformed URI the Classloader has to tell it
-                        throw new RuntimeException( e );
-                    }
-                }
-                try {
-                    addURL(newURI.toURL());
-                } catch (MalformedURLException e) {
-                    // fail fast! if we got a malformed URL the Classloader has to tell it
-                    throw new RuntimeException( e );
-                }
-                return null;
-            }
-        });
-    }
-
-    /**
-     * <p>Returns all Groovy classes loaded by this class loader.
-     *
-     * @return all classes loaded by this class loader
-     */
-    public Class[] getLoadedClasses() {
-        return classCache.values().toArray(EMPTY_CLASS_ARRAY);
-    }
-
-    /**
-     * Removes all classes from the class cache.
-     * <p>
-     * In addition to internal caches this method also clears any
-     * previously set MetaClass information for the given set of
-     * classes being removed.
-     *
-     * @see #getClassCacheEntry(String)
-     * @see #setClassCacheEntry(Class)
-     * @see #removeClassCacheEntry(String)
-     */
-    public void clearCache() {
-        Map<String, Class> clearedClasses = classCache.clear();
-
-        sourceCache.clear();
-
-        for (Map.Entry<String, Class> entry : clearedClasses.entrySet()) {
-            // Another Thread may be using an instance of this class
-            // (for the first time) requiring a ClassInfo lock and
-            // classloading which would require a lock on classCache.
-            // The following locks on ClassInfo and to avoid deadlock
-            // should not be done with a classCache lock.
-            InvokerHelper.removeClass(entry.getValue());
-        }
-    }
-
-    /**
-     * Closes this GroovyClassLoader and clears any caches it maintains.
-     * <p>
-     * No use should be made of this instance after this method is
-     * invoked. Any classes that are already loaded are still accessible.
-     *
-     * @throws IOException
-     * @see URLClassLoader#close()
-     * @see #clearCache()
-     * @since 2.5.0
-     */
-    @Override
-    public void close() throws IOException {
-        super.close();
-        clearCache();
-    }
-
-    private static class TimestampAdder extends CompilationUnit.PrimaryClassNodeOperation implements Opcodes {
-        private static final TimestampAdder INSTANCE = new TimestampAdder();
-
-        private TimestampAdder() {}
-
-        protected void addTimeStamp(ClassNode node) {
-            if (node.getDeclaredField(Verifier.__TIMESTAMP) == null) { // in case if verifier visited the call already
-                FieldNode timeTagField = new FieldNode(
-                        Verifier.__TIMESTAMP,
-                        ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
-                        ClassHelper.long_TYPE,
-                        //"",
-                        node,
-                        new ConstantExpression(System.currentTimeMillis()));
-                // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L");
-                timeTagField.setSynthetic(true);
-                node.addField(timeTagField);
-
-                timeTagField = new FieldNode(
-                        Verifier.__TIMESTAMP__ + String.valueOf(System.currentTimeMillis()),
-                        ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
-                        ClassHelper.long_TYPE,
-                        //"",
-                        node,
-                        new ConstantExpression((long) 0));
-                // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L");
-                timeTagField.setSynthetic(true);
-                node.addField(timeTagField);
-            }
-        }
-
-        @Override
-        public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
-            if ((classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) {
-                // does not apply on interfaces
-                return;
-            }
-            if (!(classNode instanceof InnerClassNode)) {
-                addTimeStamp(classNode);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyCodeSource.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyCodeSource.java b/src/main/groovy/lang/GroovyCodeSource.java
deleted file mode 100644
index a5a2bb1..0000000
--- a/src/main/groovy/lang/GroovyCodeSource.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import groovy.security.GroovyCodeSourcePermission;
-import groovy.util.CharsetToolkit;
-import org.codehaus.groovy.runtime.IOGroovyMethods;
-import org.codehaus.groovy.runtime.ResourceGroovyMethods;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.Reader;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.cert.Certificate;
-import java.util.Objects;
-
-/**
- * CodeSource wrapper class that allows specific security policies to be associated with a class
- * compiled from groovy source.
- *
- * @author Steve Goetze
- * @author Guillaume Laforge
- * @author Merlyn Albery-Speyer
- */
-public class GroovyCodeSource {
-
-    /**
-     * The codeSource to be given the generated class.  This can be used by policy file
-     * grants to administer security.
-     */
-    private CodeSource codeSource;
-
-    /**
-     * The name given to the generated class
-     */
-    private String name;
-
-    /**
-     * The groovy source to be compiled and turned into a class
-     */
-    private String scriptText;
-
-    /**
-     * The certificates used to sign the items from the codesource
-     */
-    Certificate[] certs;
-
-    private boolean cachable;
-
-    private File file;
-
-    private URL url;
-
-    public GroovyCodeSource(String script, String name, String codeBase) {
-        this.name = name;
-        this.scriptText = script;
-        this.codeSource = createCodeSource(codeBase);
-        this.cachable = true;
-    }
-
-    /**
-     * Construct a GroovyCodeSource for an inputStream of groovyCode that has an
-     * unknown provenance -- meaning it didn't come from a File or a URL (e.g.&#160;a String).
-     * The supplied codeBase will be used to construct a File URL that should match up
-     * with a java Policy entry that determines the grants to be associated with the
-     * class that will be built from the InputStream.
-     * <p>
-     * The permission groovy.security.GroovyCodeSourcePermission will be used to determine if the given codeBase
-     * may be specified.  That is, the current Policy set must have a GroovyCodeSourcePermission that implies
-     * the codeBase, or an exception will be thrown.  This is to prevent callers from hijacking
-     * existing codeBase policy entries unless explicitly authorized by the user.
-     */
-    public GroovyCodeSource(Reader reader, String name, String codeBase) {
-        this.name = name;
-        this.codeSource = createCodeSource(codeBase);
-
-        try {
-            this.scriptText = IOGroovyMethods.getText(reader);
-        } catch (IOException e) {
-            throw new RuntimeException("Impossible to read the text content from that reader, for script: " + name + " with codeBase: " + codeBase, e);
-        }
-    }
-
-    public GroovyCodeSource(final File infile, final String encoding) throws IOException {
-        // avoid files which confuse us like ones with .. in path
-        final File file = new File(infile.getCanonicalPath());
-        if (!file.exists()) {
-            throw new FileNotFoundException(file.toString() + " (" + file.getAbsolutePath() + ")");
-        }
-        if (file.isDirectory()) {
-            throw new IllegalArgumentException(file.toString() + " (" + file.getAbsolutePath() + ") is a directory not a Groovy source file.");
-        }
-        try {
-            if (!file.canRead())
-                throw new RuntimeException(file.toString() + " can not be read. Check the read permission of the file \"" + file.toString() + "\" (" + file.getAbsolutePath() + ").");
-        }
-        catch (SecurityException e) {
-            throw e;
-        }
-
-        this.file = file;
-        this.cachable = true;
-        //The calls below require access to user.dir - allow here since getName() and getCodeSource() are
-        //package private and used only by the GroovyClassLoader.
-        try {
-            Object[] info = AccessController.doPrivileged(new PrivilegedExceptionAction<Object[]>() {
-                public Object[] run() throws IOException {
-                    // retrieve the content of the file using the provided encoding
-                    if (encoding != null) {
-                        scriptText = ResourceGroovyMethods.getText(infile, encoding);
-                    } else {
-                        scriptText = ResourceGroovyMethods.getText(infile);
-                    }
-
-                    Object[] info = new Object[2];
-                    URL url = file.toURI().toURL();
-                    info[0] = url.toExternalForm();
-                    //toURI().toURL() will encode, but toURL() will not.
-                    info[1] = new CodeSource(url, (Certificate[]) null);
-                    return info;
-                }
-            });
-
-            this.name = (String) info[0];
-            this.codeSource = (CodeSource) info[1];
-        } catch (PrivilegedActionException pae) {
-            Throwable cause = pae.getCause();
-            if (cause != null && cause instanceof IOException) {
-                throw (IOException) cause;
-            }
-            throw new RuntimeException("Could not construct CodeSource for file: " + file, cause);
-        }
-    }
-
-    /**
-     * @param infile the file to create a GroovyCodeSource for.
-     * @throws IOException if an issue arises opening and reading the file.
-     */
-    public GroovyCodeSource(final File infile) throws IOException {
-        this(infile, CharsetToolkit.getDefaultSystemCharset().name());
-    }
-
-    public GroovyCodeSource(URI uri) throws IOException {
-        this(uri.toURL());
-    }
-
-    public GroovyCodeSource(URL url) {
-        if (url == null) {
-            throw new RuntimeException("Could not construct a GroovyCodeSource from a null URL");
-        }
-        this.url = url;
-        // TODO: GROOVY-6561: GroovyMain got the name this way: script.substring(script.lastIndexOf("/") + 1)
-        this.name = url.toExternalForm();
-        this.codeSource = new CodeSource(url, (java.security.cert.Certificate[]) null);
-        try {
-            String contentEncoding = getContentEncoding(url);
-            if (contentEncoding != null) {
-                this.scriptText = ResourceGroovyMethods.getText(url, contentEncoding);
-            } else {
-                this.scriptText = ResourceGroovyMethods.getText(url); // falls-back on default encoding
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Impossible to read the text content from " + name, e);
-        }
-    }
-
-    /**
-     * TODO(jwagenleitner): remove or fix in future release
-     *
-     * According to the spec getContentEncoding() returns the Content-Encoding
-     * HTTP Header which typically carries values such as 'gzip' or 'deflate'
-     * and is not the character set encoding. For compatibility in 2.4.x,
-     * this behavior is retained but should be removed or fixed (parse
-     * charset from Content-Type header) in future releases.
-     *
-     * see GROOVY-8056 and https://github.com/apache/groovy/pull/500
-     */
-    private static String getContentEncoding(URL url) throws IOException {
-        URLConnection urlConnection = url.openConnection();
-        String encoding = urlConnection.getContentEncoding();
-        try {
-            IOGroovyMethods.closeQuietly(urlConnection.getInputStream());
-        } catch (IOException ignore) {
-            // For compatibility, ignore exceptions from getInputStream() call
-        }
-        return encoding;
-    }
-
-    CodeSource getCodeSource() {
-        return codeSource;
-    }
-
-    public String getScriptText() {
-        return scriptText;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public File getFile() {
-        return file;
-    }
-
-    public URL getURL() {
-        return url;
-    }
-
-    public void setCachable(boolean b) {
-        cachable = b;
-    }
-
-    public boolean isCachable() {
-        return cachable;
-    }
-
-    private static CodeSource createCodeSource(final String codeBase) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
-        }
-        try {
-            return new CodeSource(new URL("file", "", codeBase), (java.security.cert.Certificate[]) null);
-        }
-        catch (MalformedURLException e) {
-            throw new RuntimeException("A CodeSource file URL cannot be constructed from the supplied codeBase: " + codeBase);
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        GroovyCodeSource that = (GroovyCodeSource) o;
-        return Objects.equals(codeSource, that.codeSource);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(codeSource);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyInterceptable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyInterceptable.java b/src/main/groovy/lang/GroovyInterceptable.java
deleted file mode 100644
index 8f83354..0000000
--- a/src/main/groovy/lang/GroovyInterceptable.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * Marker interface used to notify that all methods should be intercepted through the <code>invokeMethod</code> mechanism
- * of <code>GroovyObject</code>.
- *
- * @author Guillaume Laforge
- */
-public interface GroovyInterceptable extends GroovyObject {
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyObject.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyObject.java b/src/main/groovy/lang/GroovyObject.java
deleted file mode 100644
index 5f271e3..0000000
--- a/src/main/groovy/lang/GroovyObject.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  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 groovy.lang;
-
-/**
- * The interface implemented by all Groovy objects.
- * <p>
- * Especially handy for using Groovy objects when in the Java world.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public interface GroovyObject {
-
-    /**
-     * Invokes the given method.
-     *
-     * @param name the name of the method to call
-     * @param args the arguments to use for the method call
-     * @return the result of invoking the method
-     */
-    Object invokeMethod(String name, Object args);
-
-    /**
-     * Retrieves a property value.
-     *
-     * @param propertyName the name of the property of interest
-     * @return the given property
-     */
-    Object getProperty(String propertyName);
-
-    /**
-     * Sets the given property to the new value.
-     *
-     * @param propertyName the name of the property of interest
-     * @param newValue     the new value for the property
-     */
-    void setProperty(String propertyName, Object newValue);
-
-    /**
-     * Returns the metaclass for a given class.
-     *
-     * @return the metaClass of this instance
-     */
-    MetaClass getMetaClass();
-
-    /**
-     * Allows the MetaClass to be replaced with a derived implementation.
-     *
-     * @param metaClass the new metaclass
-     */
-    void setMetaClass(MetaClass metaClass);
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyObjectSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyObjectSupport.java b/src/main/groovy/lang/GroovyObjectSupport.java
deleted file mode 100644
index cf7a77f..0000000
--- a/src/main/groovy/lang/GroovyObjectSupport.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * A useful base class for Java objects wishing to be Groovy objects
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public abstract class GroovyObjectSupport implements GroovyObject {
-
-    // never persist the MetaClass
-    private transient MetaClass metaClass;
-
-    public GroovyObjectSupport() {
-        this.metaClass = getDefaultMetaClass();
-    }
-
-    public Object getProperty(String property) {
-        return getMetaClass().getProperty(this, property);
-    }
-
-    public void setProperty(String property, Object newValue) {
-        getMetaClass().setProperty(this, property, newValue);
-    }
-
-    public Object invokeMethod(String name, Object args) {
-        return getMetaClass().invokeMethod(this, name, args);
-    }
-
-    public MetaClass getMetaClass() {
-        return this.metaClass;
-    }
-
-    public void setMetaClass(MetaClass metaClass) {
-        this.metaClass =
-                null == metaClass
-                    ? getDefaultMetaClass()
-                    : metaClass;
-    }
-
-    private MetaClass getDefaultMetaClass() {
-        return InvokerHelper.getMetaClass(this.getClass());
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyResourceLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyResourceLoader.java b/src/main/groovy/lang/GroovyResourceLoader.java
deleted file mode 100644
index 7abe202..0000000
--- a/src/main/groovy/lang/GroovyResourceLoader.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * Allows frameworks that integrate with Groovy to determine how Groovy files are resolved.
- * 
- * @author Steven Devijver
- */
-public interface GroovyResourceLoader {
-
-    /**
-     * Loads a Groovy source file given its name.
-     *
-     * @param filename name of the file
-     * @return a URL
-     * @throws java.net.MalformedURLException if the URL is invalid
-     */
-    URL loadGroovySource(String filename) throws MalformedURLException;
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/lang/GroovyRuntimeException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyRuntimeException.java b/src/main/groovy/lang/GroovyRuntimeException.java
deleted file mode 100644
index 33eb51c..0000000
--- a/src/main/groovy/lang/GroovyRuntimeException.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  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 groovy.lang;
-
-import org.codehaus.groovy.ast.ASTNode;
-import org.codehaus.groovy.ast.ModuleNode;
-
-/**
- * An exception thrown by the interpreter
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- */
-public class GroovyRuntimeException extends RuntimeException {
-
-    private ModuleNode module;
-    private ASTNode node;
-
-    public GroovyRuntimeException() {
-    }
-
-    public GroovyRuntimeException(String message) {
-        super(message);
-    }
-
-    public GroovyRuntimeException(String message, ASTNode node) {
-        super(message);
-        this.node = node;
-    }
-
-    public GroovyRuntimeException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public GroovyRuntimeException(Throwable t) {
-        super();
-        initCause(t);
-    }
-
-    public void setModule(ModuleNode module) {
-        this.module = module;
-    }
-
-    public ModuleNode getModule() {
-        return module;
-    }
-
-    public String getMessage() {
-        return getMessageWithoutLocationText() + getLocationText();
-    }
-
-    public ASTNode getNode() {
-        return node;
-    }
-
-    public String getMessageWithoutLocationText() {
-        return super.getMessage();
-    }
-
-    protected String getLocationText() {
-        String answer = ". ";
-        if (node != null) {
-            answer += "At [" + node.getLineNumber() + ":" + node.getColumnNumber() + "] ";
-        }
-        if (module != null) {
-            answer += module.getDescription();
-        }
-        if (answer.equals(". ")) {
-            return "";
-        }
-        return answer;
-    }
-}