KickJava   Java API By Example, From Geeks To Geeks.

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


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 James Strachan *
9  *****************************************************************************/

10
11 package org.nanocontainer.script.groovy;
12
13 import groovy.lang.Closure;
14 import groovy.lang.GroovyObject;
15 import groovy.util.BuilderSupport;
16
17 import java.io.File JavaDoc;
18 import java.net.MalformedURLException JavaDoc;
19 import java.net.URL JavaDoc;
20 import java.security.AccessController JavaDoc;
21 import java.security.Permission JavaDoc;
22 import java.security.PrivilegedAction JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import org.codehaus.groovy.runtime.InvokerHelper;
30 import org.nanocontainer.ClassNameKey;
31 import org.nanocontainer.ClassPathElement;
32 import org.nanocontainer.DefaultNanoContainer;
33 import org.nanocontainer.NanoContainer;
34 import org.nanocontainer.script.NanoContainerMarkupException;
35 import org.nanocontainer.script.NodeBuilderDecorationDelegate;
36 import org.nanocontainer.script.NullNodeBuilderDecorationDelegate;
37 import org.picocontainer.ComponentMonitor;
38 import org.picocontainer.MutablePicoContainer;
39 import org.picocontainer.Parameter;
40 import org.picocontainer.PicoContainer;
41 import org.picocontainer.ComponentAdapter;
42 import org.picocontainer.defaults.ComponentAdapterFactory;
43 import org.picocontainer.defaults.ComponentMonitorStrategy;
44 import org.picocontainer.defaults.ConstantParameter;
45 import org.picocontainer.defaults.DefaultComponentAdapterFactory;
46 import org.picocontainer.defaults.DefaultPicoContainer;
47 import org.picocontainer.defaults.DelegatingComponentMonitor;
48
49 /**
50  * <p>
51  * Builds node trees of PicoContainers and Pico components using GroovyMarkup.
52  * </p>
53  * <p>Simple example usage in your groovy script:
54  * <code><pre>
55  * builder = new org.nanocontainer.script.groovy.OldGroovyNodeBuilder()
56  * pico = builder.container(parent:parent) {
57  * &nbsp;&nbsp;component(class:org.nanocontainer.testmodel.DefaultWebServerConfig)
58  * &nbsp;&nbsp;component(class:org.nanocontainer.testmodel.WebServerImpl)
59  * }
60  * </pre></code>
61  * </p>
62  * @author James Strachan
63  * @author Paul Hammant
64  * @author Aslak Helles&oslash;y
65  * @author Michael Rimov
66  * @author Mauro Talevi
67  * @version $Revision: 3144 $
68  * @deprecated Since version 1.0-RC-3, use GroovyNodeBuilder instead.
69  */

