You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by bh...@apache.org on 2009/12/21 00:01:01 UTC

svn commit: r892677 - in /myfaces/extensions/scripting/trunk/core/core/src: main/java/org/apache/myfaces/extensions/scripting/compiler/ test/java/org/apache/myfaces/extensions/scripting/compiler/

Author: bhuemer
Date: Sun Dec 20 23:01:01 2009
New Revision: 892677

URL: http://svn.apache.org/viewvc?rev=892677&view=rev
Log:
- Corrected some typos again
- Extended the Groovy compiler

Modified:
    myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompiler.java
    myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/JavacCompiler.java
    myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/Jsr199Compiler.java
    myfaces/extensions/scripting/trunk/core/core/src/test/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompilerTest.java

Modified: myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompiler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompiler.java?rev=892677&r1=892676&r2=892677&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompiler.java (original)
+++ myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompiler.java Sun Dec 20 23:01:01 2009
@@ -1,19 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.myfaces.extensions.scripting.compiler;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.extensions.scripting.loader.ClassLoaderUtils;
+import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.ErrorCollector;
+import org.codehaus.groovy.control.messages.Message;
+import org.codehaus.groovy.control.messages.SimpleMessage;
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
 
 import java.io.File;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
 /**
- * 
+ * <p>A compiler implementation that can be used to compile Groovy source files.</p>
  *
  */
 public class GroovyCompiler implements Compiler {
 
+    /**
+     * The logger instance for this class.
+     */
+    private static final Log logger = LogFactory.getLog(GroovyCompiler.class);
+
     // ------------------------------------------ Compiler methods
 
     /**
@@ -21,8 +51,9 @@
      *
      * @param sourcePath the path to the source directory
      * @param targetPath the path to the target directory
-     * @param file       the relative file name of the class you want to compile
-     * @return the compilation result, i.e. as of now only the compiler output
+     * @param file       the file of the class you want to compile
+     * @param classLoader the class loader to use to determine the classpath
+     * @return the compilation result
      */
     public CompilationResult compile(File sourcePath, File targetPath, String file, ClassLoader classLoader)
             throws CompilationException {
@@ -35,7 +66,8 @@
      * @param sourcePath the path to the source directory
      * @param targetPath the path to the target directory
      * @param file       the file of the class you want to compile
-     * @return the compilation result, i.e. as of now only the compiler output
+     * @param classLoader the class loader to use to determine the classpath
+     * @return the compilation result
      */
     public CompilationResult compile(File sourcePath, File targetPath, File file, ClassLoader classLoader)
             throws CompilationException {
@@ -45,13 +77,68 @@
                 buildCompilerConfiguration(sourcePath, targetPath, file, classLoader));
         compilationUnit.getConfiguration().setOutput(new PrintWriter(compilerOutput));
         compilationUnit.addSource(file);
-        compilationUnit.compile();
 
-        return new CompilationResult(compilerOutput.toString());
+        CompilationResult result;
+
+        try {
+            compilationUnit.compile();
+
+            result = new CompilationResult(compilerOutput.toString());
+        } catch (CompilationFailedException ex) {
+            // Register all collected error messages from the Groovy compiler
+            result = new CompilationResult(compilerOutput.toString());
+            ErrorCollector collector = compilationUnit.getErrorCollector();
+            for (int i = 0; i < collector.getErrorCount(); ++i) {
+                result.registerError(convertMessage(collector.getError(i)));
+            }
+        }
+
+        // Register all collected warnings from the Groovy compiler
+        ErrorCollector collector = compilationUnit.getErrorCollector();
+        for (int i = 0; i < collector.getWarningCount(); ++i) {
+            result.registerWarning(convertMessage(collector.getWarning(i)));
+        }
+
+        return result;
     }
 
     // ------------------------------------------ Utility methods
 
+    /**
+     * <p>Converts the given Groovy compiler message into a compilation message that
+     * our compilation API consists of.</p>
+     *
+     * @param message the Groovy compiler message you want to convert
+     *
+     * @return the final converted compilation message
+     */
+    protected CompilationResult.CompilationMessage convertMessage(Message message) {
+        if (message instanceof SimpleMessage) {
+            SimpleMessage simpleMessage = (SimpleMessage) message;
+            return new CompilationResult.CompilationMessage(-1, simpleMessage.getMessage());
+        } else if (message instanceof SyntaxErrorMessage) {
+            SyntaxErrorMessage syntaxErrorMessage = (SyntaxErrorMessage) message;
+            return new CompilationResult.CompilationMessage(
+                    syntaxErrorMessage.getCause().getLine(), syntaxErrorMessage.getCause().getMessage());
+        } else {
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "This compiler came across an unknown message kind ['" + message + "']. It will be ignored.");
+            }
+
+            return null;
+        }
+    }
+
+    /**
+     * <p>Configures the compiler by building its configuration object.</p>
+     *
+     * @param sourcePath the path to the source directory
+     * @param targetPath the path to the target directory
+     * @param file       the file of the class you want to compile
+     * @param classLoader the class loader to use to determine the classpath
+     * @return the compiler configuration
+     */
     protected CompilerConfiguration buildCompilerConfiguration(File sourcePath, File targetPath, File file, ClassLoader classLoader) {
         CompilerConfiguration configuration = new CompilerConfiguration();
 

Modified: myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/JavacCompiler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/JavacCompiler.java?rev=892677&r1=892676&r2=892677&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/JavacCompiler.java (original)
+++ myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/JavacCompiler.java Sun Dec 20 23:01:01 2009
@@ -156,11 +156,11 @@
                     "compile(String, PrintWriter). Are you sure that you're using a valid Sun JDK?", ex);
         }
         catch (InvocationTargetException ex) {
-            throw new IllegalStateException("An error occured while invoking the compile(String, PrintWriter) method of the " +
+            throw new IllegalStateException("An error occurred while invoking the compile(String, PrintWriter) method of the " +
                     "Javac compiler class '" + compilerClass + "'. Are you sure that you're using a valid Sun JDK?", ex);
         }
         catch (IllegalAccessException ex) {
-            throw new IllegalStateException("An error occured while invoking the compile(String, PrintWriter) method of the " +
+            throw new IllegalStateException("An error occurred while invoking the compile(String, PrintWriter) method of the " +
                     "Javac compiler class '" + compilerClass + "'. Are you sure that you're using a valid Sun JDK?", ex);
         }
     }
@@ -211,7 +211,7 @@
     }
 
     /**
-     * <p>Returns a possibly newly created classloader that you can use in order to load the
+     * <p>Returns a possibly newly created class loader that you can use in order to load the
      * Javac compiler class. Usually the user would have to put the JAR file
      * '$JAVA_HOME$/lib/tools.jar' on the classpath but this method recognizes this on its own
      * and loads the JAR file if necessary. However, it's not guaranteed that the Javac compiler
@@ -220,7 +220,7 @@
      *
      * @param toolsJar the location of the JAR file '$JAVA_HOME$/lib/tools.jar' or <code>null</code>
      *                 if you want it to be searched for automatically
-     * @return a classloader that you can use in order to load the Javac compiler class
+     * @return a class loader that you can use in order to load the Javac compiler class
      * @throws MalformedURLException if an error occurred while constructing the URL
      */
     private static ClassLoader createJavacAwareClassLoader(URL toolsJar) throws MalformedURLException {
@@ -230,7 +230,7 @@
             if (logger.isDebugEnabled()) {
                 logger.debug("Seemingly the required JAR file '$JAVA_HOME$/lib/tools.jar' has already been "
                         + "put on the classpath as the class '" + JAVAC_MAIN + "' is present. So there's no "
-                        + "need to create a custom classloader for the Javac compiler.");
+                        + "need to create a custom class loader for the Javac compiler.");
             }
 
             return ClassLoaderUtils.getDefaultClassLoader();

