You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by cc...@apache.org on 2017/12/14 21:56:35 UTC

[10/57] [abbrv] [partial] groovy git commit: Move Java source set into `src/main/java`

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/FileReaderSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/FileReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/FileReaderSource.java
new file mode 100644
index 0000000..6171f7a
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/FileReaderSource.java
@@ -0,0 +1,91 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.io;
+
+import org.codehaus.groovy.control.CompilerConfiguration;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+
+/**
+ *  A ReaderSource for source files.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+public class FileReaderSource extends AbstractReaderSource {
+    private final File file;  // The File from which we produce Readers.
+    private final Charset UTF8 = Charset.forName("UTF-8");
+
+   /**
+    *  Creates the ReaderSource from a File descriptor.
+    * @param file script source file
+    * @param configuration configuration for compiling source
+    */
+    public FileReaderSource( File file, CompilerConfiguration configuration ) {
+       super( configuration );
+        this.file = file;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    /**
+    *  Returns a new Reader on the underlying source object.  
+    */
+    public Reader getReader() throws IOException {
+       // we want to remove the BOM windows adds from a file if the encoding is UTF-8
+       // in other cases we depend on the charsets 
+       Charset cs = Charset.forName(configuration.getSourceEncoding());
+       InputStream in = new BufferedInputStream(new FileInputStream(file));
+       if (UTF8.name().equalsIgnoreCase(cs.name())) {
+           in.mark(3);
+           boolean hasBOM = true;
+           try {
+               int i = in.read();
+               hasBOM &= i == 0xEF;
+               i = in.read();
+               hasBOM &= i == 0xBB;
+               i = in.read();
+               hasBOM &= i == 0xFF;
+           } catch (IOException ioe) {
+               hasBOM= false;
+           }
+           if (!hasBOM) in.reset();
+       }
+       return new InputStreamReader( in, cs );
+    }
+
+    /**
+     * Returns a URI for the file of this source.
+     *
+     * @return URI for the file of this source.
+     */
+    public URI getURI() {
+        return file.toURI();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/InputStreamReaderSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/InputStreamReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/InputStreamReaderSource.java
new file mode 100644
index 0000000..d018698
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/InputStreamReaderSource.java
@@ -0,0 +1,76 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.control.io;
+
+import org.codehaus.groovy.control.CompilerConfiguration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+
+/**
+ * A ReaderSource for source strings.
+ *
+ * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+public class InputStreamReaderSource extends AbstractReaderSource {
+    private InputStream stream;  // The InputStream from which we produce a Reader.
+
+    /**
+     * Creates the ReaderSource from a File descriptor.
+     *
+     * @param stream        stream containing source
+     * @param configuration configuration for compiling source
+     */
+    public InputStreamReaderSource(InputStream stream, CompilerConfiguration configuration) {
+        super(configuration);
+        this.stream = stream;
+    }
+
+    /**
+     * Returns a new Reader on the underlying source object.
+     */
+    public Reader getReader() throws IOException {
+        if (stream != null) {
+            Reader reader = new InputStreamReader(stream, configuration.getSourceEncoding());
+            stream = null;
+            return reader;
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the source can be restarted (ie. if getReader()
+     * will return non-null on subsequent calls.
+     */
+    public boolean canReopenSource() {
+        return false;
+    }
+
+    /**
+     * TODO: Should return the URI for this source, but we can't know what it is here.
+     *
+     * @return null
+     */
+    public URI getURI() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/NullWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/NullWriter.java b/src/main/java/org/codehaus/groovy/control/io/NullWriter.java
new file mode 100644
index 0000000..c783249
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/NullWriter.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 org.codehaus.groovy.control.io;
+
+import java.io.Writer;
+
+/**
+ *  An Writer than eats its input.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+public class NullWriter extends Writer {
+    public static final NullWriter DEFAULT = new NullWriter();
+    
+    public void close() {}
+    
+    public void flush() {}
+    
+    public void write( char[] cbuf, int off, int len ) {}
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/ReaderSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/ReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/ReaderSource.java
new file mode 100644
index 0000000..76ddd3c
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/ReaderSource.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 org.codehaus.groovy.control.io;
+
+import org.codehaus.groovy.control.HasCleanup;
+import org.codehaus.groovy.control.Janitor;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URI;
+
+/**
+ *  An interface for things that can supply (and potentially resupply) a Reader
+ *  on a source stream.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+public interface ReaderSource extends HasCleanup {
+   /**
+    *  Returns a new Reader on the underlying source object.  Returns
+    *  null if the source can't be reopened.
+    * @throws java.io.IOException if there was an error opening for stream
+    * @return the reader to the resource
+    */
+    Reader getReader() throws IOException;
+    
+   /**
+    *  Returns true if the source can be restarted (ie. if getReader()
+    *  will return non-null on subsequent calls.
+    * @return true if the resource can be reopened for reading
+    */
+    boolean canReopenSource();
+    
+   /**
+    *  Returns a line from the source, or null, if unavailable.  If
+    *  you supply a Janitor, resources will be cached.
+    * @param lineNumber the number of the line of interest
+    * @param janitor helper to clean up afterwards
+    * @return the line of interest
+    */
+    String getLine( int lineNumber, Janitor janitor );
+    
+   /**
+    *  Cleans up any cached resources used by getLine().
+    */
+    void cleanup();
+
+    /**
+     * Returns a URI for this source.
+     *
+     * @since 2.3.0
+     */
+    URI getURI();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/StringReaderSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/StringReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/StringReaderSource.java
new file mode 100644
index 0000000..5e83de0
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/StringReaderSource.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.io;
+
+import org.codehaus.groovy.control.CompilerConfiguration;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ *  A ReaderSource for source strings.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class StringReaderSource extends AbstractReaderSource {
+    private final String string;  // The String from which we produce Readers.
+
+   /**
+    * Creates the ReaderSource from a File descriptor.
+    *
+    * @param string string containing script source
+    * @param configuration configuration for compiling source
+    */
+   public StringReaderSource( String string, CompilerConfiguration configuration ) {
+       super( configuration );
+       this.string = string;
+   }
+    
+   /**
+    *  Returns a new Reader on the underlying source object.  
+    */
+   public Reader getReader() throws IOException {
+       return new StringReader( string );
+   }
+
+    /**
+     * Returns a Data URI (RFC 2397) containing the literal value of this source string.
+     *
+     * @return Data URI containing the literal value of this source string.
+     */
+    public URI getURI() {
+        try {
+            return new URI("data", "," + string, null);
+        } catch (URISyntaxException e) {
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/URLReaderSource.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/URLReaderSource.java b/src/main/java/org/codehaus/groovy/control/io/URLReaderSource.java
new file mode 100644
index 0000000..7c92559
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/io/URLReaderSource.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.io;
+
+import groovy.lang.GroovyRuntimeException;
+import org.codehaus.groovy.control.CompilerConfiguration;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+/**
+ *  A ReaderSource for source files hosted at a URL.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+public class URLReaderSource extends AbstractReaderSource {
+    private final URL url;  // The URL from which we produce Readers.
+    
+   /**
+    *  Creates the ReaderSource from a File descriptor.
+    * @param url url pointing to script source
+    * @param configuration configuration for compiling source
+    */
+    public URLReaderSource( URL url, CompilerConfiguration configuration ) {
+       super( configuration );
+        this.url = url;
+    }
+
+   /**
+    *  Returns a new Reader on the underlying source object.  
+    */
+    public Reader getReader() throws IOException {
+       return new InputStreamReader( url.openStream(), configuration.getSourceEncoding() );
+    }
+
+    /**
+     * Returns a URI for the URL of this source.
+     *
+     * @return URI for the URL of this source.
+     */
+    public URI getURI() {
+        try {
+            return url.toURI();
+        } catch (URISyntaxException e) {
+            throw new GroovyRuntimeException("Unable to convert the URL <" + url + "> to a URI!", e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/io/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/io/package.html b/src/main/java/org/codehaus/groovy/control/io/package.html
new file mode 100644
index 0000000..9f92588
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/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 org.codehaus.groovy.control.io.*</title>
+  </head>
+  <body>
+    <p>Internal classes for Groovier Input/Output.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/ExceptionMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/ExceptionMessage.java b/src/main/java/org/codehaus/groovy/control/messages/ExceptionMessage.java
new file mode 100644
index 0000000..363b9f5
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/ExceptionMessage.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 org.codehaus.groovy.control.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.ProcessingUnit;
+
+import java.io.PrintWriter;
+
+
+
+/**
+ *  A class for error messages produced by the parser system.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class ExceptionMessage extends Message
+{
+    protected boolean verbose = true;
+
+    private Exception cause = null;   // The exception source of the message, if any
+    ProcessingUnit owner = null;
+
+    public ExceptionMessage( Exception cause, boolean v, ProcessingUnit owner )
+    {
+        this.verbose = v;
+        this.cause = cause;
+        this.owner = owner;
+    }
+    
+    
+   
+   /**
+    *  Returns the underlying Exception.
+    */
+
+    public Exception getCause()
+    {
+        return this.cause;
+    }
+    
+
+
+   /**
+    *  Writes out a nicely formatted summary of the exception. 
+    */
+    
+    public void write( PrintWriter output, Janitor janitor )
+    {
+        String description = "General error during " + owner.getPhaseDescription() + ": "; 
+        
+        String message = cause.getMessage();
+        if( message != null )
+        {
+            output.println( description + message );
+        }
+        else
+        {
+            output.println( description + cause );
+        }
+        output.println();
+
+        //if (verbose) {
+            cause.printStackTrace(output);
+        //}
+    }
+    
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/LocatedMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/LocatedMessage.java b/src/main/java/org/codehaus/groovy/control/messages/LocatedMessage.java
new file mode 100644
index 0000000..d3368ac
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/LocatedMessage.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 org.codehaus.groovy.control.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.syntax.CSTNode;
+
+import java.io.PrintWriter;
+
+
+
+/**
+ *  A base class for compilation messages.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class LocatedMessage extends SimpleMessage
+{
+    protected CSTNode context;  // The CSTNode that indicates the location to which the message applies
+    
+    public LocatedMessage( String message, CSTNode context, SourceUnit source ) 
+    {
+        super( message, source );
+        this.context = context;
+    }
+    
+    
+    public LocatedMessage( String message, Object data, CSTNode context, SourceUnit source ) 
+    {
+        super( message, data, source );
+        this.context = context;
+    }
+    
+    
+    public void write( PrintWriter writer, Janitor janitor )
+    {
+        if (owner instanceof SourceUnit) {
+            SourceUnit source = (SourceUnit) owner;
+
+            String name   = source.getName();
+            int    line   = context.getStartLine();
+            int    column = context.getStartColumn();
+            String sample = source.getSample( line, column, janitor );
+
+            if( sample != null )
+            {
+                writer.println( source.getSample(line, column, janitor) );
+            }
+
+            writer.println( name + ": " + line + ": " + this.message );
+            writer.println("");
+        } else {
+            writer.println( "<No Relevant Source>: " + this.message );
+            writer.println("");
+        }
+    }
+    
+}
+
+
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/Message.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/Message.java b/src/main/java/org/codehaus/groovy/control/messages/Message.java
new file mode 100644
index 0000000..0c2feab
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/Message.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 org.codehaus.groovy.control.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.ProcessingUnit;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.syntax.SyntaxException;
+
+import java.io.PrintWriter;
+
+
+
+/**
+ *  A base class for compilation messages.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public abstract class Message
+{
+    
+    
+   /**
+    *  Writes the message to the specified PrintWriter.  The supplied
+    *  ProcessingUnit is the unit that holds this Message.
+    */
+    
+    public abstract void write( PrintWriter writer, Janitor janitor );
+    
+    
+   /**
+    *  A synonym for write( writer, owner, null ).
+    */
+    
+    public final void write( PrintWriter writer)
+    {
+        write( writer,  null );
+    }
+    
+    
+    
+  //---------------------------------------------------------------------------
+  // FACTORY METHODS
+    
+    
+   /**
+    *  Creates a new Message from the specified text.
+    */
+    
+    public static Message create( String text, ProcessingUnit owner )
+    {
+        return new SimpleMessage( text, owner );
+    }
+    
+    
+          
+   /**
+    *  Creates a new Message from the specified text.
+    */
+     
+    public static Message create( String text, Object data, ProcessingUnit owner  )
+    {
+        return new SimpleMessage( text, data, owner);
+    }
+     
+     
+           
+   /**
+    *  Creates a new Message from the specified SyntaxException.
+    */
+      
+    public static Message create( SyntaxException error, SourceUnit owner )
+    {
+        return new SyntaxErrorMessage( error, owner );
+    }
+      
+    
+      
+    
+}
+
+
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/SimpleMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/SimpleMessage.java b/src/main/java/org/codehaus/groovy/control/messages/SimpleMessage.java
new file mode 100644
index 0000000..2cbc9d8
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/SimpleMessage.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.ProcessingUnit;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.io.PrintWriter;
+
+
+
+/**
+ *  A base class for compilation messages.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class SimpleMessage extends Message
+{
+    protected String message;  // Message text
+    protected Object data;     // Data, when the message text is an I18N identifier
+    protected ProcessingUnit owner;
+    
+    public SimpleMessage( String message, ProcessingUnit source ) 
+    {
+        this( message, null, source );
+    }
+    
+    public SimpleMessage( String message, Object data, ProcessingUnit source )
+    {
+        this.message = message;
+        this.data    = null;
+        this.owner = source;
+    }
+    
+    
+    public void write( PrintWriter writer, Janitor janitor )
+    {
+        if( owner instanceof SourceUnit )
+        {
+            String name = ((SourceUnit)owner).getName();
+            writer.println( "" + name + ": " + message );
+        }
+        else
+        {
+            writer.println( message );
+        }
+    }
+    
+    
+    public String getMessage()
+    {
+        return message;
+    }
+    
+}
+
+
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/SyntaxErrorMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/SyntaxErrorMessage.java b/src/main/java/org/codehaus/groovy/control/messages/SyntaxErrorMessage.java
new file mode 100644
index 0000000..be9339d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/SyntaxErrorMessage.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.syntax.SyntaxException;
+
+import java.io.PrintWriter;
+
+/**
+ * A class for error messages produced by the parser system.
+ *
+ * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class SyntaxErrorMessage extends Message {
+    protected SyntaxException cause;
+    protected SourceUnit source;
+    
+    public SyntaxErrorMessage(SyntaxException cause, SourceUnit source) {
+        this.cause = cause;
+        this.source = source;
+        cause.setSourceLocator(source.getName());
+    }
+
+    /**
+     * Returns the underlying SyntaxException.
+     */
+
+    public SyntaxException getCause() {
+        return this.cause;
+    }
+
+    /**
+     * Writes out a nicely formatted summary of the syntax error.
+     */
+
+    public void write(PrintWriter output, Janitor janitor) {
+        String name = source.getName();
+        int line = getCause().getStartLine();
+        int column = getCause().getStartColumn();
+        String sample = source.getSample(line, column, janitor);
+
+        output.print(name + ": " + line + ": " + getCause().getMessage());
+        if (sample != null) {
+            output.println();
+            output.print(sample);
+            output.println();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/WarningMessage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/WarningMessage.java b/src/main/java/org/codehaus/groovy/control/messages/WarningMessage.java
new file mode 100644
index 0000000..969f29f
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/WarningMessage.java
@@ -0,0 +1,118 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES 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.messages;
+
+import org.codehaus.groovy.control.Janitor;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.syntax.CSTNode;
+
+import java.io.PrintWriter;
+
+
+
+/**
+ *  A class for warning messages.
+ *
+ *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
+ */
+
+public class WarningMessage extends LocatedMessage
+{
+  //---------------------------------------------------------------------------
+  // WARNING LEVELS
+
+    public static final int NONE            = 0;  // For querying, ignore all errors
+    public static final int LIKELY_ERRORS   = 1;  // Warning indicates likely error
+    public static final int POSSIBLE_ERRORS = 2;  // Warning indicates possible error
+    public static final int PARANOIA        = 3;  // Warning indicates paranoia on the part of the compiler
+    
+    
+   /**
+    *  Returns true if a warning would be relevant to the specified level.
+    */
+    
+    public static boolean isRelevant( int actual, int limit )
+    {
+        return actual <= limit;
+    }
+    
+    
+    
+   /**
+    *  Returns true if this message is as or more important than the 
+    *  specified importance level.
+    */
+    
+    public boolean isRelevant( int importance )
+    {
+        return isRelevant( this.importance, importance );
+    }
+    
+    
+    
+  //---------------------------------------------------------------------------
+  // CONSTRUCTION AND DATA ACCESS
+
+    private final int importance;  // The warning level, for filtering
+    
+    
+   /**
+    *  Creates a new warning message.
+    * 
+    *  @param importance the warning level 
+    *  @param message    the message text
+    *  @param context    context information for locating the offending source text
+    */
+     
+    public WarningMessage( int importance, String message, CSTNode context, SourceUnit owner )
+    {
+        super( message, context, owner );
+        this.importance = importance;
+    }
+
+    
+    
+   /**
+    *  Creates a new warning message.
+    *
+    *  @param importance the warning level 
+    *  @param message    the message text
+    *  @param data       additional data needed when generating the message
+    *  @param context    context information for locating the offending source text
+    */
+     
+    public WarningMessage( int importance, String message, Object data, CSTNode context, SourceUnit owner )
+    {
+        super( message, data, context, owner );
+        this.importance = importance;
+    }
+    
+    
+    public void write( PrintWriter writer, Janitor janitor )
+    {
+        writer.print( "warning: " );
+        super.write( writer, janitor );
+    }
+
+     
+     
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/messages/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/messages/package.html b/src/main/java/org/codehaus/groovy/control/messages/package.html
new file mode 100644
index 0000000..412a4df
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/messages/package.html
@@ -0,0 +1,28 @@
+<!--
+
+     Licensed to the Apache Software Foundation (ASF) under one
+     or more contributor license agreements.  See the NOTICE file
+     distributed with this work for additional information
+     regarding copyright ownership.  The ASF licenses this file
+     to you under the Apache License, Version 2.0 (the
+     "License"); you may not use this file except in compliance
+     with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing,
+     software distributed under the License is distributed on an
+     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     KIND, either express or implied.  See the License for the
+     specific language governing permissions and limitations
+     under the License.
+
+-->
+<html>
+  <head>
+    <title>package org.codehaus.groovy.control.messages.*</title>
+  </head>
+  <body>
+    <p>Error message classes.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/control/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/package.html b/src/main/java/org/codehaus/groovy/control/package.html
new file mode 100644
index 0000000..4a9ec85
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/package.html
@@ -0,0 +1,28 @@
+<!--
+
+     Licensed to the Apache Software Foundation (ASF) under one
+     or more contributor license agreements.  See the NOTICE file
+     distributed with this work for additional information
+     regarding copyright ownership.  The ASF licenses this file
+     to you under the Apache License, Version 2.0 (the
+     "License"); you may not use this file except in compliance
+     with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing,
+     software distributed under the License is distributed on an
+     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     KIND, either express or implied.  See the License for the
+     specific language governing permissions and limitations
+     under the License.
+
+-->
+<html>
+  <head>
+    <title>package org.codehaus.groovy.control.*</title>
+  </head>
+  <body>
+    <p>Compiler control classes.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/package.html b/src/main/java/org/codehaus/groovy/package.html
new file mode 100644
index 0000000..1ff6757
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/package.html
@@ -0,0 +1,28 @@
+<!--
+
+     Licensed to the Apache Software Foundation (ASF) under one
+     or more contributor license agreements.  See the NOTICE file
+     distributed with this work for additional information
+     regarding copyright ownership.  The ASF licenses this file
+     to you under the Apache License, Version 2.0 (the
+     "License"); you may not use this file except in compliance
+     with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing,
+     software distributed under the License is distributed on an
+     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     KIND, either express or implied.  See the License for the
+     specific language governing permissions and limitations
+     under the License.
+
+-->
+<html>
+  <head>
+    <title>package org.codehaus.groovy.*</title>
+  </head>
+  <body>
+    <p>Groovy Language for the JVM</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/plugin/GroovyRunner.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/plugin/GroovyRunner.java b/src/main/java/org/codehaus/groovy/plugin/GroovyRunner.java
new file mode 100644
index 0000000..40bd257
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/plugin/GroovyRunner.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 org.codehaus.groovy.plugin;
+
+/**
+ * Classes which can run scripts should implement this interface.
+ *
+ * @deprecated use {@link org.apache.groovy.plugin.GroovyRunner}
+ */
+@Deprecated
+public interface GroovyRunner extends org.apache.groovy.plugin.GroovyRunner {
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/reflection/AccessPermissionChecker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/AccessPermissionChecker.java b/src/main/java/org/codehaus/groovy/reflection/AccessPermissionChecker.java
new file mode 100644
index 0000000..dc8194d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/AccessPermissionChecker.java
@@ -0,0 +1,84 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.reflection;
+
+import groovy.lang.GroovyObject;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ReflectPermission;
+import java.security.AccessControlException;
+
+final class AccessPermissionChecker {
+
+    private static final ReflectPermission REFLECT_PERMISSION = new ReflectPermission("suppressAccessChecks");
+
+    private AccessPermissionChecker() {
+    }
+
+    private static void checkAccessPermission(Class<?> declaringClass, final int modifiers, boolean isAccessible) {
+        final SecurityManager securityManager = System.getSecurityManager();
+        if (securityManager != null && isAccessible) {
+            if (((modifiers & Modifier.PRIVATE) != 0
+                    || ((modifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0
+                    && packageCanNotBeAddedAnotherClass(declaringClass)))
+                    && !GroovyObject.class.isAssignableFrom(declaringClass)) {
+                securityManager.checkPermission(REFLECT_PERMISSION);
+            } else if ((modifiers & (Modifier.PROTECTED)) != 0 && declaringClass.equals(ClassLoader.class)) {
+                securityManager.checkCreateClassLoader();
+            }
+        }
+    }
+
+    private static boolean packageCanNotBeAddedAnotherClass(Class<?> declaringClass) {
+        return declaringClass.getName().startsWith("java.");
+    }
+
+    static void checkAccessPermission(Method method) {
+        try {
+            checkAccessPermission(method.getDeclaringClass(), method.getModifiers(), method.isAccessible());
+        } catch (AccessControlException e) {
+            throw createCacheAccessControlExceptionOf(method, e);
+        }
+    }
+
+    private static CacheAccessControlException createCacheAccessControlExceptionOf(Method method, AccessControlException e) {
+        return new CacheAccessControlException(
+                "Groovy object can not access method " + method.getName()
+                        + " cacheAccessControlExceptionOf class " + method.getDeclaringClass().getName()
+                        + " with modifiers \"" + Modifier.toString(method.getModifiers()) + "\"", e);
+    }
+
+    static void checkAccessPermission(Field field) {
+        try {
+            checkAccessPermission(field.getDeclaringClass(), field.getModifiers(), field.isAccessible());
+        } catch (AccessControlException e) {
+            throw createCacheAccessControlExceptionOf(field, e);
+        }
+    }
+
+    private static CacheAccessControlException createCacheAccessControlExceptionOf(Field field, AccessControlException e) {
+        return new CacheAccessControlException(
+                "Groovy object can not access field " + field.getName()
+                        + " cacheAccessControlExceptionOf class " + field.getDeclaringClass().getName()
+                        + " with modifiers \"" + Modifier.toString(field.getModifiers()) + "\"", e);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/reflection/CacheAccessControlException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/CacheAccessControlException.java b/src/main/java/org/codehaus/groovy/reflection/CacheAccessControlException.java
new file mode 100644
index 0000000..c538813
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/CacheAccessControlException.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 org.codehaus.groovy.reflection;
+
+import groovy.lang.GroovyRuntimeException;
+
+public class CacheAccessControlException extends GroovyRuntimeException {
+    public CacheAccessControlException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
new file mode 100644
index 0000000..c4cb542
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
@@ -0,0 +1,542 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.reflection;
+
+import groovy.lang.Closure;
+import groovy.lang.ExpandoMetaClass;
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.MetaClass;
+import groovy.lang.MetaClassImpl;
+import groovy.lang.MetaMethod;
+import org.codehaus.groovy.classgen.asm.BytecodeHelper;
+import org.codehaus.groovy.runtime.callsite.CallSiteClassLoader;
+import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
+import org.codehaus.groovy.util.FastArray;
+import org.codehaus.groovy.util.LazyReference;
+import org.codehaus.groovy.util.ReferenceBundle;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class CachedClass {
+    private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
+    private final Class cachedClass;
+    public ClassInfo classInfo;
+    
+    private static ReferenceBundle softBundle = ReferenceBundle.getSoftBundle();
+
+    private final LazyReference<CachedField[]> fields = new LazyReference<CachedField[]>(softBundle) {
+        public CachedField[] initValue() {
+            final Field[] declaredFields = (Field[])
+               AccessController.doPrivileged(new PrivilegedAction<Field[]>() {
+                   public Field[] run() {
+                       Field[] df = getTheClass().getDeclaredFields();
+                       df = (Field[]) makeAccessible(df);
+                       return df;                                                   
+                   }
+               });
+            CachedField [] fields = new CachedField[declaredFields.length];
+            for (int i = 0; i != fields.length; ++i)
+                fields[i] = new CachedField(declaredFields[i]);
+            return fields;
+        }
+    };
+
+    private final LazyReference<CachedConstructor[]> constructors = new LazyReference<CachedConstructor[]>(softBundle) {
+        public CachedConstructor[] initValue() {
+            final Constructor[] declaredConstructors = (Constructor[])
+               AccessController.doPrivileged(new PrivilegedAction/*<Constructor[]>*/() {
+                   public /*Constructor[]*/ Object run() {
+                       return getTheClass().getDeclaredConstructors();
+                   }
+               });
+            CachedConstructor [] constructors = new CachedConstructor[declaredConstructors.length];
+            for (int i = 0; i != constructors.length; ++i)
+                constructors[i] = new CachedConstructor(CachedClass.this, declaredConstructors[i]);
+            return constructors;
+        }
+    };
+
+    // to be run in PrivilegedAction!
+    private static AccessibleObject[] makeAccessible(final AccessibleObject[] aoa) {
+        try {
+            AccessibleObject.setAccessible(aoa, true);
+            return aoa;
+        } catch (Throwable outer) {
+            // swallow for strict security managers, module systems, android or others,
+            // but try one-by-one to get the allowed ones at least
+            final ArrayList<AccessibleObject> ret = new ArrayList<>(aoa.length);
+            for (final AccessibleObject ao : aoa) {
+                try {
+                    ao.setAccessible(true);
+                    ret.add(ao);
+                } catch (Throwable inner) {
+                    // swallow for strict security managers, module systems, android or others
+                }
+            }
+            return ret.toArray((AccessibleObject[]) Array.newInstance(aoa.getClass().getComponentType(), ret.size()));
+        }
+    }
+
+    private final LazyReference<CachedMethod[]> methods = new LazyReference<CachedMethod[]>(softBundle) {
+        public CachedMethod[] initValue() {
+            final Method[] declaredMethods = (Method[])
+               AccessController.doPrivileged(new PrivilegedAction/*<Method[]>*/() {
+                   public /*Method[]*/ Object run() {
+                       try {
+                           Method[] dm = getTheClass().getDeclaredMethods();
+                           dm = (Method[]) makeAccessible(dm);
+                           return dm;
+                       } catch (Throwable e) {
+                           // Typically, Android can throw ClassNotFoundException
+                           return EMPTY_METHOD_ARRAY;
+                       }
+                   }
+               });
+            List<CachedMethod> methods = new ArrayList<CachedMethod>(declaredMethods.length);
+            List<CachedMethod> mopMethods = new ArrayList<CachedMethod>(declaredMethods.length);
+            for (int i = 0; i != declaredMethods.length; ++i) {
+                final CachedMethod cachedMethod = new CachedMethod(CachedClass.this, declaredMethods[i]);
+                final String name = cachedMethod.getName();
+
+                if (declaredMethods[i].isBridge() || name.indexOf('+') >= 0) {
+                    // Skip Synthetic methods inserted by JDK 1.5 compilers and later
+                    continue;
+                } /*else if (Modifier.isAbstract(reflectionMethod.getModifiers())) {
+                   continue;
+                }*/
+
+                if (name.startsWith("this$") || name.startsWith("super$"))
+                  mopMethods.add(cachedMethod);
+                else
+                  methods.add(cachedMethod);
+            }
+            CachedMethod [] resMethods = methods.toArray(new CachedMethod[methods.size()]);
+            Arrays.sort(resMethods);
+
+            final CachedClass superClass = getCachedSuperClass();
+            if (superClass != null) {
+                superClass.getMethods();
+                final CachedMethod[] superMopMethods = superClass.mopMethods;
+                for (int i = 0; i != superMopMethods.length; ++i)
+                  mopMethods.add(superMopMethods[i]);
+            }
+            CachedClass.this.mopMethods = mopMethods.toArray(new CachedMethod[mopMethods.size()]);
+            Arrays.sort(CachedClass.this.mopMethods, CachedMethodComparatorByName.INSTANCE);
+
+            return resMethods;
+        }
+    };
+
+    private final LazyReference<CachedClass> cachedSuperClass = new LazyReference<CachedClass>(softBundle) {
+        public CachedClass initValue() {
+            if (!isArray)
+              return ReflectionCache.getCachedClass(getTheClass().getSuperclass());
+            else
+              if (cachedClass.getComponentType().isPrimitive() || cachedClass.getComponentType() == Object.class)
+                return ReflectionCache.OBJECT_CLASS;
+              else
+                return ReflectionCache.OBJECT_ARRAY_CLASS;
+        }
+    };
+
+    private final LazyReference<CallSiteClassLoader> callSiteClassLoader = new LazyReference<CallSiteClassLoader>(softBundle) {
+        public CallSiteClassLoader initValue() {
+            return
+               AccessController.doPrivileged(new PrivilegedAction<CallSiteClassLoader>() {
+                   public CallSiteClassLoader run() {
+                       return new CallSiteClassLoader(CachedClass.this.cachedClass);
+                   }
+               });
+        }
+    };
+
+    private final LazyReference<LinkedList<ClassInfo>> hierarchy = new LazyReference<LinkedList<ClassInfo>>(softBundle) {
+        public LinkedList<ClassInfo> initValue() {
+            Set<ClassInfo> res = new LinkedHashSet<ClassInfo> ();
+
+            res.add(classInfo);
+
+            for (CachedClass iface : getDeclaredInterfaces())
+              res.addAll(iface.getHierarchy());
+
+            final CachedClass superClass = getCachedSuperClass();
+            if (superClass != null)
+              res.addAll(superClass.getHierarchy());
+
+            if (isInterface)
+              res.add(ReflectionCache.OBJECT_CLASS.classInfo);
+
+            return new LinkedList<ClassInfo> (res);
+        }
+    };
+
+    static final MetaMethod[] EMPTY = new MetaMethod[0];
+
+    int hashCode;
+
+    public  CachedMethod [] mopMethods;
+    public static final CachedClass[] EMPTY_ARRAY = new CachedClass[0];
+
+    private final LazyReference<Set<CachedClass>> declaredInterfaces = new LazyReference<Set<CachedClass>> (softBundle) {
+        public Set<CachedClass> initValue() {
+            Set<CachedClass> res = new HashSet<CachedClass> (0);
+
+            Class[] classes = getTheClass().getInterfaces();
+            for (Class cls : classes) {
+                res.add(ReflectionCache.getCachedClass(cls));
+            }
+            return res;
+        }
+    };
+
+    private final LazyReference<Set<CachedClass>> interfaces = new LazyReference<Set<CachedClass>> (softBundle) {
+        public Set<CachedClass> initValue() {
+            Set<CachedClass> res = new HashSet<CachedClass> (0);
+
+            if (getTheClass().isInterface())
+              res.add(CachedClass.this);
+
+            Class[] classes = getTheClass().getInterfaces();
+            for (Class cls : classes) {
+                final CachedClass aClass = ReflectionCache.getCachedClass(cls);
+                if (!res.contains(aClass))
+                    res.addAll(aClass.getInterfaces());
+            }
+
+            final CachedClass superClass = getCachedSuperClass();
+            if (superClass != null)
+              res.addAll(superClass.getInterfaces());
+
+            return res;
+        }
+    };
+
+    public final boolean isArray;
+    public final boolean isPrimitive;
+    public final int modifiers;
+    int distance = -1;
+    public final boolean isInterface;
+    public final boolean isNumber;
+
+    public CachedClass(Class klazz, ClassInfo classInfo) {
+        cachedClass = klazz;
+        this.classInfo = classInfo;
+        isArray = klazz.isArray();
+        isPrimitive = klazz.isPrimitive();
+        modifiers = klazz.getModifiers();
+        isInterface = klazz.isInterface();
+        isNumber = Number.class.isAssignableFrom(klazz);
+
+        for (CachedClass inf : getInterfaces()) {
+            ReflectionCache.isAssignableFrom(klazz, inf.cachedClass);
+        }
+
+        for (CachedClass cur = this; cur != null; cur = cur.getCachedSuperClass()) {
+            ReflectionCache.setAssignableFrom(cur.cachedClass, klazz);
+        }
+    }
+
+    public CachedClass getCachedSuperClass() {
+        return cachedSuperClass.get();
+    }
+
+    public Set<CachedClass> getInterfaces() {
+        return interfaces.get();
+    }
+
+    public Set<CachedClass> getDeclaredInterfaces() {
+        return declaredInterfaces.get();
+    }
+
+    public CachedMethod[] getMethods() {
+        return methods.get();
+    }
+
+    public CachedField[] getFields() {
+        return fields.get();
+    }
+
+    public CachedConstructor[] getConstructors() {
+        return constructors.get();
+    }
+
+    public CachedMethod searchMethods(String name, CachedClass[] parameterTypes) {
+        CachedMethod[] methods = getMethods();
+
+        CachedMethod res = null;
+        for (CachedMethod m : methods) {
+            if (m.getName().equals(name)
+                    && ReflectionCache.arrayContentsEq(parameterTypes, m.getParameterTypes())
+                    && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType())))
+                res = m;
+        }
+
+        return res;
+    }
+
+    public int getModifiers() {
+        return modifiers;
+    }
+
+    public Object coerceArgument(Object argument) {
+        return argument;
+    }
+    
+    public int getSuperClassDistance() {
+        if (distance>=0) return distance;
+
+        int distance = 0;
+        for (Class klazz= getTheClass(); klazz != null; klazz = klazz.getSuperclass()) {
+            distance++;
+        }
+        this.distance = distance;
+        return distance;
+    }
+
+    public int hashCode() {
+        if (hashCode == 0) {
+          hashCode = super.hashCode();
+          if (hashCode == 0)
+            hashCode = 0xcafebebe;
+        }
+        return hashCode;
+    }
+
+    public boolean isPrimitive() {
+        return isPrimitive;
+    }
+
+    public boolean isVoid() {
+        return getTheClass() == void.class;
+    }
+    
+    public boolean isInterface() {
+        return isInterface;
+    }
+
+    public String getName() {
+        return getTheClass().getName();
+    }
+
+    public String getTypeDescription() {
+        return BytecodeHelper.getTypeDescription(getTheClass());
+    }
+
+    public final Class getTheClass() {
+        return cachedClass;
+    }
+
+    public MetaMethod[] getNewMetaMethods() {
+        List<MetaMethod> arr = new ArrayList<MetaMethod>();
+        arr.addAll(Arrays.asList(classInfo.newMetaMethods));
+
+        final MetaClass metaClass = classInfo.getStrongMetaClass();
+        if (metaClass != null && metaClass instanceof ExpandoMetaClass) {
+            arr.addAll(((ExpandoMetaClass)metaClass).getExpandoMethods());
+        }
+
+        if (isInterface) {
+            MetaClass mc = ReflectionCache.OBJECT_CLASS.classInfo.getStrongMetaClass();
+            addSubclassExpandos(arr, mc);
+        }
+        else {
+            for (CachedClass cls = this; cls != null; cls = cls.getCachedSuperClass()) {
+                MetaClass mc = cls.classInfo.getStrongMetaClass();
+                addSubclassExpandos(arr, mc);
+            }
+        }
+
+        for (CachedClass inf : getInterfaces()) {
+            MetaClass mc = inf.classInfo.getStrongMetaClass();
+            addSubclassExpandos(arr, mc);
+        }
+
+        return arr.toArray(new MetaMethod[arr.size()]);
+    }
+
+    private void addSubclassExpandos(List<MetaMethod> arr, MetaClass mc) {
+        if (mc != null && mc instanceof ExpandoMetaClass) {
+            ExpandoMetaClass emc = (ExpandoMetaClass) mc;
+            for (Object mm : emc.getExpandoSubclassMethods()) {
+                if (mm instanceof MetaMethod) {
+                    MetaMethod method = (MetaMethod) mm;
+                    if (method.getDeclaringClass() == this)
+                      arr.add(method);
+                }
+                else {
+                    FastArray farr = (FastArray) mm;
+                    for (int i = 0; i != farr.size; ++i) {
+                        MetaMethod method = (MetaMethod) farr.get(i);
+                        if (method.getDeclaringClass() == this)
+                          arr.add(method);
+                    }
+                }
+            }
+        }
+    }
+
+    public void setNewMopMethods(List<MetaMethod> arr) {
+        final MetaClass metaClass = classInfo.getStrongMetaClass();
+        if (metaClass != null) {
+          if (metaClass.getClass() == MetaClassImpl.class) {
+              classInfo.setStrongMetaClass(null);
+              updateSetNewMopMethods(arr);
+              classInfo.setStrongMetaClass(new MetaClassImpl(metaClass.getTheClass()));
+              return;
+          }
+
+          if (metaClass.getClass() == ExpandoMetaClass.class) {
+              classInfo.setStrongMetaClass(null);
+              updateSetNewMopMethods(arr);
+              ExpandoMetaClass newEmc = new ExpandoMetaClass(metaClass.getTheClass());
+              newEmc.initialize();
+              classInfo.setStrongMetaClass(newEmc);
+              return;
+          }
+
+          throw new GroovyRuntimeException("Can't add methods to class " + getTheClass().getName() + ". Strong custom meta class already set.");
+        }
+
+        classInfo.setWeakMetaClass(null);
+        updateSetNewMopMethods(arr);
+    }
+
+    private void updateSetNewMopMethods(List<MetaMethod> arr) {
+        if (arr != null) {
+            final MetaMethod[] metaMethods = arr.toArray(new MetaMethod[arr.size()]);
+            classInfo.dgmMetaMethods = metaMethods;
+            classInfo.newMetaMethods = metaMethods;
+        }
+        else
+            classInfo.newMetaMethods = classInfo.dgmMetaMethods;
+    }
+
+    public void addNewMopMethods(List<MetaMethod> arr) {
+        final MetaClass metaClass = classInfo.getStrongMetaClass();
+        if (metaClass != null) {
+          if (metaClass.getClass() == MetaClassImpl.class) {
+              classInfo.setStrongMetaClass(null);
+              List<MetaMethod> res = new ArrayList<MetaMethod>();
+              Collections.addAll(res, classInfo.newMetaMethods);
+              res.addAll(arr);
+              updateSetNewMopMethods(res);
+              MetaClassImpl answer = new MetaClassImpl(((MetaClassImpl)metaClass).getRegistry(),metaClass.getTheClass());
+              answer.initialize();
+              classInfo.setStrongMetaClass(answer);
+              return;
+          }
+
+          if (metaClass.getClass() == ExpandoMetaClass.class) {
+              ExpandoMetaClass emc = (ExpandoMetaClass)metaClass;
+              classInfo.setStrongMetaClass(null);
+              updateAddNewMopMethods(arr);
+              ExpandoMetaClass newEmc = new ExpandoMetaClass(metaClass.getTheClass());
+              for (MetaMethod mm : emc.getExpandoMethods()) {
+                  newEmc.registerInstanceMethod(mm);
+              }
+              newEmc.initialize();
+              classInfo.setStrongMetaClass(newEmc);
+              return;
+          }
+
+          throw new GroovyRuntimeException("Can't add methods to class " + getTheClass().getName() + ". Strong custom meta class already set.");
+        }
+
+        classInfo.setWeakMetaClass(null);
+
+        updateAddNewMopMethods(arr);
+    }
+
+    private void updateAddNewMopMethods(List<MetaMethod> arr) {
+        List<MetaMethod> res = new ArrayList<MetaMethod>();
+        res.addAll(Arrays.asList(classInfo.newMetaMethods));
+        res.addAll(arr);
+        classInfo.newMetaMethods = res.toArray(new MetaMethod[res.size()]);
+        Class theClass = classInfo.getCachedClass().getTheClass();
+        if (theClass==Closure.class || theClass==Class.class) {
+            ClosureMetaClass.resetCachedMetaClasses();
+        }
+    }
+
+    public boolean isAssignableFrom(Class argument) {
+        return argument == null || ReflectionCache.isAssignableFrom(getTheClass(), argument);
+    }
+
+    public boolean isDirectlyAssignable(Object argument) {
+        return ReflectionCache.isAssignableFrom(getTheClass(), argument.getClass());
+    }
+
+    public CallSiteClassLoader getCallSiteLoader() {
+        return callSiteClassLoader.get();
+    }
+
+    public Collection<ClassInfo> getHierarchy() {
+        return hierarchy.get();
+    }
+
+    public static class CachedMethodComparatorByName implements Comparator {
+        public static final Comparator INSTANCE = new CachedMethodComparatorByName();
+
+        public int compare(Object o1, Object o2) {
+              return ((CachedMethod)o1).getName().compareTo(((CachedMethod)o2).getName());
+        }
+    }
+
+    public static class CachedMethodComparatorWithString implements Comparator {
+        public static final Comparator INSTANCE = new CachedMethodComparatorWithString();
+
+        public int compare(Object o1, Object o2) {
+            if (o1 instanceof CachedMethod)
+              return ((CachedMethod)o1).getName().compareTo((String)o2);
+            else
+              return ((String)o1).compareTo(((CachedMethod)o2).getName());
+        }
+    }
+
+    public String toString() {
+        return cachedClass.toString();
+    }
+
+    /**
+     * compatibility method
+     * @return this
+     */
+    public CachedClass getCachedClass () {
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/reflection/CachedConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedConstructor.java b/src/main/java/org/codehaus/groovy/reflection/CachedConstructor.java
new file mode 100644
index 0000000..74d9b71
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedConstructor.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 org.codehaus.groovy.reflection;
+
+import groovy.lang.GroovyRuntimeException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * @author Alex.Tkachman
+ */
+public class CachedConstructor extends ParameterTypes {
+    CachedClass clazz;
+
+    public final Constructor cachedConstructor;
+
+    public CachedConstructor(CachedClass clazz, final Constructor c) {
+        this.cachedConstructor = c;
+        this.clazz = clazz;
+        try {
+            AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    c.setAccessible(true);
+                    return null;
+                }
+            });
+        } catch (SecurityException e) {
+            // IGNORE
+        } catch (RuntimeException re) {
+            // test for JDK9 JIGSAW
+            if (!"java.lang.reflect.InaccessibleObjectException".equals(re.getClass().getName())) throw re;
+            // else IGNORE
+        }
+    }
+
+    public CachedConstructor(Constructor c) {
+        this(ReflectionCache.getCachedClass(c.getDeclaringClass()), c);
+    }
+
+    protected Class[] getPT() {
+        return cachedConstructor.getParameterTypes();
+    }
+
+    public static CachedConstructor find(Constructor constructor) {
+        CachedConstructor[] constructors = ReflectionCache.getCachedClass(constructor.getDeclaringClass()).getConstructors();
+        for (int i = 0; i < constructors.length; i++) {
+            CachedConstructor cachedConstructor = constructors[i];
+            if (cachedConstructor.cachedConstructor.equals(constructor))
+                return cachedConstructor;
+        }
+        throw new RuntimeException("Couldn't find method: " + constructor);
+    }
+
+    public Object doConstructorInvoke(Object[] argumentArray) {
+        argumentArray = coerceArgumentsToClasses(argumentArray);
+        return invoke(argumentArray);
+    }
+
+    public Object invoke(Object[] argumentArray) {
+        Constructor constr = cachedConstructor;
+        try {
+            return constr.newInstance(argumentArray);
+        } catch (InvocationTargetException e) {
+            throw e.getCause() instanceof RuntimeException ? (RuntimeException)e.getCause() : new InvokerInvocationException(e);
+        } catch (IllegalArgumentException e) {
+            throw createException("failed to invoke constructor: ", constr, argumentArray, e, false);
+        } catch (IllegalAccessException e) {
+            throw createException("could not access constructor: ", constr, argumentArray, e, false);
+        } catch (Exception e) {
+            if (e instanceof RuntimeException)
+                throw (RuntimeException)e;
+            else
+                throw createException("failed to invoke constructor: ", constr, argumentArray, e, true);
+        }
+    }
+
+    private static GroovyRuntimeException createException(String init, Constructor constructor, Object[] argumentArray, Throwable e, boolean setReason) {
+        return new GroovyRuntimeException(
+                init
+                        + constructor
+                        + " with arguments: "
+                        + InvokerHelper.toString(argumentArray)
+                        + " reason: "
+                        + e,
+                setReason ? e : null);
+    }
+
+    public int getModifiers () {
+        return cachedConstructor.getModifiers();
+    }
+    
+    public CachedClass getCachedClass() {
+        return clazz;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/reflection/CachedField.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedField.java b/src/main/java/org/codehaus/groovy/reflection/CachedField.java
new file mode 100644
index 0000000..a5ce0c2
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedField.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 org.codehaus.groovy.reflection;
+
+import groovy.lang.GroovyRuntimeException;
+import groovy.lang.MetaProperty;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+public class CachedField extends MetaProperty {
+    public final Field field;
+
+    public CachedField(Field field) {
+        super (field.getName(), field.getType());
+        this.field = field;
+    }
+
+    public boolean isStatic() {
+        return Modifier.isStatic(getModifiers());
+    }
+
+    public boolean isFinal() {
+        return Modifier.isFinal(getModifiers());
+    }
+
+    public int getModifiers() {
+        return field.getModifiers();
+    }
+
+    /**
+     * @return the property of the given object
+     * @throws RuntimeException if the property could not be evaluated
+     */
+    public Object getProperty(final Object object) {
+        AccessPermissionChecker.checkAccessPermission(field);
+        try {
+            return field.get(object);
+        } catch (IllegalAccessException e) {
+            throw new GroovyRuntimeException("Cannot get the property '" + name + "'.", e);
+        }
+    }
+
+    /**
+     * 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(final Object object, Object newValue) {
+        AccessPermissionChecker.checkAccessPermission(field);
+        final Object goalValue = DefaultTypeTransformation.castToType(newValue, field.getType());
+
+        if (isFinal()) {
+            throw new GroovyRuntimeException("Cannot set the property '" + name + "' because the backing field is final.");
+        }
+        try {
+            field.set(object, goalValue);
+        } catch (IllegalAccessException ex) {
+            throw new GroovyRuntimeException("Cannot set the property '" + name + "'.", ex);
+        }
+    }
+}