70 public class OldGroovyNodeBuilder extends BuilderSupport {
71
72     private static final String JavaDoc NEW_BUILDER = "newBuilder";
73     private static final String JavaDoc CONTAINER = "container";
74     private static final String JavaDoc COMPONENT = "component";
75     private static final String JavaDoc INSTANCE = "instance";
76     private static final String JavaDoc KEY = "key";
77     private static final String JavaDoc PARAMETERS = "parameters";
78     private static final String JavaDoc BEAN = "bean";
79     private static final String JavaDoc BEAN_CLASS = "beanClass";
80     private static final String JavaDoc CLASS = "class";
81     private static final String JavaDoc CLASS_NAME_KEY = "classNameKey";
82     private static final String JavaDoc CLASSPATH_ELEMENT = "classPathElement";
83     private static final String JavaDoc CLASSLOADER = "classLoader";
84     private static final String JavaDoc PATH = "path";
85     private static final String JavaDoc GRANT = "grant";
86     private static final String JavaDoc HTTP = "http://";
87     private static final String JavaDoc PARENT = "parent";
88     private static final String JavaDoc COMPONENT_ADAPTER_FACTORY = "componentAdapterFactory";
89     private static final String JavaDoc COMPONENT_MONITOR = "componentMonitor";
90     private static final String JavaDoc EMPTY = "";
91     private static final String JavaDoc DO_CALL = "doCall";
92
93     private final NodeBuilderDecorationDelegate decorationDelegate;
94
95     public OldGroovyNodeBuilder(NodeBuilderDecorationDelegate decorationDelegate) {
96         this.decorationDelegate = decorationDelegate;
97     }
98
99     public OldGroovyNodeBuilder() {
100         this(new NullNodeBuilderDecorationDelegate());
101     }
102
103     protected void setParent(Object JavaDoc parent, Object JavaDoc child) {
104     }
105
106     protected Object JavaDoc doInvokeMethod(String JavaDoc s, Object JavaDoc name, Object JavaDoc args) {
107         //TODO use setClosureDelegate() from Groovy JSR
108
Object JavaDoc answer = super.doInvokeMethod(s, name, args);
109         List JavaDoc list = InvokerHelper.asList(args);
110         if (!list.isEmpty()) {
111             Object JavaDoc o = list.get(list.size() - 1);
112             if (o instanceof Closure) {
113                 Closure closure = (Closure) o;
114                 closure.setDelegate(answer);
115             }
116         }
117         return answer;
118     }
119
120     protected void setClosureDelegate(Closure closure, Object JavaDoc o) {
121         super.setClosureDelegate(closure, o);
122     }
123
124     protected Object JavaDoc createNode(Object JavaDoc name) {
125         return createNode(name, Collections.EMPTY_MAP);
126     }
127
128     protected Object JavaDoc createNode(Object JavaDoc name, Object JavaDoc value) {
129         Map JavaDoc attributes = new HashMap JavaDoc();
130         attributes.put(CLASS, value);
131         return createNode(name, attributes);
132     }
133
134     /**
135      * Override of create node. Called by BuilderSupport. It examines the
136      * current state of the builder and the given parameters and dispatches the
137      * code to one of the create private functions in this object.
138      * @param name The name of the groovy node we're building. Examples are
139      * 'container', and 'grant',
140      * @param attributes Map attributes of the current invocation.
141      * @return Object the created object.
142      */

143     protected Object JavaDoc createNode(Object JavaDoc name, Map JavaDoc attributes, Object JavaDoc value) {
144         Object JavaDoc current = getCurrent();
145         if (current != null && current instanceof GroovyObject) {
146             return createChildBuilder(current, name, attributes);
147         } else if (current == null || current instanceof NanoContainer) {
148             NanoContainer parent = (NanoContainer) current;
149             Object JavaDoc parentAttribute = attributes.get(PARENT);
150             if (parent != null && parentAttribute != null) {
151                 throw new NanoContainerMarkupException("You can't explicitly specify a parent in a child element.");
152             }
153             if (parent == null && (parentAttribute instanceof MutablePicoContainer)) {
154                 // we're not in an enclosing scope - look at parent attribute instead
155
parent = new DefaultNanoContainer((MutablePicoContainer) parentAttribute);
156             }
157             if (parent == null && (parentAttribute instanceof NanoContainer)) {
158                 // we're not in an enclosing scope - look at parent attribute instead
159
parent = (NanoContainer) parentAttribute;
160             }
161             if (name.equals(CONTAINER)) {
162                 return createChildContainer(attributes, parent);
163             } else {
164                 try {
165                     return createChildOfContainerNode(parent, name, attributes, current);
166                 } catch (ClassNotFoundException JavaDoc e) {
167                     throw new NanoContainerMarkupException("ClassNotFoundException: " + e.getMessage(), e);
168                 }
169             }
170         } else if (current instanceof ClassPathElement) {
171             if (name.equals(GRANT)) {
172                 return createGrantPermission(attributes, (ClassPathElement) current);
173             }
174             return EMPTY;
175         } else if (current instanceof ComponentAdapter && name.equals("instance")) {
176
177             // TODO - Michael.
178
// Michael, we could implement key() implementation() and possibly (with many limits on use) instance() here.
179
// Not what you outline in NANO-138 as is though.
180

181             return decorationDelegate.createNode(name, attributes, current);
182
183         } else {
184             // we don't know how to handle it - delegate to the decorator.
185
return decorationDelegate.createNode(name, attributes, current);
186         }
187     }
188
189     private Object JavaDoc createChildBuilder(Object JavaDoc current, Object JavaDoc name, Map JavaDoc attributes) {
190         GroovyObject groovyObject = (GroovyObject) current;
191         return groovyObject.invokeMethod(name.toString(), attributes);
192     }
193
194     private Object JavaDoc createGrantPermission(Map JavaDoc attributes, ClassPathElement cpe) {
195         Permission JavaDoc perm = (Permission JavaDoc) attributes.remove(CLASS);
196         return cpe.grantPermission(perm);
197
198     }
199
200     private Object JavaDoc createChildOfContainerNode(NanoContainer parentContainer, Object JavaDoc name, Map JavaDoc attributes, Object JavaDoc current) throws ClassNotFoundException JavaDoc {
201         if (name.equals(COMPONENT)) {
202             decorationDelegate.rememberComponentKey(attributes);
203             return createComponentNode(attributes, parentContainer, name);
204         } else if (name.equals(BEAN)) {
205             return createBeanNode(attributes, parentContainer.getPico());
206         } else if (name.equals(CLASSPATH_ELEMENT)) {
207             return createClassPathElementNode(attributes, parentContainer);
208         } else if (name.equals(DO_CALL)) {
209             // TODO does this node need to be handled?
210
return null;
211         } else if (name.equals(NEW_BUILDER)) {
212             return createNewBuilderNode(attributes, parentContainer);
213         } else if (name.equals(CLASSLOADER)) {
214             return createComponentClassLoader(parentContainer);
215         } else {
216             // we don't know how to handle it - delegate to the decorator.
217
return decorationDelegate.createNode(name, attributes, current);
218         }
219
220     }
221
222     private Object JavaDoc createNewBuilderNode(Map JavaDoc attributes, NanoContainer parentContainer) {
223         String JavaDoc builderClass = (String JavaDoc) attributes.remove(CLASS);
224         NanoContainer factory = new DefaultNanoContainer();
225         MutablePicoContainer parentPico = parentContainer.getPico();
226         factory.getPico().registerComponentInstance(MutablePicoContainer.class, parentPico);
227         try {
228             factory.registerComponentImplementation(GroovyObject.class, builderClass);
229         } catch (ClassNotFoundException JavaDoc e) {
230             throw new NanoContainerMarkupException("ClassNotFoundException " + builderClass);
231         }
232         Object JavaDoc componentInstance = factory.getPico().getComponentInstance(GroovyObject.class);
233         return componentInstance;
234     }
235
236     private ClassPathElement createClassPathElementNode(Map JavaDoc attributes, NanoContainer nanoContainer) {
237
238         final String JavaDoc path = (String JavaDoc) attributes.remove(PATH);
239         URL JavaDoc pathURL = null;
240         try {
241             if (path.toLowerCase().startsWith(HTTP)) {
242                 pathURL = new URL JavaDoc(path);
243             } else {
244                 Object JavaDoc rVal = AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
245                     public Object JavaDoc run() {
246                         try {
247                             File JavaDoc file = new File JavaDoc(path);
248                             if (!file.exists()) {
249                                 return new NanoContainerMarkupException("classpath '" + path + "' does not exist ");
250                             }
251                             return file.toURL();
252                         } catch (MalformedURLException JavaDoc e) {
253                             return e;
254                         }
255
256                     }
257                 });
258                 if (rVal instanceof MalformedURLException JavaDoc) {
259                     throw (MalformedURLException JavaDoc) rVal;
260                 }
261                 if (rVal instanceof NanoContainerMarkupException) {
262                     throw (NanoContainerMarkupException) rVal;
263                 }
264                 pathURL = (URL JavaDoc) rVal;
265             }
266         } catch (MalformedURLException JavaDoc e) {
267             throw new NanoContainerMarkupException("classpath '" + path + "' malformed ", e);
268         }
269         return nanoContainer.addClassLoaderURL(pathURL);
270     }
271
272     private Object JavaDoc createBeanNode(Map JavaDoc attributes, MutablePicoContainer pico) {
273         Object JavaDoc bean = createBean(attributes);
274         pico.registerComponentInstance(bean);
275         return bean;
276     }
277
278     private Object JavaDoc createComponentNode(Map JavaDoc attributes, NanoContainer nano, Object JavaDoc name) throws ClassNotFoundException JavaDoc {
279         Object JavaDoc key = attributes.remove(KEY);
280         Object JavaDoc cnkey = attributes.remove(CLASS_NAME_KEY);
281         Object JavaDoc classValue = attributes.remove(CLASS);
282         Object JavaDoc instance = attributes.remove(INSTANCE);
283         Object JavaDoc retval = null;
284         List JavaDoc parameters = (List JavaDoc) attributes.remove(PARAMETERS);
285
286         MutablePicoContainer pico = nano.getPico();
287
288         if (cnkey != null) {
289             key = new ClassNameKey((String JavaDoc)cnkey);
290         }
291
292         Parameter[] parameterArray = getParameters(parameters);
293         if (classValue instanceof Class JavaDoc) {
294             Class JavaDoc clazz = (Class JavaDoc) classValue;
295             key = key == null ? clazz : key;
296             retval = pico.registerComponentImplementation(key, clazz, parameterArray);
297         } else if (classValue instanceof String JavaDoc) {
298             String JavaDoc className = (String JavaDoc) classValue;
299             key = key == null ? className : key;
300             retval = nano.registerComponentImplementation(key, className, parameterArray);
301         } else if (instance != null) {
302             key = key == null ? instance.getClass() : key;
303             retval = pico.registerComponentInstance(key, instance);
304         } else {
305             throw new NanoContainerMarkupException("Must specify a class attribute for a component as a class name (string) or Class. Attributes:" + attributes);
306         }
307
308         return retval;
309     }
310
311     protected Object JavaDoc createNode(Object JavaDoc name, Map JavaDoc attributes) {
312         return createNode(name, attributes, null);
313     }
314
315     /**
316      * Creates a new container. There may or may not be a parent to this container.
317      * Supported attributes are:
318      * <ul>
319      * <li><tt>componentAdapterFactory</tt>: The ComponentAdapterFactory used for new container</li>
320      * <li><tt>componentMonitor</tt>: The ComponentMonitor used for new container</li>
321      * </ul>
322      * @param attributes Map Attributes defined by the builder in the script.
323      * @param parent The parent container
324      * @return The NanoContainer
325      */

