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 00:56:39 UTC

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

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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/10110145/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;
+}