/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.aop.microcontainer.beans.metadata;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.jboss.aop.microcontainer.beans.Aspect;
import org.jboss.aop.microcontainer.beans.ClassLoaderAwareGenericBeanFactory;
import org.jboss.beans.metadata.plugins.AbstractDependencyValueMetaData;
import org.jboss.beans.metadata.spi.BeanMetaData;
import org.jboss.beans.metadata.spi.BeanMetaDataFactory;
import org.jboss.beans.metadata.spi.MetaDataVisitorNode;
import org.jboss.beans.metadata.spi.ValueMetaData;
import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
import org.jboss.xb.annotations.JBossXmlSchema;
import org.w3c.dom.Element;
/**
* AspectBeanMetaDataFactory.
*
* @author <a href="adrian@jboss.com">Adrian Brock</a>
* @version $Revision: 61194 $
*/
@JBossXmlSchema(namespace="urn:jboss:aop-beans:1.0", elementFormDefault=XmlNsForm.QUALIFIED)
@XmlRootElement(name="aspect")
@XmlType(name="aspectType", propOrder={"aliases", "annotations", "classLoader", "constructor", "properties", "create", "start", "depends", "demands", "supplies", "installs", "uninstalls", "installCallbacks", "uninstallCallbacks"})
public class AspectBeanMetaDataFactory extends AspectManagerAwareBeanMetaDataFactory
implements BeanMetaDataFactory
{
private static final long serialVersionUID = 1L;
private String scope = "PER_VM";
private String factory;
private String aspectName;
private boolean initialisedName;
private List<Element> elements;
@XmlAttribute
public void setScope(String scope)
{
this.scope = scope;
}
public String getScope()
{
return scope;
}
@XmlAttribute
public void setFactory(String clazz)
{
this.factory = clazz;
if (getBean() != null)
{
throw new RuntimeException("Cannot set both factory and clazz");
}
//Meeded to satisfy validation in BeanFactoryHandler.endElement()
super.setBean(clazz);
}
public String getFactory()
{
return factory;
}
@Override
@XmlAttribute(name="class")
public void setBean(String bean)
{
if (factory != null)
{
throw new RuntimeException("Cannot set both factory and clazz");
}
super.setBean(bean);
}
public List<Element> getElements()
{
return elements;
}
@XmlAnyElement(lax=true)
public void setElements(List<Element> elements)
{
this.elements = elements;
}
@Override
public List<BeanMetaData> getBeans()
{
ArrayList<BeanMetaData> result = new ArrayList<BeanMetaData>();
if (this.name == null)
{
this.name = super.getBean();
}
//Add the bean factory
if (!initialisedName)
{
aspectName = this.name;
this.name = "Factory$" + name;
initialisedName = true;
}
List<BeanMetaData> beans = super.getBeans();
if (beans.size() != 1)
{
throw new RuntimeException("Wrong number of beans" + beans);
}
BeanMetaData factory = beans.get(0);
BeanMetaDataBuilder factoryBuilder = AOPBeanMetaDataBuilder.createBuilder(factory);
factoryBuilder.setBean(ClassLoaderAwareGenericBeanFactory.class.getName());
result.add(factory);
//Add the Aspect
BeanMetaDataBuilder aspectBuilder = AOPBeanMetaDataBuilder.createBuilder(aspectName, Aspect.class.getName());
aspectBuilder.addPropertyMetaData("scope", scope);
aspectBuilder.addPropertyMetaData("name", aspectName);
HashMap<String, String> attributes = new HashMap<String, String>();
attributes.put("name", name);
if (factory != null)
{
attributes.put("factory", this.factory);
}
else
{
attributes.put("class", bean);
}
attributes.put("scope", scope);
if (elements != null && elements.size() > 0)
{
aspectBuilder.addPropertyMetaData("element", XmlLoadableRootElementUtil.getRootElementString(elements, getTagName(), attributes));
}
setAspectManagerProperty(aspectBuilder);
if (this.factory != null)
{
aspectBuilder.addPropertyMetaData("factory", Boolean.TRUE);
}
result.add(aspectBuilder.getBeanMetaData());
if (hasInjectedBeans(factory))
{
configureWithDependencies(factoryBuilder, aspectBuilder);
}
else
{
configureNoDependencies(aspectBuilder);
}
return result;
}
private void configureWithDependencies(BeanMetaDataBuilder factoryBuilder, BeanMetaDataBuilder aspectBuilder)
{
aspectBuilder.addPropertyMetaData("adviceBean", name);
factoryBuilder.addInstallWithThis("install", aspectBuilder.getBeanMetaData().getName());
factoryBuilder.addUninstall("uninstall", aspectBuilder.getBeanMetaData().getName());
}
private void configureNoDependencies(BeanMetaDataBuilder aspectBuilder)
{
ValueMetaData inject = aspectBuilder.createInject(name);
aspectBuilder.addPropertyMetaData("advice", inject);
}
private boolean hasInjectedBeans(BeanMetaData beanMetaData)
{
ArrayList<ValueMetaData> dependencies = new ArrayList<ValueMetaData>();
getDependencies(dependencies, beanMetaData);
for (ValueMetaData dep : dependencies)
{
if(!((String)dep.getUnderlyingValue()).startsWith("jboss.kernel:service="))
{
return true;
}
}
return false;
}
private void getDependencies(ArrayList<ValueMetaData> dependencies, MetaDataVisitorNode node)
{
if (node instanceof AbstractDependencyValueMetaData)
{
dependencies.add((AbstractDependencyValueMetaData)node);
}
Iterator<? extends MetaDataVisitorNode> children = node.getChildren();
if (children != null)
{
while (children.hasNext())
{
MetaDataVisitorNode child = children.next();
getDependencies(dependencies, child);
}
}
}
protected String getTagName()
{
return "aspect";
}
}