View Javadoc
1   /*
2    * Copyright 2011 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.fatwire.gst.foundation.groovy;
18  
19  import groovy.util.GroovyScriptEngine;
20  import groovy.util.ResourceException;
21  import groovy.util.ScriptException;
22  
23  import java.io.File;
24  import java.io.FileFilter;
25  import java.net.MalformedURLException;
26  import java.net.URI;
27  import java.net.URL;
28  
29  import javax.servlet.ServletContext;
30  
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.commons.logging.Log;
33  import org.codehaus.groovy.control.CompilationFailedException;
34  
35  import COM.FutureTense.Interfaces.ICS;
36  
37  import com.fatwire.gst.foundation.facade.logging.LogUtil;
38  
39  /**
40   * Loader for groovy script classes, configured via the ServletContext
41   * 
42   * @author Dolf Dijkstra
43   * @since Mar 28, 2011
44   */
45  /*
46   * alternative method:
47   * http://groovy.codehaus.org/Alternate+Spring-Groovy-Integration
48   */
49  public class DiskGroovyLoader implements GroovyLoader {
50  
51      private Log logger = LogUtil.getLog(getClass());
52      private GroovyScriptEngine groovyScriptEngine;
53  
54      private File scriptPath;
55      private String configPath = "/WEB-INF/gsf-groovy";
56      private int minimumRecompilationInterval = 0;
57  
58      public DiskGroovyLoader() {
59          super();
60  
61      }
62  
63      public DiskGroovyLoader(ServletContext servletContext) {
64          bootEngine(servletContext.getRealPath(configPath));
65  
66      }
67  
68      public void bootEngine(String path) {
69          scriptPath = new File(path).getAbsoluteFile();
70          scriptPath.mkdirs();
71          if (!scriptPath.exists() || !scriptPath.isDirectory())
72              throw new IllegalStateException("The realPath " + scriptPath + " is not a directory.");
73          URI u = scriptPath.toURI();
74          URL[] paths;
75          try {
76              paths = new URL[] { u.toURL() };
77              groovyScriptEngine = new GroovyScriptEngine(paths, Thread.currentThread().getContextClassLoader());
78              groovyScriptEngine.getConfig().setRecompileGroovySource(true);
79              groovyScriptEngine.getConfig().setMinimumRecompilationInterval(minimumRecompilationInterval);
80          } catch (MalformedURLException e) {
81              throw new IllegalStateException("The realPath " + scriptPath + " can't be made into a URL. "
82                      + e.getMessage(), e);
83          }
84  
85      }
86  
87      @Override
88      public Object load(ICS ics,final String name) throws Exception {
89  
90          Class<?> c;
91          try {
92              c = groovyScriptEngine.loadScriptByName(toScriptName(name));
93          } catch (ResourceException e) {
94  
95              if (logger.isDebugEnabled())
96                  logger.debug("GroovyScriptEngine was not able to load " + name + " as a script: " + e.getMessage()
97                          + ". Now trying as a class.");
98              String className = name.replace('/', '.');
99              try {
100                 c = groovyScriptEngine.getGroovyClassLoader().loadClass(className);
101             } catch (ClassNotFoundException cnfe) {
102                 if (logger.isDebugEnabled())
103                     logger.debug("GroovyClassLoader was not able to load " + className + ": " + cnfe.getMessage()
104                             + ". Aborting.");
105                 return null;
106 
107             }
108         }
109 
110         return c.newInstance();
111     }
112 
113     protected String toScriptName(String name) {
114         if (name.endsWith(".groovy")) {
115             return StringUtils.removeEnd(name, ".groovy").replace('.', '/') + ".groovy";
116         } else
117             return name.replace('.', '/') + ".groovy";
118     }
119 
120     protected String toClassName(String name) {
121 
122         return name.replace('/', '.').replace('\\', '.').substring(0, name.length() - 7);
123     }
124 
125     public void precompile() {
126         doDir(scriptPath);
127 
128     }
129 
130     protected void doDir(File dir) {
131         File[] listFiles = dir.listFiles(new FileFilter() {
132 
133             @Override
134             public boolean accept(File pathname) {
135                 return pathname.isDirectory() || pathname.getName().endsWith(".groovy");
136             }
137 
138         });
139         for (File file : listFiles) {
140             if (file.isDirectory()) {
141                 doDir(file);
142             } else {
143                 String name = file.getAbsolutePath().substring(scriptPath.getAbsolutePath().length() + 1);
144                 try {
145 
146                     groovyScriptEngine.loadScriptByName(name);
147                 } catch (CompilationFailedException e) {
148                     logger.warn(e.getMessage() + " on " + name + " during precompilation.");
149                 } catch (ResourceException e) {
150                     logger.warn(e.getMessage() + " on " + name + " during precompilation.");
151                 } catch (ScriptException e) {
152                     logger.warn(e.getMessage() + " on " + name + " during precompilation.");
153                 }
154             }
155         }
156     }
157 
158     /**
159      * @return the configPath
160      */
161     public String getConfigPath() {
162         return configPath;
163     }
164 
165     /**
166      * @param configPath the configPath to set
167      */
168     public void setConfigPath(String configPath) {
169         this.configPath = configPath;
170     }
171 
172     /**
173      * @return the minimumRecompilationInterval
174      */
175     public int getMinimumRecompilationInterval() {
176         return minimumRecompilationInterval;
177     }
178 
179     /**
180      * Sets the minimumRecompilationInterval of the GroovyScriptEngine
181      * configuration.
182      * 
183      * @param minimumRecompilationInterval the minimumRecompilationInterval to
184      *            set
185      */
186     public void setMinimumRecompilationInterval(int minimumRecompilationInterval) {
187         this.minimumRecompilationInterval = minimumRecompilationInterval;
188         GroovyScriptEngine g = getGroovyScriptEngine();
189         if (g != null) {
190             g.getConfig().setMinimumRecompilationInterval(minimumRecompilationInterval);
191         }
192     }
193 
194     public GroovyScriptEngine getGroovyScriptEngine() {
195         return groovyScriptEngine;
196     }
197 
198     public void setGroovyScriptEngine(GroovyScriptEngine groovyScrptEngine) {
199         this.groovyScriptEngine = groovyScrptEngine;
200     }
201 
202 }