/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat 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.as.weld.deployment.processors;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.as.ee.structure.DeploymentType;
import org.jboss.as.ee.structure.DeploymentTypeMarker;
import org.jboss.as.ee.weld.WeldDeploymentMarker;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.server.deployment.SubDeploymentMarker;
import org.jboss.as.server.deployment.module.ModuleRootMarker;
import org.jboss.as.server.deployment.module.ResourceRoot;
import org.jboss.as.weld.deployment.ExplicitBeanArchiveMetadata;
import org.jboss.as.weld.deployment.ExplicitBeanArchiveMetadataContainer;
import org.jboss.as.weld.deployment.PropertyReplacingBeansXmlParser;
import org.jboss.as.weld.deployment.WeldAttachments;
import org.jboss.as.weld.logging.WeldLogger;
import org.jboss.vfs.VirtualFile;
import org.jboss.weld.bootstrap.spi.BeanDiscoveryMode;
import org.jboss.weld.bootstrap.spi.BeansXml;
/**
* Deployment processor that finds <literal>beans.xml</literal> files and attaches the information to the deployment
*
* @author Stuart Douglas
*/
public class BeansXmlProcessor implements DeploymentUnitProcessor {
private static final String WEB_INF_BEANS_XML = "WEB-INF/beans.xml";
private static final String META_INF_BEANS_XML = "META-INF/beans.xml";
@Override
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
Map<ResourceRoot, ExplicitBeanArchiveMetadata> beanArchiveMetadata = new HashMap<ResourceRoot, ExplicitBeanArchiveMetadata>();
ResourceRoot deploymentRoot = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
if (deploymentRoot == null) {
return;
}
PropertyReplacingBeansXmlParser parser = new PropertyReplacingBeansXmlParser(deploymentUnit);
ResourceRoot classesRoot = null;
List<ResourceRoot> structure = deploymentUnit.getAttachmentList(Attachments.RESOURCE_ROOTS);
for (ResourceRoot resourceRoot : structure) {
if (ModuleRootMarker.isModuleRoot(resourceRoot) && !SubDeploymentMarker.isSubDeployment(resourceRoot)) {
if (resourceRoot.getRootName().equals("classes")) {
// hack for dealing with war modules
classesRoot = resourceRoot;
deploymentUnit.putAttachment(WeldAttachments.CLASSES_RESOURCE_ROOT, resourceRoot);
} else {
VirtualFile beansXml = resourceRoot.getRoot().getChild(META_INF_BEANS_XML);
if (beansXml.exists() && beansXml.isFile()) {
WeldLogger.DEPLOYMENT_LOGGER.debugf("Found beans.xml: %s", beansXml.toString());
beanArchiveMetadata.put(resourceRoot, new ExplicitBeanArchiveMetadata(beansXml, resourceRoot, parseBeansXml(beansXml, parser, deploymentUnit), false));
}
}
}
}
if (DeploymentTypeMarker.isType(DeploymentType.WAR, deploymentUnit)) {
final VirtualFile rootBeansXml = deploymentRoot.getRoot().getChild(WEB_INF_BEANS_XML);
final boolean rootBeansXmlPresent = rootBeansXml.exists() && rootBeansXml.isFile();
VirtualFile beansXml = null;
if (classesRoot != null) {
beansXml = classesRoot.getRoot().getChild(META_INF_BEANS_XML);
}
final boolean beansXmlPresent = beansXml != null && beansXml.exists() && beansXml.isFile();
if (rootBeansXmlPresent) {
if (beansXmlPresent) {
// warn that it is not portable to use both locations at the same time
WeldLogger.DEPLOYMENT_LOGGER.duplicateBeansXml();
beanArchiveMetadata.put(deploymentRoot, new ExplicitBeanArchiveMetadata(rootBeansXml, beansXml, classesRoot, parseBeansXml(rootBeansXml, parser, deploymentUnit), true));
} else {
WeldLogger.DEPLOYMENT_LOGGER.debugf("Found beans.xml: %s", rootBeansXml);
beanArchiveMetadata.put(deploymentRoot, new ExplicitBeanArchiveMetadata(rootBeansXml, classesRoot, parseBeansXml(rootBeansXml, parser, deploymentUnit), true));
}
} else if (beansXmlPresent) {
WeldLogger.DEPLOYMENT_LOGGER.debugf("Found beans.xml: %s", beansXml);
beanArchiveMetadata.put(deploymentRoot, new ExplicitBeanArchiveMetadata(beansXml, classesRoot, parseBeansXml(beansXml, parser, deploymentUnit), true));
}
} else if (!DeploymentTypeMarker.isType(DeploymentType.EAR, deploymentUnit)) {
final VirtualFile rootBeansXml = deploymentRoot.getRoot().getChild(META_INF_BEANS_XML);
if (rootBeansXml.exists() && rootBeansXml.isFile()) {
WeldLogger.DEPLOYMENT_LOGGER.debugf("Found beans.xml: %s", rootBeansXml.toString());
beanArchiveMetadata.put(deploymentRoot, new ExplicitBeanArchiveMetadata(rootBeansXml, deploymentRoot, parseBeansXml(rootBeansXml, parser, deploymentUnit), true));
}
}
if (!beanArchiveMetadata.isEmpty()) {
ExplicitBeanArchiveMetadataContainer deploymentMetadata = new ExplicitBeanArchiveMetadataContainer(beanArchiveMetadata);
deploymentUnit.putAttachment(ExplicitBeanArchiveMetadataContainer.ATTACHMENT_KEY, deploymentMetadata);
for (Iterator<Entry<ResourceRoot, ExplicitBeanArchiveMetadata>> iterator = beanArchiveMetadata.entrySet().iterator(); iterator.hasNext(); ) {
if (BeanDiscoveryMode.NONE != iterator.next().getValue().getBeansXml().getBeanDiscoveryMode()) {
// mark the deployment as requiring CDI integration as long as it contains at least one bean archive with bean-discovery-mode other than "none"
WeldDeploymentMarker.mark(deploymentUnit);
break;
}
}
}
}
@Override
public void undeploy(DeploymentUnit deploymentUnit) {
deploymentUnit.removeAttachment(WeldAttachments.CLASSES_RESOURCE_ROOT);
deploymentUnit.removeAttachment(ExplicitBeanArchiveMetadataContainer.ATTACHMENT_KEY);
}
private BeansXml parseBeansXml(VirtualFile beansXmlFile, PropertyReplacingBeansXmlParser parser, final DeploymentUnit deploymentUnit) throws DeploymentUnitProcessingException {
try {
return parser.parse(beansXmlFile.asFileURL());
} catch (MalformedURLException e) {
throw WeldLogger.ROOT_LOGGER.couldNotGetBeansXmlAsURL(beansXmlFile.toString(), e);
} catch (RuntimeException e) {
throw new DeploymentUnitProcessingException(e);
}
}
}