1 /**
2 * Copyright 2005-2006 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.services.scripting.groovy;
16
17 import org.figure8.join.core.InvalidParameterException;
18 import org.figure8.join.services.scripting.ScriptLauncher;
19 import org.figure8.join.services.scripting.ScriptException;
20 import org.figure8.join.util.LogUtil;
21
22 import groovy.lang.Script;
23 import groovy.lang.Binding;
24 import groovy.lang.GroovyShell;
25 import org.apache.commons.logging.Log;
26 import org.codehaus.groovy.control.CompilationFailedException;
27
28 import java.io.IOException;
29 import java.io.PrintWriter;
30 import java.util.Properties;
31 import java.util.Enumeration;
32 /**
33 * Extension of {@link ScriptLauncher} dedicated to the Groovy script
34 * language (see http://groovy.codehaus.org). This implementation lets
35 * you wrap the execution of a Groovy script within a ScriptLauncher.
36 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
37 * @version $Revision: 1.2 $
38 */
39 public class GroovyScriptLauncher extends ScriptLauncher{
40
41
42
43 /** Get a commons logger. */
44 private static final Log log = LogUtil.getLog(GroovyScriptLauncher.class);
45
46
47
48
49 /** A handler on parsed script file (for optimization) */
50 private Script groovyScript = null;
51 /** Copy of base class value (for optimization on parsing) */
52 private String scriptPath = super.getScriptPath();
53
54
55
56
57 /** Creates a new instance of GroovyScriptLauncher. */
58 public GroovyScriptLauncher(){
59 }
60
61 /**
62 * Creates a new instance of GroovyScriptLauncher with script path.
63 * @param scriptPath the path of script to later execute
64 * @throws InvalidParameterException if path cannot be accessed
65 */
66 public GroovyScriptLauncher(String scriptPath) throws InvalidParameterException{
67 super(scriptPath);
68 }
69
70
71
72
73 /**
74 * Run the Groovy script file identified by <code>scriptPath</code> inner
75 * field. Properties passed as param are injected into the Groovy script
76 * as binding properties. Script can directly use them using the ${property_name}
77 * form. <b>Warning: </b> "." in properties keys passing in are modified
78 * into "_" before injected. This is necessary because "." as special meaning
79 * in Groovy (nested field) that we don't want to have here.
80 * @param properties
81 */
82 public void runScript(Properties properties) throws ScriptException{
83
84 PrintWriter writer = null;
85 try{
86
87 if (scriptHasChanged()){
88
89 Thread th = Thread.currentThread();
90 GroovyShell shell = new GroovyShell(th.getContextClassLoader());
91 log.info("Parsing Groovy script '" + getScript().getPath() + "'");
92 groovyScript = shell.parse(getScript());
93 }
94
95
96 Binding binding = new Binding();
97 Enumeration keys = properties.keys();
98 while (keys != null && keys.hasMoreElements()){
99 String key = (String)keys.nextElement();
100 String value = properties.getProperty(key);
101
102
103 if (log.isDebugEnabled())
104 log.debug("Adding property '" + key.replace('.', '_') + "' (" + value + ") as binding property");
105 binding.setProperty(key.replace('.', '_'), value);
106 }
107
108
109 if (getLogOutputStream() != null){
110 writer = new PrintWriter(getLogOutputStream());
111 binding.setVariable("out", writer);
112 }
113
114
115 groovyScript.setBinding(binding);
116 groovyScript.run();
117 }
118 catch (CompilationFailedException cfe){
119
120 log.error("The compilation of '" + scriptPath + "' Groovy script failed !");
121 log.error("Here's the detailed message: " + cfe.getMessage());
122 throw new ScriptException("Compilation of Groovy script failed", cfe);
123 }
124 catch (IOException ioe){
125
126 log.error("IOException while accessing Groovy script '" + scriptPath + "'");
127 throw new ScriptException("IOException while accessing Groovy script", ioe);
128 }
129 finally{
130
131 if (writer != null)
132 writer.close();
133 }
134 }
135
136
137
138
139 /** @return True if script has changed since last parsing */
140 private boolean scriptHasChanged(){
141
142 if (groovyScript== null || !getScriptPath().equals(scriptPath)){
143 log.info("Script has changed, getting " + getScriptPath());
144 scriptPath = getScriptPath();
145 return true;
146 }
147 return false;
148 }
149 }