KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nanocontainer > script > groovy > GroovyContainerBuilder


1 /*****************************************************************************
2  * Copyright (C) NanoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by *
9  *****************************************************************************/

10 package org.nanocontainer.script.groovy;
11
12 import groovy.lang.Binding;
13 import groovy.lang.GroovyClassLoader;
14 import groovy.lang.GroovyCodeSource;
15 import groovy.lang.GroovyObject;
16 import groovy.lang.MissingPropertyException;
17 import groovy.lang.Script;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.Reader JavaDoc;
22 import java.net.URL JavaDoc;
23
24 import org.codehaus.groovy.control.CompilationFailedException;
25 import org.codehaus.groovy.runtime.InvokerHelper;
26 import org.nanocontainer.NanoContainer;
27 import org.nanocontainer.script.NanoContainerMarkupException;
28 import org.nanocontainer.script.ScriptedContainerBuilder;
29 import org.picocontainer.PicoContainer;
30 import org.picocontainer.alternatives.EmptyPicoContainer;
31 import org.nanocontainer.reflection.DefaultNanoPicoContainer;
32
33 /**
34  * {@inheritDoc}
35  * The groovy script has to return an instance of {@link NanoContainer}.
36  * There is an implicit variable named "parent" that may contain a reference to a parent
37  * container. It is recommended to use this as a constructor argument to the instantiated
38  * NanoPicoContainer.
39  *
40  * @author Paul Hammant
41  * @author Aslak Hellesøy
42  * @author Mauro Talevi
43  * @version $Revision: 3144 $
44  */

45 public class GroovyContainerBuilder extends ScriptedContainerBuilder {
46     private Class JavaDoc scriptClass;
47
48     public GroovyContainerBuilder(final Reader JavaDoc script, ClassLoader JavaDoc classLoader) {
49         super(script, classLoader);
50         createGroovyClass();
51     }
52
53     public GroovyContainerBuilder(final URL JavaDoc script, ClassLoader JavaDoc classLoader) {
54         super(script, classLoader);
55         createGroovyClass();
56     }
57
58     // TODO: This should really return NanoContainer using a nano variable in the script. --Aslak
59
protected PicoContainer createContainerFromScript(PicoContainer parentContainer, Object JavaDoc assemblyScope) {
60
61         Binding binding = new Binding();
62         if ( parentContainer == null ){
63             parentContainer = new DefaultNanoPicoContainer(getClassLoader(), new EmptyPicoContainer());
64         }
65         binding.setVariable("parent", parentContainer);
66         binding.setVariable("builder", createGroovyNodeBuilder());
67         binding.setVariable("assemblyScope", assemblyScope);
68         handleBinding(binding);
69         return runGroovyScript(binding);
70     }
71
72     /**
73      * Allows customization of the groovy node builder in descendants.
74      * @return GroovyNodeBuilder
75      */

76     protected GroovyObject createGroovyNodeBuilder() {
77         return new GroovyNodeBuilder();
78     }
79
80     /**
81      * This allows children of this class to add to the default binding.
82      * Might want to add similar or a more generic implementation of this
83      * method to support the other scripting languages.
84      */

85     protected void handleBinding(Binding binding) {
86         // does nothing but adds flexibility for children
87
}
88
89
90     /**
91      * Parses the groovy script into a class. We store the Class instead
92      * of the script proper so that it doesn't invoke race conditions on
93      * multiple executions of the script.
94      */

95     private void createGroovyClass() {
96         try {
97             GroovyClassLoader loader = new GroovyClassLoader(getClassLoader());
98             InputStream JavaDoc scriptIs = getScriptInputStream();
99             GroovyCodeSource groovyCodeSource = new GroovyCodeSource(scriptIs,"nanocontainer.groovy","groovyGeneratedForNanoContainer");
100             scriptClass = loader.parseClass(groovyCodeSource);
101         } catch (CompilationFailedException e) {
102             throw new GroovyCompilationException("Compilation Failed '" + e.getMessage() + "'", e);
103         } catch (IOException JavaDoc e) {
104             throw new NanoContainerMarkupException(e);
105         }
106
107     }
108
109     /**
110      * Executes the groovy script with the given binding.
111      * @param binding Binding
112      * @return PicoContainer
113      */

114     private PicoContainer runGroovyScript(Binding binding){
115         Script script = createGroovyScript(binding);
116
117         Object JavaDoc result = script.run();
118         Object JavaDoc picoVariable;
119         try {
120             picoVariable = binding.getVariable("pico");
121         } catch (MissingPropertyException e) {
122             picoVariable = result;
123         }
124         if (picoVariable == null) {
125             throw new NullPointerException JavaDoc("Groovy Script Variable: pico");
126         }
127
128         if (picoVariable instanceof PicoContainer) {
129             return (PicoContainer) picoVariable;
130         } else if (picoVariable instanceof NanoContainer) {
131             return ((NanoContainer) picoVariable).getPico();
132         } else {
133             throw new NanoContainerMarkupException("Bad type for pico:" + picoVariable.getClass().getName());
134         }
135
136     }
137
138     private Script createGroovyScript(Binding binding) {
139         return InvokerHelper.createScript(scriptClass, binding);
140     }
141 }
142
Popular Tags