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 }