001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.camel.spring.xml;
019
020 import org.apache.camel.spring.CamelContextFactoryBean;
021 import org.apache.camel.spring.EndpointFactoryBean;
022 import org.apache.camel.spring.CamelBeanPostProcessor;
023 import static org.apache.camel.util.ObjectHelper.isNotNullOrBlank;
024 import org.apache.camel.builder.xml.XPathBuilder;
025 import org.springframework.beans.factory.config.BeanDefinition;
026 import org.springframework.beans.factory.config.RuntimeBeanReference;
027 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
028 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
029 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
030 import org.springframework.beans.factory.xml.ParserContext;
031 import org.springframework.util.xml.DomUtils;
032 import org.w3c.dom.Element;
033 import org.w3c.dom.Node;
034 import org.w3c.dom.NodeList;
035
036 import java.util.Set;
037 import java.util.HashSet;
038
039 public class CamelNamespaceHandler extends NamespaceHandlerSupport {
040 protected CamelBeanDefinitionParser routesParser = new CamelBeanDefinitionParser(this);
041 protected BeanDefinitionParser endpointParser = new BeanDefinitionParser(EndpointFactoryBean.class);
042 protected BeanDefinitionParser beanPostProcessorParser = new BeanDefinitionParser(CamelBeanPostProcessor.class);
043 protected Set<String> parserElementNames = new HashSet<String>();
044
045 public void init() {
046 registerParser("routes", routesParser);
047 registerParser("routeBuilder", routesParser);
048 registerParser("endpoint", endpointParser);
049
050 registerParser("camelContext", new BeanDefinitionParser(CamelContextFactoryBean.class) {
051 @Override
052 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
053 super.doParse(element, parserContext, builder);
054
055 String contextId = element.getAttribute("id");
056
057 Element routes = element.getOwnerDocument().createElement("routes");
058 // now lets move all the content there...
059 NodeList list = element.getChildNodes();
060 for (int size = list.getLength(), i = 0; i < size; i++) {
061 Node child = list.item(i);
062 if (child instanceof Element) {
063 Element childElement = (Element) child;
064 if (child.getLocalName().equals("beanPostProcessor")) {
065 String beanPostProcessorId = contextId + ":beanPostProcessor";
066 childElement.setAttribute("id", beanPostProcessorId);
067 BeanDefinition definition = beanPostProcessorParser.parse(childElement, parserContext);
068 definition.getPropertyValues().addPropertyValue("camelContext", new RuntimeBeanReference(contextId));
069 }
070 else {
071 element.removeChild(child);
072 routes.appendChild(child);
073 }
074 }
075 }
076 String routeId = contextId + ":routes";
077 routes.setAttribute("id", routeId);
078
079 BeanDefinition definition = routesParser.parse(routes, parserContext);
080 definition.getPropertyValues().addPropertyValue("context", new RuntimeBeanReference(contextId));
081 parserContext.registerComponent(new BeanComponentDefinition(definition, routeId));
082
083 list = routes.getElementsByTagName("endpoint");
084 for (int size = list.getLength(), i = 0; i < size; i++) {
085 Element node = (Element) list.item(i);
086 definition = endpointParser.parse(node, parserContext);
087 String id = node.getAttribute("id");
088 if (isNotNullOrBlank(id)) {
089 definition.getPropertyValues().addPropertyValue("context", new RuntimeBeanReference(contextId));
090 //definition.getPropertyValues().addPropertyValue("context", builder.getBeanDefinition());
091 parserContext.registerComponent(new BeanComponentDefinition(definition, id));
092 }
093 }
094 }
095 });
096
097 registerParser("xpath", new BeanDefinitionParser(XPathBuilder.class) {
098 @Override
099 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
100 // lets create a child context
101 String xpath = DomUtils.getTextValue(element);
102 builder.addConstructorArg(xpath);
103 super.doParse(element, parserContext, builder);
104 builder.addPropertyValue("namespacesFromDom", element);
105 }
106 });
107
108
109 // scripting expressions
110 registerScriptParser("script", null);
111 registerScriptParser("groovy", "groovy");
112 registerScriptParser("ruby", "jruby");
113 registerScriptParser("javaScript", "js");
114 registerScriptParser("python", "python");
115 registerScriptParser("php", "php");
116 }
117
118 protected void registerScriptParser(String elementName, String engineName) {
119 registerParser(elementName, new ScriptDefinitionParser(engineName));
120 }
121
122 protected void registerParser(String name, org.springframework.beans.factory.xml.BeanDefinitionParser parser) {
123 parserElementNames.add(name);
124 registerBeanDefinitionParser(name, parser);
125 }
126
127 public Set<String> getParserElementNames() {
128 return parserElementNames;
129 }
130 }