Skip to content
Browse files

AS7-5966 Add support for creating CDI beans from modules outside the …

…deployment
  • Loading branch information...
1 parent 98e3ac4 commit d252522bc58a3d30e01828ddf55eb92cb81c99eb @stuartwdouglas stuartwdouglas committed with bstansberry
View
1 server/src/main/java/org/jboss/as/server/deployment/Phase.java
@@ -390,6 +390,7 @@ public Phase next() {
public static final int POST_MODULE_VALIDATOR_FACTORY = 0x0B00;
public static final int POST_MODULE_EAR_DEPENDENCY = 0x0C00;
public static final int POST_MODULE_WELD_BEAN_ARCHIVE = 0x0D00;
+ public static final int POST_MODULE_WELD_EXTERNAL_BEAN_ARCHIVE = 0x0D50;
public static final int POST_MODULE_WELD_PORTABLE_EXTENSIONS = 0x0E00;
// should come before ejb jndi bindings processor
public static final int POST_MODULE_EJB_IMPLICIT_NO_INTERFACE_VIEW = 0x1000;
View
1 server/src/main/java/org/jboss/as/server/deployment/module/ManifestDependencyProcessor.java
@@ -108,6 +108,7 @@ public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentU
final ModuleDependency dependency = new ModuleDependency(dependencyLoader, dependencyId, optional, export, services, true);
if(metaInf) {
dependency.addImportFilter(PathFilters.getMetaInfSubdirectoriesFilter(), true);
+ dependency.addImportFilter(PathFilters.getMetaInfFilter(), true);
}
deploymentUnit.addToAttachmentList(Attachments.MANIFEST_DEPENDENCIES, dependency);
}
View
32 ...on/basic/src/test/java/org/jboss/as/test/integration/weld/multideployment/SimpleBean.java
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.integration.weld.multideployment;
+
+import javax.inject.Named;
+
+/**
+ * @author Stuart Douglas
+ */
+@Named
+public class SimpleBean {
+}
View
78 .../java/org/jboss/as/test/integration/weld/multideployment/WeldCrossDeploymentTestCase.java
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.integration.weld.multideployment;
+
+import javax.inject.Inject;
+import javax.persistence.NoResultException;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.as.test.integration.weld.jpa.CdiJpaInjectingBean;
+import org.jboss.as.test.integration.weld.jpa.Employee;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Weld cross deployment injection test case. Verifies that weld can read beans.xml and scan classes outside the
+ * deployment.
+ *
+ * @author Stuart Douglas
+ */
+@RunWith(Arquillian.class)
+public class WeldCrossDeploymentTestCase {
+
+
+
+ @Deployment(name = "d1", order = 1, testable = false)
+ public static Archive<?> deploy() {
+ JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "d1.jar");
+ jar.addClasses(SimpleBean.class);
+ jar.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ return jar;
+ }
+
+ @Deployment(name = "d2", order = 2)
+ public static Archive<?> deploy2() {
+ JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "d2.jar");
+ jar.addClass(WeldCrossDeploymentTestCase.class);
+ jar.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ jar.addAsManifestResource(new StringAsset("Dependencies: deployment.d1.jar meta-inf\n"), "MANIFEST.MF");
+ return jar;
+ }
+
+ @Inject
+ private SimpleBean bean;
+
+ @Test
+ @OperateOnDeployment("d2")
+ public void testSimpleBeanInjected() throws Exception {
+ Assert.assertNotNull(bean);
+ }
+}
View
168 ...java/org/jboss/as/test/integration/weld/multideployment/WeldModuleDeploymentTestCase.java
@@ -0,0 +1,168 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.integration.weld.multideployment;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.as.arquillian.api.ServerSetup;
+import org.jboss.as.arquillian.container.ManagementClient;
+import org.jboss.as.test.integration.management.base.AbstractMgmtServerSetupTask;
+import org.jboss.dmr.ModelNode;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xnio.IoUtils;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+
+/**
+ * Tests that beans definied in a static can be used by a deployment
+ *
+ * @author Stuart Douglas
+ */
+@RunWith(Arquillian.class)
+public class WeldModuleDeploymentTestCase {
+
+ public static void doSetup() throws Exception {
+ File testModuleRoot = new File(getModulePath(), "org/jboss/test/weldModule");
+ deleteRecursively(testModuleRoot);
+ createTestModule(testModuleRoot);
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ File testModuleRoot = new File(getModulePath(), "org/jboss/test/weldModule");
+ deleteRecursively(testModuleRoot);
+ }
+
+ private static void deleteRecursively(File file) {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ for (String name : file.list()) {
+ deleteRecursively(new File(file, name));
+ }
+ }
+ file.delete();
+ }
+ }
+
+ private static void createTestModule(File testModuleRoot) throws IOException {
+ if (testModuleRoot.exists()) {
+ throw new IllegalArgumentException(testModuleRoot + " already exists");
+ }
+ File file = new File(testModuleRoot, "main");
+ if (!file.mkdirs()) {
+ throw new IllegalArgumentException("Could not create " + file);
+ }
+
+ URL url = WeldModuleDeploymentTestCase.class.getResource("module.xml");
+ if (url == null) {
+ throw new IllegalStateException("Could not find module.xml");
+ }
+ copyFile(new File(file, "module.xml"), url.openStream());
+
+ JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "weldTest.jar");
+ jar.addClasses(SimpleBean.class);
+ jar.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ FileOutputStream jarFile = new FileOutputStream(new File(file, "weldTest.jar"));
+ try {
+ jar.as(ZipExporter.class).exportTo(jarFile);
+ } finally {
+ jarFile.flush();
+ jarFile.close();
+ }
+
+ }
+
+ private static void copyFile(File target, InputStream src) throws IOException {
+ final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target));
+ try {
+ int i = src.read();
+ while (i != -1) {
+ out.write(i);
+ i = src.read();
+ }
+ } finally {
+ IoUtils.safeClose(out);
+ }
+ }
+
+ private static File getModulePath() {
+ String modulePath = System.getProperty("module.path", null);
+ if (modulePath == null) {
+ String jbossHome = System.getProperty("jboss.home", null);
+ if (jbossHome == null) {
+ throw new IllegalStateException("Neither -Dmodule.path nor -Djboss.home were set");
+ }
+ modulePath = jbossHome + File.separatorChar + "modules";
+ } else {
+ modulePath = modulePath.split(File.pathSeparator)[0];
+ }
+ File moduleDir = new File(modulePath);
+ if (!moduleDir.exists()) {
+ throw new IllegalStateException("Determined module path does not exist");
+ }
+ if (!moduleDir.isDirectory()) {
+ throw new IllegalStateException("Determined module path is not a dir");
+ }
+ return moduleDir;
+ }
+
+
+ @Deployment
+ public static Archive<?> deploy2() throws Exception {
+ doSetup();
+ JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "d2.jar");
+ jar.addClasses(WeldModuleDeploymentTestCase.class);
+ jar.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ jar.addAsManifestResource(new StringAsset("Dependencies: org.jboss.test.weldModule meta-inf\n"), "MANIFEST.MF");
+ return jar;
+ }
+
+ @Inject
+ private SimpleBean bean;
+
+ @Test
+ public void testSimpleBeanInjected() throws Exception {
+ Assert.assertNotNull(bean);
+ }
+}
View
42 ...gration/basic/src/test/java/org/jboss/as/test/integration/weld/multideployment/module.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2010, Red Hat, Inc., and individual contributors
+ ~ as indicated by the @author tags. See the copyright.txt file 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.
+ -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.jboss.test.weldModule">
+
+ <resources>
+ <resource-root path="weldTest.jar"/>
+ <!-- Insert resources here -->
+ </resources>
+
+ <dependencies>
+ <module name="javax.api"/>
+ <module name="javax.resource.api"/>
+ <module name="javax.enterprise.api"/>
+ <module name="javax.inject.api"/>
+
+ <module name="javax.validation.api"/>
+ <module name="org.hibernate.validator"/>
+ <module name="javax.xml.stream.api"/>
+ </dependencies>
+</module>
View
13 weld/src/main/java/org/jboss/as/weld/WeldLogger.java
@@ -22,6 +22,7 @@
package org.jboss.as.weld;
+import java.io.IOException;
import java.lang.reflect.Member;
import java.net.URL;
@@ -110,4 +111,16 @@
@LogMessage(level = Logger.Level.ERROR)
@Message(value = "Exception tearing down thread state", id = 16013)
void exceptionClearingThreadState(@Cause Exception e);
+
+ @LogMessage(level = Logger.Level.ERROR)
+ @Message(value = "Error loading file %s", id = 16014)
+ void errorLoadingFile(String newPath);
+
+ @LogMessage(level = Logger.Level.ERROR)
+ @Message(value = "Could not read entries", id = 16015)
+ void couldNotReadEntries(@Cause IOException ioe);
+
+ @LogMessage(level = Logger.Level.WARN)
+ @Message(value = "URL scanner does not understand the URL protocol %s, CDI beans will not be scanned.", id = 16016)
+ void doNotUnderstandProtocol(URL url);
}
View
4 weld/src/main/java/org/jboss/as/weld/WeldSubsystemAdd.java
@@ -33,6 +33,7 @@
import org.jboss.as.weld.deployment.CdiAnnotationProcessor;
import org.jboss.as.weld.deployment.processors.BeanArchiveProcessor;
import org.jboss.as.weld.deployment.processors.BeansXmlProcessor;
+import org.jboss.as.weld.deployment.processors.ExternalBeanArchiveProcessor;
import org.jboss.as.weld.deployment.processors.WebIntegrationProcessor;
import org.jboss.as.weld.deployment.processors.WeldBeanManagerServiceProcessor;
import org.jboss.as.weld.deployment.processors.WeldComponentIntegrationProcessor;
@@ -61,11 +62,12 @@ protected void populateModel(ModelNode operation, ModelNode model) {
protected void performBoottime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) {
context.addStep(new AbstractDeploymentChainStep() {
protected void execute(DeploymentProcessorTarget processorTarget) {
- processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, Phase.DEPENDENCIES_WELD, new WeldDependencyProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.PARSE, Phase.PARSE_CDI_ANNOTATIONS, new CdiAnnotationProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.PARSE, Phase.PARSE_WELD_DEPLOYMENT, new BeansXmlProcessor());
+ processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, Phase.DEPENDENCIES_WELD, new WeldDependencyProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.POST_MODULE, Phase.POST_MODULE_WELD_WEB_INTEGRATION, new WebIntegrationProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.POST_MODULE, Phase.POST_MODULE_WELD_BEAN_ARCHIVE, new BeanArchiveProcessor());
+ processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.POST_MODULE, Phase.POST_MODULE_WELD_EXTERNAL_BEAN_ARCHIVE, new ExternalBeanArchiveProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.POST_MODULE, Phase.POST_MODULE_WELD_PORTABLE_EXTENSIONS, new WeldPortableExtensionProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.POST_MODULE, Phase.POST_MODULE_WELD_COMPONENT_INTEGRATION, new WeldComponentIntegrationProcessor());
processorTarget.addDeploymentProcessor(WeldExtension.SUBSYSTEM_NAME, Phase.INSTALL, Phase.INSTALL_WELD_DEPLOYMENT, new WeldDeploymentProcessor());
View
181 weld/src/main/java/org/jboss/as/weld/deployment/UrlScanner.java
@@ -0,0 +1,181 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import org.jboss.as.weld.WeldLogger;
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UrlScanner {
+
+
+ public boolean handleBeansXml(final URL url, final List<String> discoveredClasses) {
+ String urlPath = url.toExternalForm();
+
+ // determin resource type (eg: jar, file, bundle)
+ String urlType = "file";
+ int colonIndex = urlPath.indexOf(":");
+ if (colonIndex != -1) {
+ urlType = urlPath.substring(0, colonIndex);
+ }
+
+ // Extra built-in support for simple file-based resources
+ if ("file".equals(urlType) || "jar".equals(urlType)) {
+ // switch to using getPath() instead of toExternalForm()
+ urlPath = url.getPath();
+
+ if (urlPath.indexOf('!') > 0) {
+ urlPath = urlPath.substring(0, urlPath.indexOf('!'));
+ } else {
+ // hack for /META-INF/beans.xml
+ File dirOrArchive = new File(urlPath);
+ dirOrArchive = dirOrArchive.getParentFile();
+ urlPath = dirOrArchive.getParent();
+ }
+
+ try {
+ urlPath = URLDecoder.decode(urlPath, "UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ throw new RuntimeException(ex);
+ }
+ handle(urlPath, discoveredClasses);
+ return true;
+ } else if ("vfs".equals(urlType)) {
+ try {
+ VirtualFile vfsRoot = VFS.getChild(url).getParent().getParent();
+ handle(vfsRoot, discoveredClasses);
+ return true;
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ WeldLogger.DEPLOYMENT_LOGGER.doNotUnderstandProtocol(url);
+ return false;
+ }
+ }
+
+ private void handle(VirtualFile urlPath, List<String> discoveredClasses) {
+ WeldLogger.DEPLOYMENT_LOGGER.tracef("scanning: %s", urlPath);
+ handleDirectory(urlPath, null, discoveredClasses);
+ }
+
+ private void handle(String urlPath, List<String> discoveredClasses) {
+ try {
+ WeldLogger.DEPLOYMENT_LOGGER.tracef("scanning: %s", urlPath);
+
+ if (urlPath.startsWith("file:")) {
+ urlPath = urlPath.substring(5);
+ }
+ if (urlPath.indexOf('!') > 0) {
+ urlPath = urlPath.substring(0, urlPath.indexOf('!'));
+ }
+
+ File file = new File(urlPath);
+ if (file.isDirectory()) {
+ handleDirectory(file, null, discoveredClasses);
+ } else {
+ handleArchiveByFile(file, discoveredClasses);
+ }
+ } catch (IOException ioe) {
+ WeldLogger.DEPLOYMENT_LOGGER.couldNotReadEntries(ioe);
+ }
+ }
+
+ private void handleArchiveByFile(File file, List<String> discoveredClasses) throws IOException {
+ try {
+ WeldLogger.DEPLOYMENT_LOGGER.trace("archive: " + file);
+
+ String archiveUrl = "jar:" + file.toURI().toURL().toExternalForm() + "!/";
+ ZipFile zip = new ZipFile(file);
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ String name = entry.getName();
+ handleFile(name, discoveredClasses);
+ }
+ } catch (ZipException e) {
+ throw new RuntimeException("Error handling file " + file, e);
+ }
+ }
+
+ private void handleDirectory(File file, String path, List<String> discoveredClasses) {
+
+ WeldLogger.DEPLOYMENT_LOGGER.tracef("handling directory: %s", file);
+
+ for (File child : file.listFiles()) {
+ String newPath = (path == null) ? child.getName() : (path + '/' + child.getName());
+
+ if (child.isDirectory()) {
+ handleDirectory(child, newPath, discoveredClasses);
+ } else {
+ handleFile(newPath, discoveredClasses);
+ }
+ }
+ }
+
+ private void handleDirectory(VirtualFile file, String path, List<String> discoveredClasses) {
+
+
+ WeldLogger.DEPLOYMENT_LOGGER.tracef("handling directory: %s", file);
+
+ for (VirtualFile child : file.getChildren()) {
+ String newPath = (path == null) ? child.getName() : (path + '/' + child.getName());
+
+ if (child.isDirectory()) {
+ handleDirectory(child, newPath, discoveredClasses);
+ } else {
+ handleFile(newPath, discoveredClasses);
+ }
+ }
+ }
+
+ protected void handleFile(String name, List<String> discoveredClasses) {
+ if (name.endsWith(".class")) {
+ discoveredClasses.add(filenameToClassname(name));
+ }
+ }
+
+ /**
+ * Convert a path to a class file to a class name
+ */
+ public static String filenameToClassname(String filename) {
+ return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
+ }
+}
View
10 weld/src/main/java/org/jboss/as/weld/deployment/WeldAttachments.java
@@ -41,6 +41,16 @@
public static final AttachmentKey<BeanDeploymentModule> BEAN_DEPLOYMENT_MODULE = AttachmentKey.create(BeanDeploymentModule.class);
/**
+ * top level list of all additional bean deployment modules
+ */
+ public static final AttachmentKey<AttachmentList<BeanDeploymentModule>> ADDITIONAL_BEAN_DEPLOYMENT_MODULES = AttachmentKey.createList(BeanDeploymentModule.class);
+
+ /**
+ * per DU list of all visible additional BDM's
+ */
+ public static final AttachmentKey<AttachmentList<BeanDeploymentModule>> VISIBLE_ADDITIONAL_BEAN_DEPLOYMENT_MODULE = AttachmentKey.createList(BeanDeploymentModule.class);
+
+ /**
* The {@link BeanDeploymentArchiveImpl} that corresponds to the main resource root of a deployment or sub deployment. For
* consistency, the bean manager that corresponds to this bda is always bound to the java:comp namespace for web modules.
*/
View
167 weld/src/main/java/org/jboss/as/weld/deployment/processors/ExternalBeanArchiveProcessor.java
@@ -0,0 +1,167 @@
+/*
+ * 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.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.as.ee.structure.SpecDescriptorPropertyReplacement;
+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.reflect.DeploymentReflectionIndex;
+import org.jboss.as.weld.WeldDeploymentMarker;
+import org.jboss.as.weld.WeldLogger;
+import org.jboss.as.weld.deployment.BeanArchiveMetadata;
+import org.jboss.as.weld.deployment.BeanDeploymentArchiveImpl;
+import org.jboss.as.weld.deployment.BeanDeploymentModule;
+import org.jboss.as.weld.deployment.BeansXmlParser;
+import org.jboss.as.weld.deployment.UrlScanner;
+import org.jboss.as.weld.deployment.WeldAttachments;
+import org.jboss.as.weld.deployment.WeldDeploymentMetadata;
+import org.jboss.as.weld.services.bootstrap.WeldJpaInjectionServices;
+import org.jboss.modules.Module;
+import org.jboss.weld.bootstrap.spi.BeansXml;
+import org.jboss.weld.injection.spi.JpaInjectionServices;
+
+/**
+ * Deployment processor that builds bean archives from external deployments.
+ * <p/>
+ * This is only run at the top level, as multiple sub deployments can reference the same
+ * beans.xml information, so we have to iterate through all bean deployment archives in this processor, to prevent
+ * beans.xml from being potentially parsed twice.
+ * <p/>
+ *
+ * @author Stuart Douglas
+ */
+public class ExternalBeanArchiveProcessor implements DeploymentUnitProcessor {
+
+ 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();
+ final WeldDeploymentMetadata cdiDeploymentMetadata = deploymentUnit
+ .getAttachment(WeldDeploymentMetadata.ATTACHMENT_KEY);
+ final DeploymentReflectionIndex reflectionIndex = deploymentUnit.getAttachment(Attachments.REFLECTION_INDEX);
+
+ if (!WeldDeploymentMarker.isPartOfWeldDeployment(deploymentUnit)) {
+ return;
+ }
+
+ if (deploymentUnit.getParent() != null) {
+ return;
+ }
+
+ final String beanArchiveIdPrefix = deploymentUnit.getName() + ".external.";
+
+ final List<DeploymentUnit> deploymentUnits = new ArrayList<DeploymentUnit>();
+ deploymentUnits.add(deploymentUnit);
+ deploymentUnits.addAll(deploymentUnit.getAttachmentList(Attachments.SUB_DEPLOYMENTS));
+
+ BeansXmlParser parser = new BeansXmlParser();
+
+ final Map<URL, List<DeploymentUnit>> deploymentUnitMap = new HashMap<URL, List<DeploymentUnit>>();
+
+ final HashSet<URL> existing = new HashSet<URL>();
+
+ for (DeploymentUnit deployment : deploymentUnits) {
+ try {
+ final WeldDeploymentMetadata weldDeploymentMetadata = deployment.getAttachment(WeldDeploymentMetadata.ATTACHMENT_KEY);
+ if (weldDeploymentMetadata != null) {
+ for (BeanArchiveMetadata md : weldDeploymentMetadata.getBeanArchiveMetadata()) {
+ URL file = md.getBeansXmlFile().toURL();
+ existing.add(file);
+ }
+ }
+ } catch (MalformedURLException e) {
+ throw new DeploymentUnitProcessingException(e);
+ }
+ }
+
+ for (DeploymentUnit deployment : deploymentUnits) {
+ final Module module = deployment.getAttachment(Attachments.MODULE);
+ if (module == null) {
+ return;
+ }
+ try {
+ Enumeration<URL> resources = module.getClassLoader().getResources(META_INF_BEANS_XML);
+ while (resources.hasMoreElements()) {
+ final URL beansXml = resources.nextElement();
+ if (existing.contains(beansXml)) {
+ continue;
+ }
+ WeldLogger.DEPLOYMENT_LOGGER.debugf("Found external beans.xml: %s", beansXml.toString());
+ List<DeploymentUnit> dus = deploymentUnitMap.get(beansXml);
+ if (dus == null) {
+ deploymentUnitMap.put(beansXml, dus = new ArrayList<DeploymentUnit>());
+ }
+ dus.add(deployment);
+ }
+ } catch (IOException e) {
+ throw new DeploymentUnitProcessingException(e);
+ }
+ }
+
+ for (final Map.Entry<URL, List<DeploymentUnit>> entry : deploymentUnitMap.entrySet()) {
+ //we just take the first module, it should not make any difference. The idea that
+ //the same beans.xml is accessible via two different CL's is not something we can deal with
+ final Module module = entry.getValue().get(0).getAttachment(Attachments.MODULE);
+ final BeansXml beansXml = parseBeansXml(entry.getKey(), parser, deploymentUnit);
+
+ final UrlScanner urlScanner = new UrlScanner();
+ final List<String> discoveredClasses = new ArrayList<String>();
+ if(!urlScanner.handleBeansXml(entry.getKey(), discoveredClasses)) {
+ continue;
+ }
+
+ final BeanDeploymentArchiveImpl bda = new BeanDeploymentArchiveImpl(new HashSet<String>(discoveredClasses), beansXml, module, beanArchiveIdPrefix + entry.getKey().toExternalForm());
+
+ final BeanDeploymentModule bdm = new BeanDeploymentModule(Collections.singleton(bda));
+ final JpaInjectionServices jpaInjectionServices = new WeldJpaInjectionServices(deploymentUnit, deploymentUnit.getServiceRegistry());
+ bdm.addService(JpaInjectionServices.class, jpaInjectionServices);
+ deploymentUnit.addToAttachmentList(WeldAttachments.ADDITIONAL_BEAN_DEPLOYMENT_MODULES, bdm);
+ for (DeploymentUnit du : entry.getValue()) {
+ du.addToAttachmentList(WeldAttachments.VISIBLE_ADDITIONAL_BEAN_DEPLOYMENT_MODULE, bdm);
+ }
+ }
+ }
+
+ @Override
+ public void undeploy(DeploymentUnit context) {
+
+ }
+
+ private BeansXml parseBeansXml(URL beansXmlFile, BeansXmlParser parser, final DeploymentUnit deploymentUnit) throws DeploymentUnitProcessingException {
+ return parser.parse(beansXmlFile, SpecDescriptorPropertyReplacement.propertyReplacer(deploymentUnit));
+ }
+}
View
24 weld/src/main/java/org/jboss/as/weld/deployment/processors/WeldDeploymentProcessor.java
@@ -141,6 +141,12 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro
final EEApplicationDescription eeApplicationDescription = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_APPLICATION_DESCRIPTION);
bdmsByIdentifier.put(module.getIdentifier(), rootBeanDeploymentModule);
+
+ for(final BeanDeploymentModule additional : deploymentUnit.getAttachmentList(WeldAttachments.VISIBLE_ADDITIONAL_BEAN_DEPLOYMENT_MODULE)) {
+ additional.addBeanDeploymentModule(rootBeanDeploymentModule);
+ rootBeanDeploymentModule.addBeanDeploymentModule(additional);
+ }
+
moduleSpecByIdentifier.put(module.getIdentifier(), moduleSpecification);
beanDeploymentArchives.addAll(rootBeanDeploymentModule.getBeanDeploymentArchives());
@@ -166,12 +172,18 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro
// add the modules bdas to the global set of bdas
beanDeploymentArchives.addAll(bdm.getBeanDeploymentArchives());
bdmsByIdentifier.put(subDeploymentModule.getIdentifier(), bdm);
+ List<BeanDeploymentModule> additionalModules = subDeployment.getAttachmentList(WeldAttachments.VISIBLE_ADDITIONAL_BEAN_DEPLOYMENT_MODULE);
moduleSpecByIdentifier.put(subDeploymentModule.getIdentifier(), subDeploymentModuleSpec);
//we have to do this here as the aggregate components are not available in earlier phases
final ResourceRoot subDeploymentRoot = subDeployment.getAttachment(Attachments.DEPLOYMENT_ROOT);
final EjbInjectionServices ejbInjectionServices = new WeldEjbInjectionServices(deploymentUnit.getServiceRegistry(), eeModuleDescription, eeApplicationDescription, subDeploymentRoot.getRoot());
bdm.addService(EjbInjectionServices.class, ejbInjectionServices);
+ for(final BeanDeploymentModule additional : additionalModules) {
+ additional.addBeanDeploymentModule(bdm);
+ bdm.addBeanDeploymentModule(additional);bdm.addService(EjbInjectionServices.class, ejbInjectionServices);
+ }
+
}
for (Map.Entry<ModuleIdentifier, BeanDeploymentModule> entry : bdmsByIdentifier.entrySet()) {
@@ -188,6 +200,15 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro
}
}
+ final EjbInjectionServices ejbInjectionServices = new WeldEjbInjectionServices(deploymentUnit.getServiceRegistry(), eeModuleDescription, eeApplicationDescription, deploymentRoot.getRoot());
+
+ rootBeanDeploymentModule.addService(EjbInjectionServices.class, ejbInjectionServices);
+
+ for(final BeanDeploymentModule additional : deploymentUnit.getAttachmentList(WeldAttachments.ADDITIONAL_BEAN_DEPLOYMENT_MODULES)) {
+ beanDeploymentArchives.addAll(additional.getBeanDeploymentArchives());
+ additional.addService(EjbInjectionServices.class, ejbInjectionServices);
+ }
+
final List<Metadata<Extension>> extensions = deploymentUnit.getAttachmentList(WeldAttachments.PORTABLE_EXTENSIONS);
final WeldDeployment deployment = new WeldDeployment(beanDeploymentArchives, extensions, module, subDeploymentLoaders);
@@ -197,10 +218,7 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro
//TODO: we need to change weld so this is a per-BDA service
final ValidatorFactory factory = deploymentUnit.getAttachment(BeanValidationAttachments.VALIDATOR_FACTORY);
weldBootstrapService.addWeldService(ValidationServices.class, new WeldValidationServices(factory));
-
- final EjbInjectionServices ejbInjectionServices = new WeldEjbInjectionServices(deploymentUnit.getServiceRegistry(), eeModuleDescription, eeApplicationDescription, deploymentRoot.getRoot());
weldBootstrapService.addWeldService(EjbInjectionServices.class, ejbInjectionServices);
- rootBeanDeploymentModule.addService(EjbInjectionServices.class, ejbInjectionServices);
weldBootstrapService.addWeldService(EjbServices.class, new WeldEjbServices(deploymentUnit.getServiceRegistry()));

0 comments on commit d252522

Please sign in to comment.
Something went wrong with that request. Please try again.