
org.directwebremoting.spring.DwrNamespaceHandler Maven / Gradle / Ivy
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.directwebremoting.spring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.directwebremoting.create.NewCreator;
import org.directwebremoting.filter.ExtraLatencyAjaxFilter;
import org.directwebremoting.util.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The Spring namespace handler which handles all elements that are defined as
* part of the DWR namespace.
* The DWR namespace is defined in the spring-dwr-X.X.xsd
file. All
* elements that are encountered in Spring configuration files are automatically
* converted to their actual bean representation in the Spring bean registry.
*
* @author Erik Wiersma
* @author Bram Smeets
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class DwrNamespaceHandler extends NamespaceHandlerSupport
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init()
{
// register bean definition parsers and decorators for all dwr namespace elements
registerBeanDefinitionParser("configuration", new ConfigurationBeanDefinitionParser());
registerBeanDefinitionParser("controller", new ControllerBeanDefinitionParser());
registerBeanDefinitionDecorator("create", new CreatorBeanDefinitionDecorator());
registerBeanDefinitionDecorator("convert", new ConverterBeanDefinitionDecorator());
registerBeanDefinitionDecorator("signatures", new SignaturesBeanDefinitionDecorator());
registerBeanDefinitionDecorator("remote", new RemoteBeanDefinitionDecorator());
}
/*
*
*/
protected BeanDefinition registerSpringConfiguratorIfNecessary(BeanDefinitionRegistry registry)
{
if (!registry.containsBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID))
{
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SpringConfigurator.class);
builder.addPropertyValue("creators", new ManagedMap());
builder.addPropertyValue("converters", new ManagedMap());
registry.registerBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID, builder.getBeanDefinition());
}
return registry.getBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID);
}
/**
* Registers a new {@link org.directwebremoting.extend.Creator} in the registry using name javascript
.
* TODO: Specifically tailored to SpringCreator; ignores type
* @param registry The definition of all the Beans
* @param javascript The name of the bean in the registry.
* @param beanCreator The {@link org.directwebremoting.extend.Creator} to register.
* @param children The node list to check for nested elements
*/
protected void registerCreator(BeanDefinitionRegistry registry, String javascript, BeanDefinitionBuilder beanCreator,
NodeList children)
{
registerSpringConfiguratorIfNecessary(registry);
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanCreator.getBeanDefinition(), "__" + javascript + "_creator");
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
BeanDefinitionBuilder creatorConfig = BeanDefinitionBuilder.rootBeanDefinition(CreatorConfig.class);
creatorConfig.addPropertyReference("creator", "__" + javascript + "_creator");
List includes = new ArrayList();
creatorConfig.addPropertyValue("includes", includes);
List excludes = new ArrayList();
creatorConfig.addPropertyValue("excludes", excludes);
Properties auth = new Properties();
creatorConfig.addPropertyValue("auth", auth);
// check to see if there are any nested elements here
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) node;
if (node.getNodeName().equals("dwr:latencyfilter"))
{
BeanDefinitionBuilder beanFilter = BeanDefinitionBuilder.rootBeanDefinition(ExtraLatencyAjaxFilter.class);
beanFilter.addPropertyValue("delay", child.getAttribute("delay"));
BeanDefinitionHolder holder2 = new BeanDefinitionHolder(beanFilter.getBeanDefinition(), "__latencyFilter_" + javascript);
BeanDefinitionReaderUtils.registerBeanDefinition(holder2, registry);
ManagedList filterList = new ManagedList();
filterList.add(new RuntimeBeanReference("__latencyFilter_" + javascript));
creatorConfig.addPropertyValue("filters", filterList);
}
else if (node.getNodeName().equals("dwr:include"))
{
includes.add(child.getAttribute("method"));
}
else if (node.getNodeName().equals("dwr:exclude"))
{
excludes.add(child.getAttribute("method"));
}
else if (node.getNodeName().equals("dwr:auth"))
{
auth.setProperty(child.getAttribute("method"), child.getAttribute("role"));
}
else if (node.getNodeName().equals("dwr:convert"))
{
Element element = (Element) node;
String type = element.getAttribute("type");
String className = element.getAttribute("class");
ConverterConfig converterConfig = new ConverterConfig();
converterConfig.setType(type);
parseConverterSettings(converterConfig, element);
lookupConverters(registry).put(className, converterConfig);
}
else if (node.getNodeName().equals("dwr:filter"))
{
Element element = (Element) node;
String filterClass = element.getAttribute("class");
BeanDefinitionBuilder beanFilter;
try {
beanFilter = BeanDefinitionBuilder.rootBeanDefinition(ClassUtils.forName(filterClass));
} catch (ClassNotFoundException e) {
// TODO: proper error handling
throw new IllegalArgumentException("bla");
}
BeanDefinitionHolder holder2 = new BeanDefinitionHolder(beanFilter.getBeanDefinition(), "__filter_" + filterClass + "_" + javascript);
BeanDefinitionReaderUtils.registerBeanDefinition(holder2, registry);
ManagedList filterList = new ManagedList();
filterList.add(new RuntimeBeanReference("__filter_" + filterClass + "_" + javascript));
creatorConfig.addPropertyValue("filters", filterList);
}
else
{
throw new RuntimeException("an unknown dwr:remote sub node was fouund: " + node.getNodeName());
}
}
String creatorConfigName = "__" + javascript;
BeanDefinitionHolder holder3 = new BeanDefinitionHolder(creatorConfig.getBeanDefinition(), creatorConfigName);
BeanDefinitionReaderUtils.registerBeanDefinition(holder3, registry);
lookupCreators(registry).put(javascript, new RuntimeBeanReference(creatorConfigName));
}
protected class ConfigurationBeanDefinitionParser implements BeanDefinitionParser
{
public BeanDefinition parse(Element element, ParserContext parserContext)
{
BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinition beanDefinition = registerSpringConfiguratorIfNecessary(registry);
List createElements = DomUtils.getChildElementsByTagName(element, "create");
Iterator iter = createElements.iterator();
while (iter.hasNext())
{
Element createElement = (Element) iter.next();
findDecoratorForNode(createElement).decorate(createElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
List convertElements = DomUtils.getChildElementsByTagName(element, "convert");
iter = convertElements.iterator();
while (iter.hasNext())
{
Element convertElement = (Element) iter.next();
findDecoratorForNode(convertElement).decorate(convertElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
List signatureElements = DomUtils.getChildElementsByTagName(element, "signatures");
for (Iterator i = signatureElements.iterator(); i.hasNext(); )
{
Element signatureElement = (Element) i.next();
findDecoratorForNode(signatureElement).decorate(signatureElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
return beanDefinition;
}
}
protected class ControllerBeanDefinitionParser implements BeanDefinitionParser
{
public BeanDefinition parse(Element element, ParserContext parserContext)
{
BeanDefinitionBuilder dwrController = BeanDefinitionBuilder.rootBeanDefinition(DwrController.class);
List configurators = new ManagedList();
configurators.add(new RuntimeBeanReference(DEFAULT_SPRING_CONFIGURATOR_ID));
dwrController.addPropertyValue("configurators", configurators);
String debug = element.getAttribute("debug");
if (StringUtils.hasText(debug)) {
dwrController.addPropertyValue("debug", debug);
}
String beanName = element.getAttribute("id");
String[] aliases = null;
if (!StringUtils.hasText(beanName)) {
beanName = element.getAttribute("name");
} else {
String aliasName = element.getAttribute("name");
if (StringUtils.hasText(aliasName)) {
aliases = new String[] { aliasName };
}
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(
dwrController.getBeanDefinition(), beanName, aliases);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
return dwrController.getBeanDefinition();
}
}
protected class RemoteBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
Element element = (Element) node;
String parentBeanName = definition.getBeanName();
String javascript = element.getAttribute("javascript");
BeanDefinitionBuilder beanCreator = BeanDefinitionBuilder.rootBeanDefinition(BeanCreator.class);
beanCreator.addPropertyValue("bean", new RuntimeBeanReference(parentBeanName));
beanCreator.addPropertyValue("javascript", javascript);
registerCreator(parserContext.getRegistry(), javascript, beanCreator, node.getChildNodes());
return definition;
}
}
protected class ConverterBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
Element element = (Element) node;
String type = element.getAttribute("type");
String className = element.getAttribute("class");
BeanDefinitionRegistry registry = parserContext.getRegistry();
ConverterConfig converterConfig = new ConverterConfig();
converterConfig.setType(type);
parseConverterSettings(converterConfig, element);
lookupConverters(registry).put(className, converterConfig);
return definition;
}
}
protected void parseConverterSettings(ConverterConfig converterConfig, Element parent)
{
NodeList children = parent.getChildNodes();
// check to see if there are any nested elements here
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) node;
if (child.getNodeName().equals("dwr:include"))
{
converterConfig.addInclude(child.getAttribute("method"));
}
else if (child.getNodeName().equals("dwr:exclude"))
{
converterConfig.addExclude(child.getAttribute("method"));
}
/* TODO Why is this only a property of ObjectConverter?
else if (child.getNodeName().equals("dwr:force"))
{
converterConfig.setForce(Boolean.parseBoolean(child.getAttribute("value")));
}
*/
else
{
throw new RuntimeException("an unknown dwr:remote sub node was fouund: " + node.getNodeName());
}
}
}
/**
* Uses the BeanDefinitionDecorator since we need access to the name of the parent definition??
*/
protected class CreatorBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
String parentBeanName = definition.getBeanName();
Element element = (Element) node;
String javascript = element.getAttribute("javascript");
String type = element.getAttribute("type");
// Make sure the Creator is registered in the registry.
BeanDefinitionBuilder creator;
if ("spring".equals(type))
{
// TODO: duplicate of RemoteBeanDefinitionDecorator
creator = BeanDefinitionBuilder.rootBeanDefinition(SpringCreator.class);
creator.addPropertyValue("bean", new RuntimeBeanReference(parentBeanName));
creator.addPropertyValue("javascript", javascript);
}
else if ("new".equals(type))
{
creator = BeanDefinitionBuilder.rootBeanDefinition(NewCreator.class);
creator.addPropertyValue("className", node.getAttributes().getNamedItem("class").getNodeValue());
creator.addPropertyValue("javascript", javascript);
}
else
{
throw new UnsupportedOperationException("Type " + type + " is not yet supported");
}
registerCreator(parserContext.getRegistry(), javascript, creator, node.getChildNodes());
return definition;
}
}
protected class SignaturesBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
StringBuffer sigtext = new StringBuffer();
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if (child.getNodeType() != Node.TEXT_NODE && child.getNodeType() != Node.CDATA_SECTION_NODE)
{
log.warn("Ignoring illegal node type: " + child.getNodeType());
continue;
}
sigtext.append(child.getNodeValue());
}
config.getPropertyValues().addPropertyValue("signatures", sigtext.toString());
return definition;
}
}
protected Map lookupCreators(BeanDefinitionRegistry registry)
{
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
return (Map) config.getPropertyValues().getPropertyValue("creators").getValue();
}
protected Map lookupConverters(BeanDefinitionRegistry registry)
{
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
return (Map) config.getPropertyValues().getPropertyValue("converters").getValue();
}
protected final static String DEFAULT_SPRING_CONFIGURATOR_ID = "__dwrConfiguration";
/**
* The log stream
*/
protected static final Logger log = Logger.getLogger(DwrNamespaceHandler.class);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy