KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > scripting > config > ScriptBeanDefinitionParser


1 /*
2  * Copyright 2002-2007 the original author or authors.
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 org.springframework.scripting.config;
18
19 import java.util.List JavaDoc;
20
21 import org.w3c.dom.Element JavaDoc;
22
23 import org.springframework.beans.factory.config.ConstructorArgumentValues;
24 import org.springframework.beans.factory.config.RuntimeBeanReference;
25 import org.springframework.beans.factory.support.AbstractBeanDefinition;
26 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
27 import org.springframework.beans.factory.support.RootBeanDefinition;
28 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
29 import org.springframework.beans.factory.xml.ParserContext;
30 import org.springframework.beans.factory.xml.XmlReaderContext;
31 import org.springframework.scripting.support.ScriptFactoryPostProcessor;
32 import org.springframework.util.StringUtils;
33 import org.springframework.util.xml.DomUtils;
34
35 /**
36  * BeanDefinitionParser implementation for the '<code>&lt;lang:groovy/&gt;</code>',
37  * '<code>&lt;lang:jruby/&gt;</code>' and '<code>&lt;lang:bsh/&gt;</code>' tags.
38  * Allows for objects written using dynamic languages to be easily exposed with
39  * the {@link org.springframework.beans.factory.BeanFactory}.
40  *
41  * <p>The script for each object can be specified either as a reference to the Resource
42  * containing it (using the '<code>script-source</code>' attribute) or inline in the XML configuration
43  * itself (using the '<code>inline-script</code>' attribute.
44  *
45  * <p>By default, dynamic objects created with these tags are <strong>not</strong> refreshable.
46  * To enable refreshing, specify the refresh check delay for each object (in milliseconds) using the
47  * '<code>refresh-check-delay</code>' attribute.
48  *
49  * @author Rob Harrop
50  * @author Rod Johnson
51  * @since 2.0
52  */