326     protected NanoContainer createChildContainer(Map JavaDoc attributes, NanoContainer parent) {
327
328         ClassLoader JavaDoc parentClassLoader = null;
329         MutablePicoContainer childContainer = null;
330         if (parent != null) {
331             parentClassLoader = parent.getComponentClassLoader();
332             if ( isAttribute(attributes, COMPONENT_ADAPTER_FACTORY) ) {
333                 ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes);
334                 childContainer = new DefaultPicoContainer(
335                         decorationDelegate.decorate(componentAdapterFactory, attributes), parent.getPico());
336                 if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
337                     changeComponentMonitor(childContainer, createComponentMonitor(attributes));
338                 }
339                 parent.getPico().addChildContainer(childContainer);
340             } else if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
341                 ComponentAdapterFactory componentAdapterFactory = new DefaultComponentAdapterFactory(
342                                                     createComponentMonitor(attributes));
343                 childContainer = new DefaultPicoContainer(
344                         decorationDelegate.decorate(componentAdapterFactory, attributes), parent.getPico());
345             } else {
346                 childContainer = parent.getPico().makeChildContainer();
347             }
348         } else {
349             parentClassLoader = (ClassLoader JavaDoc) AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
350                 public Object JavaDoc run() {
351                     return PicoContainer.class.getClassLoader();
352                 }
353             });
354             ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes);
355             childContainer = new DefaultPicoContainer(
356                     decorationDelegate.decorate(componentAdapterFactory, attributes));
357             if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
358                 changeComponentMonitor(childContainer, createComponentMonitor(attributes));
359             }
360         }
361
362         MutablePicoContainer decoratedPico = decorationDelegate.decorate(childContainer);
363         if ( isAttribute(attributes, CLASS) ) {
364             Class JavaDoc clazz = (Class JavaDoc) attributes.get(CLASS);
365             return createNanoContainer(clazz, decoratedPico, parentClassLoader);
366         } else {
367             return new DefaultNanoContainer(parentClassLoader, decoratedPico);
368         }
369     }
370
371     private void changeComponentMonitor(MutablePicoContainer childContainer, ComponentMonitor monitor) {
372         if ( childContainer instanceof ComponentMonitorStrategy ){
373             ((ComponentMonitorStrategy)childContainer).changeMonitor(monitor);
374         }
375     }
376
377     private NanoContainer createNanoContainer(Class JavaDoc clazz, MutablePicoContainer decoratedPico, ClassLoader JavaDoc parentClassLoader) {
378         DefaultPicoContainer instantiatingContainer = new DefaultPicoContainer();
379         instantiatingContainer.registerComponentInstance(ClassLoader JavaDoc.class, parentClassLoader);
380         instantiatingContainer.registerComponentInstance(MutablePicoContainer.class, decoratedPico);
381         instantiatingContainer.registerComponentImplementation(NanoContainer.class, clazz);
382         Object JavaDoc componentInstance = instantiatingContainer.getComponentInstance(NanoContainer.class);
383         return (NanoContainer) componentInstance;
384     }
385
386     private boolean isAttribute(Map JavaDoc attributes, String JavaDoc key) {
387         return attributes.containsKey(key) && attributes.get(key) != null;
388     }
389
390     private ComponentAdapterFactory createComponentAdapterFactory(Map JavaDoc attributes) {
391         final ComponentAdapterFactory factory = (ComponentAdapterFactory) attributes.remove(COMPONENT_ADAPTER_FACTORY);
392         if ( factory == null ){
393             return new DefaultComponentAdapterFactory();
394         }
395         return factory;
396     }
397
398     private ComponentMonitor createComponentMonitor(Map JavaDoc attributes) {
399         final ComponentMonitor monitor = (ComponentMonitor) attributes.remove(COMPONENT_MONITOR);
400         if ( monitor == null ){
401             return new DelegatingComponentMonitor();
402         }
403         return monitor;
404     }
405
406     protected NanoContainer createComponentClassLoader(NanoContainer parent) {
407         return new DefaultNanoContainer(parent.getComponentClassLoader(), parent.getPico());
408     }
409
410
411     protected Object JavaDoc createBean(Map JavaDoc attributes) {
412         Class JavaDoc type = (Class JavaDoc) attributes.remove(BEAN_CLASS);
413         if (type == null) {
414             throw new NanoContainerMarkupException("Bean must have a beanClass attribute");
415         }
416         try {
417             Object JavaDoc bean = type.newInstance();
418             // now let's set the properties on the bean
419
for (Iterator JavaDoc iter = attributes.entrySet().iterator(); iter.hasNext();) {
420                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
421                 String JavaDoc name = entry.getKey().toString();
422                 Object JavaDoc value = entry.getValue();
423                 InvokerHelper.setProperty(bean, name, value);
424             }
425             return bean;
426         } catch (IllegalAccessException JavaDoc e) {
427             throw new NanoContainerMarkupException("Failed to create bean of type '" + type + "'. Reason: " + e, e);
428         } catch (InstantiationException JavaDoc e) {
429             throw new NanoContainerMarkupException("Failed to create bean of type " + type + "'. Reason: " + e, e);
430         }
431     }
432
433     private Parameter[] getParameters(List JavaDoc paramsList) {
434         if (paramsList == null) {
435             return null;
436         }
437         int n = paramsList.size();
438         Parameter[] parameters = new Parameter[n];
439         for (int i = 0; i < n; ++i) {
440             parameters[i] = toParameter(paramsList.get(i));
441         }
442         return parameters;
443     }
444
445     private Parameter toParameter(Object JavaDoc obj) {
446         return obj instanceof Parameter ? (Parameter) obj : new ConstantParameter(obj);
447     }
448
449 }
450
Popular Tags