Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 08C52200D7E for ; Sun, 17 Dec 2017 16:04:36 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 055C3160C17; Sun, 17 Dec 2017 15:04:36 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id F1767160C4B for ; Sun, 17 Dec 2017 16:04:29 +0100 (CET) Received: (qmail 66598 invoked by uid 500); 17 Dec 2017 15:04:29 -0000 Mailing-List: contact commits-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list commits@groovy.apache.org Received: (qmail 66285 invoked by uid 99); 17 Dec 2017 15:04:28 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 17 Dec 2017 15:04:28 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id D845AF1820; Sun, 17 Dec 2017 15:04:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cchampeau@apache.org To: commits@groovy.apache.org Date: Sun, 17 Dec 2017 15:04:33 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [11/62] [abbrv] [partial] groovy git commit: Move Java source set into `src/main/java` archived-at: Sun, 17 Dec 2017 15:04:36 -0000 http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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 Chris Poirier + */ +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/a188738d/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 Chris Poirier + */ +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/a188738d/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 Chris Poirier + */ +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/a188738d/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 Chris Poirier + */ +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/a188738d/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 Chris Poirier + */ + +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/a188738d/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 Chris Poirier + */ +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/a188738d/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 @@ + + + + package org.codehaus.groovy.control.io.* + + +

Internal classes for Groovier Input/Output.

+ + http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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 Chris Poirier + */ + +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/a188738d/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 Chris Poirier + */ + +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( ": " + this.message ); + writer.println(""); + } + } + +} + + + + http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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 Chris Poirier + */ + +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/a188738d/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 Chris Poirier + */ + +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/a188738d/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 Chris Poirier + */ + +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/a188738d/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 Chris Poirier + */ + +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/a188738d/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 @@ + + + + package org.codehaus.groovy.control.messages.* + + +

Error message classes.

+ + http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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 @@ + + + + package org.codehaus.groovy.control.* + + +

Compiler control classes.

+ + http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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 @@ + + + + package org.codehaus.groovy.* + + +

Groovy Language for the JVM

+ + http://git-wip-us.apache.org/repos/asf/groovy/blob/a188738d/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/a188738d/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/a188738d/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/a188738d/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 fields = new LazyReference(softBundle) { + public CachedField[] initValue() { + final Field[] declaredFields = (Field[]) + AccessController.doPrivileged(new PrivilegedAction() { + 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 constructors = new LazyReference(softBundle) { + public CachedConstructor[] initValue() { + final Constructor[] declaredConstructors = (Constructor[]) + AccessController.doPrivileged(new PrivilegedAction/**/() { + 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 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 methods = new LazyReference(softBundle) { + public CachedMethod[] initValue() { + final Method[] declaredMethods = (Method[]) + AccessController.doPrivileged(new PrivilegedAction/**/() { + 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 methods = new ArrayList(declaredMethods.length); + List mopMethods = new ArrayList(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 cachedSuperClass = new LazyReference(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 = new LazyReference(softBundle) { + public CallSiteClassLoader initValue() { + return + AccessController.doPrivileged(new PrivilegedAction() { + public CallSiteClassLoader run() { + return new CallSiteClassLoader(CachedClass.this.cachedClass); + } + }); + } + }; + + private final LazyReference> hierarchy = new LazyReference>(softBundle) { + public LinkedList initValue() { + Set res = new LinkedHashSet (); + + 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 (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> declaredInterfaces = new LazyReference> (softBundle) { + public Set initValue() { + Set res = new HashSet (0); + + Class[] classes = getTheClass().getInterfaces(); + for (Class cls : classes) { + res.add(ReflectionCache.getCachedClass(cls)); + } + return res; + } + }; + + private final LazyReference> interfaces = new LazyReference> (softBundle) { + public Set initValue() { + Set res = new HashSet (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 getInterfaces() { + return interfaces.get(); + } + + public Set 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 arr = new ArrayList(); + 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 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 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 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 arr) { + final MetaClass metaClass = classInfo.getStrongMetaClass(); + if (metaClass != null) { + if (metaClass.getClass() == MetaClassImpl.class) { + classInfo.setStrongMetaClass(null); + List res = new ArrayList(); + 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 arr) { + List res = new ArrayList(); + 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 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/a188738d/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/a188738d/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); + } + } +}