Modified: myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/Jsr199Compiler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/Jsr199Compiler.java?rev=892677&r1=892676&r2=892677&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/Jsr199Compiler.java (original)
+++ myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/extensions/scripting/compiler/Jsr199Compiler.java Sun Dec 20 23:01:01 2009
@@ -135,7 +135,7 @@
     protected List<String> buildCompilerOptions(File sourcePath, File targetPath, ClassLoader classLoader) {
         List<String> arguments = new ArrayList<String>();
 
-        // Note that we're knowingly not specifying the sourcepath as the compiler really should compile
+        // Note that we're knowingly not specifying the source path as the compiler really should compile
         // only a single file (see 'file'). The dependent classes are available on the classpath anyway.
         // Otherwise the compiler would also compile dependent classes, which we want to avoid! This
         // would result in different versions of a Class file being in use (the system doesn't know that
@@ -148,7 +148,7 @@
         arguments.add("-d");
         arguments.add(targetPath.getAbsolutePath());
 
-        // Specify the classpath of the given classloader. This enables the user to write new Java
+        // Specify the classpath of the given class loader. This enables the user to write new Java
         // "scripts" that depend on classes that have already been loaded previously. Otherwise he
         // wouldn't be able to use for example classes that are available in a library.
         arguments.add("-classpath");

Modified: myfaces/extensions/scripting/trunk/core/core/src/test/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompilerTest.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/core/src/test/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompilerTest.java?rev=892677&r1=892676&r2=892677&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/core/src/test/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompilerTest.java (original)
+++ myfaces/extensions/scripting/trunk/core/core/src/test/java/org/apache/myfaces/extensions/scripting/compiler/GroovyCompilerTest.java Sun Dec 20 23:01:01 2009
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.apache.myfaces.extensions.scripting.compiler;
 
 import org.apache.myfaces.extensions.scripting.AbstractGeneratorTestCase;
@@ -12,6 +30,11 @@
 
     // ------------------------------------------ Test methods
 
+    /**
+     * <p>Tests whether it is possible to compile a dynamically generated Groovy source file.</p>
+     * 
+     * @throws Exception if an error occurs
+     */
     public void testCompileGeneratedFile() throws Exception {
         writeFile("/src/main/groovy/org/apache/myfaces/extensions/scripting/HelloWorld.groovy", new String[]{
                 "package org.apache.myfaces.extensions.scripting;   ",
@@ -35,8 +58,78 @@
                 buildAbsolutePath("/target/test-classes/"), "org/apache/myfaces/extensions/scripting/HelloWorld.class").exists());
     }
 
+    /**
+     * <p>Tests whether compilation fails in case of an invalid Groovy source file.</p>
+     *
+     * @throws Exception if an error occurs
+     */
+    public void testCompileGeneratedFileWithError() throws Exception {
+        writeFile("/src/main/groovy/org/apache/myfaces/extensions/scripting/HelloWorld.groovy", new String[]{
+                "package org.apache.myfaces.extensions.scripting;   ",
+                "                                                   ",
+                "def class HelloWorld {                             ",
+                "                                                   ",
+                "   def static main(String[] args) {                ",
+                "       System2.out.println(\"Hello World\");       ",
+                "   }                                               ",
+                "}                                                  "
+        });
+
+        Compiler compiler = new GroovyCompiler();
+        CompilationResult result = compiler.compile(
+                new File(buildAbsolutePath("/src/main/groovy")),
+                new File(buildAbsolutePath("/target/test-classes")),
+                "org/apache/myfaces/extensions/scripting/HelloWorld.groovy", getCurrentClassLoader());
+
+        assertTrue(result.hasErrors());
+        assertFalse(new File(
+                buildAbsolutePath("/target/test-classes/"), "org/apache/myfaces/extensions/scripting/HelloWorld.class").exists());
+    }
+
+    /**
+     * <p>Tests whether it is possible to reference dependencies in the Groovy
+     * source files that have to be resolved using the supplied class loader.</p>
+     * 
+     * @throws Exception if an error occurs
+     */
+    public void testCompileFileWithDependencies() throws Exception {
+        writeFile("/src/main/groovy/org/apache/myfaces/extensions/scripting/DummyCompiler.groovy", new String[]{
+                "package org.apache.myfaces.extensions.scripting;                                   ",
+                "                                                                                   ",
+                "import java.io.File;                                                               ",
+                "import org.apache.myfaces.extensions.scripting.compiler.Compiler;                  ",
+                "import org.apache.myfaces.extensions.scripting.compiler.CompilationResult;         ",
+                "                                                                                   ",
+                "def class DummyCompiler implements Compiler {                                      ",
+                "                                                                                   ",
+                "   def CompilationResult compile(File s, File t, String f, ClassLoader c) {        ",
+                "       return null;                                                                ",
+                "   }                                                                               ",
+                "                                                                                   ",
+                "   def CompilationResult compile(File s, File t, File f, ClassLoader c) {          ",
+                "       return null;                                                                ",
+                "   }                                                                               ",
+                "}                                                                                  "
+        });
+
+        Compiler compiler = new GroovyCompiler();
+        CompilationResult result = compiler.compile(
+                new File(buildAbsolutePath("/src/main/groovy")),
+                new File(buildAbsolutePath("/target/test-classes")),
+                "org/apache/myfaces/extensions/scripting/DummyCompiler.groovy", getCurrentClassLoader());
+
+        assertFalse(result.hasErrors());
+        assertTrue(new File(
+                buildAbsolutePath("/target/test-classes/"), "org/apache/myfaces/extensions/scripting/DummyCompiler.class").exists());
+    }
+
     // ------------------------------------------ Utility methods
 
+    /**
+     * <p>Returns the class loader that has loaded this class.</p>
+     * 
+     * @return the class loader that has loaded this class
+     */
     protected ClassLoader getCurrentClassLoader() {
         return getClass().getClassLoader();
     }