/* * Copyright 2014 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.runtime.support.spring; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.solmix.commons.util.StringUtils; import org.solmix.runtime.Container; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.w3c.dom.Element; /** * * @author solmix.f@gmail.com * @version $Id$ 2014年9月11日 */ public class ContainerDefinitionParser extends AbstractBeanDefinitionParser implements BeanDefinitionParser { private static AtomicInteger counter = new AtomicInteger(0); public ContainerDefinitionParser(){ super(); setBeanClass(ContainerType.class); } @Override protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder bean) { String cname=element.getAttribute("name"); String id = element.getAttribute("id"); if (!StringUtils.isEmpty(id)) { bean.addPropertyValue("id", id); } if(StringUtils.isEmpty(cname)){ cname="solmix"; } super.doParse(element, ctx, bean); if(ctx.getRegistry().containsBeanDefinition(cname)){ BeanDefinition def = ctx.getRegistry().getBeanDefinition(cname); copyProps(bean, def); bean.addConstructorArgValue(cname); }else if(!"solmix".equals(cname)){ bean.getRawBeanDefinition().setBeanClass(SpringContainer.class); bean.setDestroyMethodName("close"); try { element.setUserData("ID", cname, null); } catch (Throwable t) { } }else{ addBusWiringAttribute(bean, true, cname, ctx); bean.getRawBeanDefinition().setAttribute(WIRE_CONTAINER_CREATE, resolveId(element, null, ctx)); bean.addConstructorArgValue(cname); } } private void copyProps(BeanDefinitionBuilder src, BeanDefinition def) { for (PropertyValue v : src.getBeanDefinition().getPropertyValues().getPropertyValues()) { if (!"name".equals(v.getName())) { def.getPropertyValues().addPropertyValue(v.getName(), v.getValue()); } src.getBeanDefinition().getPropertyValues().removePropertyValue(v); } } @Override protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext ctx) { String container = null; try { container = (String)element.getUserData("ID"); } catch (Throwable t) { //ignore } if (container == null) { container = element.getAttribute("name"); if (StringUtils.isEmpty(container)) { container = Container.DEFAULT_CONTAINER_ID + ".config" + counter.getAndIncrement(); } else { container =container + ".config"; } try { element.setUserData("ID", container, null); } catch (Throwable t) { //maybe no DOM level 3, ignore, but, may have issues with the counter } } return container; } @Override protected void mapElement(ParserContext ctx, BeanDefinitionBuilder bean, Element e, String name) { if ("properties".equals(name)) { Map<?, ?> map = ctx.getDelegate().parseMapElement(e, bean.getBeanDefinition()); bean.addPropertyValue("properties", map); } } public static class ContainerType implements ApplicationContextAware { Container container; String name; String id; Map<String, Object> properties; public ContainerType(String name) { this.name = name; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { } public void setContainer(Container bb) { if (container == bb) { return; } container = bb; if (properties != null) { container.setProperties(properties); properties = null; } if (!StringUtils.isEmpty(id)) { container.setId(id); } /* * if (features != null) { container.setFeatures(features); features * = null; } */ } public Map<String, Object> getProperties() { if (container != null) { return container.getProperties(); } return properties; } public void setProperties(Map<String, Object> s) { if (container != null) { container.setProperties(s); } else { this.properties = s; } } public void setId(String s) { id = s; } } }