53 class ScriptBeanDefinitionParser extends AbstractBeanDefinitionParser {
54
55     /**
56      * The unique name under which the internally managed {@link ScriptFactoryPostProcessor} is
57      * registered in the {@link BeanDefinitionRegistry}.
58      */

59     private static final String JavaDoc SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME = ".scriptFactoryPostProcessor";
60
61     private static final String JavaDoc SCRIPT_SOURCE_ATTRIBUTE = "script-source";
62
63     private static final String JavaDoc INLINE_SCRIPT_ELEMENT = "inline-script";
64
65     private static final String JavaDoc SCOPE_ATTRIBUTE = "scope";
66
67     private static final String JavaDoc SCRIPT_INTERFACES_ATTRIBUTE = "script-interfaces";
68
69     private static final String JavaDoc REFRESH_CHECK_DELAY_ATTRIBUTE = "refresh-check-delay";
70     
71     private static final String JavaDoc CUSTOMIZER_REF_ATTRIBUTE = "customizer-ref";
72
73
74     /**
75      * The {@link org.springframework.scripting.ScriptFactory} class that this
76      * parser instance will create bean definitions for.
77      */

78     private final String JavaDoc scriptFactoryClassName;
79
80
81     /**
82      * Create a new instance of this parser, creating bean definitions for the
83      * supplied {@link org.springframework.scripting.ScriptFactory} class.
84      * @param scriptFactoryClassName the ScriptFactory class to operate on
85      */

86     public ScriptBeanDefinitionParser(String JavaDoc scriptFactoryClassName) {
87         this.scriptFactoryClassName = scriptFactoryClassName;
88     }
89
90
91     /**
92      * Parses the dynamic object element and returns the resulting bean definition.
93      * Registers a {@link ScriptFactoryPostProcessor} if needed.
94      */

95     protected AbstractBeanDefinition parseInternal(Element JavaDoc element, ParserContext parserContext) {
96         // Resolve the script source.
97
String JavaDoc value = resolveScriptSource(element, parserContext.getReaderContext());
98         if (value == null) {
99             return null;
100         }
101
102         // Set up infrastructure.
103
registerScriptFactoryPostProcessorIfNecessary(parserContext.getRegistry());
104
105         // Create script factory bean definition.
106
RootBeanDefinition beanDefinition = new RootBeanDefinition();
107         beanDefinition.setBeanClassName(this.scriptFactoryClassName);
108         beanDefinition.setSource(parserContext.extractSource(element));
109
110         // Determine bean scope.
111
String JavaDoc scope = element.getAttribute(SCOPE_ATTRIBUTE);
112         if (StringUtils.hasLength(scope)) {
113             beanDefinition.setScope(scope);
114         }
115
116         // Attach any refresh metadata.
117
String JavaDoc refreshCheckDelay = element.getAttribute(REFRESH_CHECK_DELAY_ATTRIBUTE);
118         if (StringUtils.hasText(refreshCheckDelay)) {
119             beanDefinition.setAttribute(
120                     ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, new Long JavaDoc(refreshCheckDelay));
121         }
122
123         // Add constructor arguments.
124
ConstructorArgumentValues cav = beanDefinition.getConstructorArgumentValues();
125         int constructorArgNum = 0;
126         cav.addIndexedArgumentValue(constructorArgNum++, value);
127         if (element.hasAttribute(SCRIPT_INTERFACES_ATTRIBUTE)) {
128             cav.addIndexedArgumentValue(constructorArgNum++, element.getAttribute(SCRIPT_INTERFACES_ATTRIBUTE));
129         }
130         
131         // This is used for Groovy. It's a bean reference to a customizer bean.
132
if (element.hasAttribute(CUSTOMIZER_REF_ATTRIBUTE)) {
133             String JavaDoc customizerBeanName = element.getAttribute(CUSTOMIZER_REF_ATTRIBUTE);
134             cav.addIndexedArgumentValue(constructorArgNum++, new RuntimeBeanReference(customizerBeanName));
135         }
136
137         // Add any property definitions that need adding.
138
parserContext.getDelegate().parsePropertyElements(element, beanDefinition);
139
140         return beanDefinition;
141     }
142
143     /**
144      * Resolves the script source from either the '<code>script-source</code>' attribute or
145      * the '<code>inline-script</code>' element. Logs and {@link XmlReaderContext#error} and
146      * returns <code>null</code> if neither or both of these values are specified.
147      */

148     private String JavaDoc resolveScriptSource(Element JavaDoc element, XmlReaderContext readerContext) {
149         boolean hasScriptSource = element.hasAttribute(SCRIPT_SOURCE_ATTRIBUTE);
150         List JavaDoc elements = DomUtils.getChildElementsByTagName(element, INLINE_SCRIPT_ELEMENT);
151         if (hasScriptSource && !elements.isEmpty()) {
152             readerContext.error("Only one of 'script-source' and 'inline-script' should be specified.", element);
153             return null;
154         }
155         else if (hasScriptSource) {
156             return element.getAttribute(SCRIPT_SOURCE_ATTRIBUTE);
157         }
158         else if (!elements.isEmpty()) {
159             Element JavaDoc inlineElement = (Element JavaDoc) elements.get(0);
160             return "inline:" + DomUtils.getTextValue(inlineElement);
161         }
162         else {
163             readerContext.error("Must specify either 'script-source' or 'inline-script'.", element);
164             return null;
165         }
166     }
167
168     /**
169      * Registers a {@link ScriptFactoryPostProcessor} bean definition in the supplied
170      * {@link BeanDefinitionRegistry} if the {@link ScriptFactoryPostProcessor} hasn't
171      * already been registered.
172      */

173     private static void registerScriptFactoryPostProcessorIfNecessary(BeanDefinitionRegistry registry) {
174         if (!registry.containsBeanDefinition(SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME)) {
175             RootBeanDefinition beanDefinition = new RootBeanDefinition(ScriptFactoryPostProcessor.class);
176             registry.registerBeanDefinition(SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME, beanDefinition);
177         }
178     }
179
180 }
181
Popular Tags