You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2015/05/25 07:03:45 UTC
[3/5] tomee git commit: getting rid of the version in arquilian
openejb embedded adapter
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/WARArquillianTest.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/WARArquillianTest.java b/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/WARArquillianTest.java
deleted file mode 100644
index dccd95e..0000000
--- a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/WARArquillianTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openejb.arquillian.openejb;
-
-import org.apache.openejb.loader.SystemInstance;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.junit.Arquillian;
-import org.jboss.shrinkwrap.api.ArchivePaths;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import javax.inject.Inject;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-@RunWith(Arquillian.class)
-public class WARArquillianTest {
- @Inject
- private ABean bean;
-
- @Deployment
- public static WebArchive archive() {
- return ShrinkWrap.create(WebArchive.class, WARArquillianTest.class.getSimpleName().concat(".war"))
- .addClasses(ABean.class)
- .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("classes/META-INF/beans.xml"));
- }
-
- @Test
- public void checkItIsStarted() {
- assertTrue(SystemInstance.isInitialized());
- }
-
- @Test
- public void checkInjections() {
- assertNotNull(bean);
- }
-
- public static class ABean {}
-}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive.java b/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive.java
deleted file mode 100644
index c20984b..0000000
--- a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openejb.arquillian.openejb.archive;
-
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-
-import javax.annotation.PostConstruct;
-import javax.ejb.Singleton;
-import javax.ejb.Startup;
-
-public final class SimpleArchive {
- private SimpleArchive() {
- // no-op
- }
-
- @Deployment
- public static WebArchive war() {
- return ShrinkWrap.create(WebArchive.class, "start.war")
- .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
- .addClass(ASingleton.class);
- }
-
- @Startup
- @Singleton
- public static class ASingleton {
- public static boolean ok = false;
-
- @PostConstruct
- public void init() {
- ok = true;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive2.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive2.java b/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive2.java
deleted file mode 100644
index 3a99937..0000000
--- a/arquillian/arquillian-openejb-embedded-5/src/test/java/org/apache/openejb/arquillian/openejb/archive/SimpleArchive2.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openejb.arquillian.openejb.archive;
-
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-
-import javax.ejb.Singleton;
-
-public final class SimpleArchive2 {
- private SimpleArchive2() {
- // no-op
- }
-
- @Deployment
- public static WebArchive war() {
- return ShrinkWrap.create(WebArchive.class, "start2.war")
- .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
- .addClass(AnotherSingleton.class);
- }
-
- @Singleton
- public static class AnotherSingleton {}
-}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded-5/src/test/resources/a-pom.xml
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/test/resources/a-pom.xml b/arquillian/arquillian-openejb-embedded-5/src/test/resources/a-pom.xml
deleted file mode 100644
index bfdfea2..0000000
--- a/arquillian/arquillian-openejb-embedded-5/src/test/resources/a-pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>fake</groupId>
- <version>fake</version>
- <artifactId>fake</artifactId>
-
- <dependencies>
- <dependency> <!-- whatever it is, just to check we can use it -->
- <groupId>info.cukes</groupId>
- <artifactId>gherkin</artifactId>
- <version>2.11.0</version>
- </dependency>
- </dependencies>
-</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded-5/src/test/resources/arquillian.xml
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/test/resources/arquillian.xml b/arquillian/arquillian-openejb-embedded-5/src/test/resources/arquillian.xml
deleted file mode 100644
index 463d72c..0000000
--- a/arquillian/arquillian-openejb-embedded-5/src/test/resources/arquillian.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<arquillian
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
- <container qualifier="openejb" default="true">
- <configuration>
- <property name="properties">
- # used to not have a single DataSource and be able to test the resource resolution
- db1 = new://Resource?type=DataSource
- db1.JdbcUrl = jdbc:hsqldb:mem:db1
-
- java\:global/db = new://Resource?type=DataSource
- java\:global/db.JdbcUrl = jdbc:hsqldb:mem:global
-
- # to check startup deployment
- openejb.arquillian.predeploy-archives = org.apache.openejb.arquillian.openejb.archive.[SimpleArchive|SimpleArchive2]
- </property>
- </configuration>
- </container>
-</arquillian>
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/pom.xml
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/pom.xml b/arquillian/arquillian-openejb-embedded/pom.xml
new file mode 100644
index 0000000..1cc2da7
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/pom.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>arquillian</artifactId>
+ <groupId>org.apache.tomee</groupId>
+ <version>7.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>arquillian-openejb-embedded</artifactId>
+ <name>OpenEJB :: Arquillian Adaptors Parent :: OpenEJB Container</name>
+ <version>7.0.0-SNAPSHOT</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-core</artifactId>
+ <version>${openejb.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-spi</artifactId>
+ <version>${version.arquillian}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>shrinkwrap-descriptors-spi</artifactId>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>shrinkwrap-descriptors-api-base</artifactId>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ <artifactId>shrinkwrap-descriptors-spi</artifactId>
+ <version>${version.shrinkwrap.descriptor}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ <artifactId>shrinkwrap-descriptors-api-base</artifactId>
+ <version>${version.shrinkwrap.descriptor}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-test-spi</artifactId>
+ <version>${version.arquillian}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${version.arquillian}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>shrinkwrap-descriptors-spi</artifactId>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ <artifactId>shrinkwrap-descriptors-impl-javaee</artifactId>
+ <version>${version.shrinkwrap.descriptor}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ <artifactId>shrinkwrap-descriptors-api-javaee</artifactId>
+ <version>${version.shrinkwrap.descriptor}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-api</artifactId>
+ <version>${version.shrinkwrap.shrinkwrap}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-impl-base</artifactId>
+ <version>${version.shrinkwrap.shrinkwrap}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+ <version>2.0.0</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-common</artifactId>
+ <version>${tomee.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-openejb-transaction-provider</artifactId>
+ <version>${tomee.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>hamcrest-core</artifactId>
+ <groupId>org.hamcrest</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>info.cukes</groupId>
+ <artifactId>cucumber-core</artifactId>
+ <version>1.1.8</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency> <!-- shouldn't be a compile/runtime dependency -->
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-http</artifactId>
+ <version>${openejb.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${openejb.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
new file mode 100644
index 0000000..5d093da
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+
+public class Closeables implements Closeable {
+ private final Collection<Closeable> closeables = new LinkedList<>();
+
+ public synchronized void add(final Closeable closeable) {
+ closeables.add(closeable);
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ for (final Closeable c : closeables) {
+ c.close();
+ }
+ closeables.clear();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
new file mode 100644
index 0000000..1a75a69
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
@@ -0,0 +1,620 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import org.apache.openejb.ClassLoaderUtil;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.OpenEJBRuntimeException;
+import org.apache.openejb.cdi.CompositeBeans;
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.DeploymentLoader;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.config.FinderFactory;
+import org.apache.openejb.config.ReadDescriptors;
+import org.apache.openejb.config.WebModule;
+import org.apache.openejb.config.WebappAggregatedArchive;
+import org.apache.openejb.jee.Beans;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.ManagedBean;
+import org.apache.openejb.jee.TransactionType;
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.jee.WebApp$JAXB;
+import org.apache.openejb.jee.oejb3.EjbDeployment;
+import org.apache.openejb.jee.oejb3.OpenejbJar;
+import org.apache.openejb.loader.IO;
+import org.apache.openejb.sxc.Sxc;
+import org.apache.openejb.util.classloader.URLClassLoaderFirst;
+import org.apache.xbean.finder.archive.ClassesArchive;
+import org.apache.xbean.finder.archive.CompositeArchive;
+import org.apache.xbean.finder.archive.FilteredArchive;
+import org.apache.xbean.finder.archive.JarArchive;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
+import org.jboss.shrinkwrap.api.asset.ArchiveAsset;
+import org.jboss.shrinkwrap.api.asset.Asset;
+import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
+import org.jboss.shrinkwrap.api.asset.FileAsset;
+import org.jboss.shrinkwrap.api.asset.UrlAsset;
+import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.impl.base.filter.IncludeRegExpPaths;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static java.util.Arrays.asList;
+import static org.apache.openejb.arquillian.openejb.reflection.Assets.EMPTY_LOADER;
+import static org.apache.openejb.arquillian.openejb.reflection.Assets.get;
+
+// doesn't implement ApplicationArchiveProcessor anymore since in some cases
+// (with some observers set for instance)
+// it is not called before the deployment itself
+// so it is like if it was skipped
+public class OpenEJBArchiveProcessor {
+ private static final Logger LOGGER = Logger.getLogger(OpenEJBArchiveProcessor.class.getName());
+
+ private static final String META_INF = "META-INF/";
+ private static final String WEB_INF = "WEB-INF/";
+ private static final String EJB_JAR_XML = "ejb-jar.xml";
+
+ private static final String BEANS_XML = "beans.xml";
+ private static final String VALIDATION_XML = "validation.xml";
+ private static final String RESOURCES_XML = "resources.xml";
+ private static final String PERSISTENCE_XML = "persistence.xml";
+ private static final String OPENEJB_JAR_XML = "openejb-jar.xml";
+ private static final String ENV_ENTRIES_PROPERTIES = "env-entries.properties";
+ private static final String WEB_INF_CLASSES = "/WEB-INF/classes/";
+
+ public static AppModule createModule(final Archive<?> archive, final TestClass testClass, final Closeables closeables) {
+ final Class<?> javaClass;
+ if (testClass != null) {
+ javaClass = testClass.getJavaClass();
+ } else {
+ javaClass = null;
+ }
+
+ final ClassLoader parent;
+ if (javaClass == null) {
+ parent = Thread.currentThread().getContextClassLoader();
+ } else {
+ parent = javaClass.getClassLoader();
+ }
+
+ final List<URL> additionalPaths = new ArrayList<>();
+ CompositeArchive scannedArchive = null;
+ final Map<URL, List<String>> earMap = new HashMap<>();
+ final Map<String, Object> altDD = new HashMap<>();
+ final List<Archive> earLibsArchives = new ArrayList<>();
+ final CompositeBeans earBeans = new CompositeBeans();
+
+ final boolean isEar = EnterpriseArchive.class.isInstance(archive);
+ final boolean isWebApp = WebArchive.class.isInstance(archive);
+ final String prefix = isWebApp ? WEB_INF : META_INF;
+ if (isEar || isWebApp) {
+ final Map<ArchivePath, Node> jars = archive.getContent(new IncludeRegExpPaths(isEar ? "/.*\\.jar" : "/WEB-INF/lib/.*\\.jar"));
+ scannedArchive = analyzeLibs(parent, additionalPaths, earMap, earLibsArchives, earBeans, jars, altDD);
+ }
+
+ final URL[] urls = additionalPaths.toArray(new URL[additionalPaths.size()]);
+
+ final URLClassLoaderFirst swParent = new URLClassLoaderFirst(urls, parent);
+ closeables.add(swParent);
+
+ if (!isEar) {
+ earLibsArchives.add(archive);
+ }
+ final SWClassLoader loader = new SWClassLoader(swParent, earLibsArchives.toArray(new Archive<?>[earLibsArchives.size()]));
+ closeables.add(loader);
+ final URLClassLoader tempClassLoader = ClassLoaderUtil.createTempClassLoader(loader);
+ closeables.add(tempClassLoader);
+
+ final AppModule appModule = new AppModule(loader, archive.getName());
+ if (WEB_INF.equals(prefix)) {
+ appModule.setDelegateFirst(false);
+ appModule.setStandloneWebModule();
+
+ final WebModule webModule = new WebModule(createWebApp(archive), contextRoot(archive.getName()), loader, "", appModule.getModuleId());
+ webModule.setUrls(additionalPaths);
+ appModule.getWebModules().add(webModule);
+ } else if (isEar) { // mainly for CDI TCKs
+ final FinderFactory.OpenEJBAnnotationFinder earLibFinder = new FinderFactory.OpenEJBAnnotationFinder(new SimpleWebappAggregatedArchive(tempClassLoader, scannedArchive, earMap));
+ appModule.setEarLibFinder(earLibFinder);
+
+ final EjbModule earCdiModule = new EjbModule(appModule.getClassLoader(), DeploymentLoader.EAR_SCOPED_CDI_BEANS + appModule.getModuleId(), new EjbJar(), new OpenejbJar());
+ earCdiModule.setBeans(earBeans);
+ earCdiModule.setFinder(earLibFinder);
+
+ final EjbJar ejbJar;
+ final AssetSource ejbJarXml = AssetSource.class.isInstance(altDD.get(EJB_JAR_XML)) ? AssetSource.class.cast(altDD.get(EJB_JAR_XML)) : null;
+ if (ejbJarXml != null) {
+ try {
+ ejbJar = ReadDescriptors.readEjbJar(ejbJarXml.get());
+ } catch (final Exception e) {
+ throw new OpenEJBRuntimeException(e);
+ }
+ } else {
+ ejbJar = new EjbJar();
+ }
+
+ earCdiModule.setEjbJar(ejbJar); // EmptyEjbJar would prevent to add scanned EJBs but this is *here* an aggregator so we need to be able to do so
+ appModule.getEjbModules().add(earCdiModule);
+
+ for (final Map.Entry<ArchivePath, Node> node : archive.getContent(new IncludeRegExpPaths("/.*\\.war")).entrySet()) {
+ final Asset asset = node.getValue().getAsset();
+ if (ArchiveAsset.class.isInstance(asset)) {
+ final Archive<?> webArchive = ArchiveAsset.class.cast(asset).getArchive();
+ if (WebArchive.class.isInstance(webArchive)) {
+ final Map<String, Object> webAltDD = new HashMap<>();
+ final Node beansXml = findBeansXml(webArchive, WEB_INF);
+
+ final List<URL> webappAdditionalPaths = new LinkedList<>();
+ final CompositeBeans webAppBeansXml = new CompositeBeans();
+ final List<Archive> webAppArchives = new LinkedList<Archive>();
+ final Map<URL, List<String>> webAppClassesByUrl = new HashMap<URL, List<String>>();
+ final CompositeArchive webAppArchive = analyzeLibs(parent,
+ webappAdditionalPaths, webAppClassesByUrl,
+ webAppArchives, webAppBeansXml,
+ webArchive.getContent(new IncludeRegExpPaths("/WEB-INF/lib/.*\\.jar")),
+ webAltDD);
+
+ webAppArchives.add(webArchive);
+ final SWClassLoader webLoader = new SWClassLoader(parent, webAppArchives.toArray(new Archive<?>[webAppArchives.size()]));
+ closeables.add(webLoader);
+
+ final FinderFactory.OpenEJBAnnotationFinder finder = new FinderFactory.OpenEJBAnnotationFinder(
+ finderArchive(beansXml, webArchive, webLoader, webAppArchive, webAppClassesByUrl, webAppBeansXml));
+
+ final String contextRoot = contextRoot(webArchive.getName());
+ final WebModule webModule = new WebModule(createWebApp(webArchive), contextRoot, webLoader, "", appModule.getModuleId() + "_" + contextRoot);
+ webModule.setUrls(Collections.<URL>emptyList());
+ webModule.setScannableUrls(Collections.<URL>emptyList());
+ webModule.setFinder(finder);
+
+ final EjbJar webEjbJar = createEjbJar(prefix, webArchive);
+
+ final EjbModule ejbModule = new EjbModule(webLoader, webModule.getModuleId(), null, webEjbJar, new OpenejbJar());
+ ejbModule.setBeans(webAppBeansXml);
+ ejbModule.getAltDDs().putAll(webAltDD);
+ ejbModule.getAltDDs().put("beans.xml", webAppBeansXml);
+ ejbModule.setFinder(finder);
+ ejbModule.setClassLoader(webLoader);
+ ejbModule.setWebapp(true);
+
+ appModule.getEjbModules().add(ejbModule);
+ appModule.getWebModules().add(webModule);
+
+ addPersistenceXml(archive, WEB_INF, appModule);
+ addOpenEJbJarXml(archive, WEB_INF, ejbModule);
+ addValidationXml(archive, WEB_INF, new HashMap<String, Object>(), ejbModule);
+ addResourcesXml(archive, WEB_INF, ejbModule);
+ addEnvEntries(archive, WEB_INF, appModule, ejbModule);
+ }
+ }
+ }
+ }
+
+ if (isEar) { // adding the test class as lib class can break test if tested against the web part of the ear
+ addTestClassAsManagedBean(javaClass, tempClassLoader, appModule);
+ return appModule;
+ }
+
+ // add the test as a managed bean to be able to inject into it easily
+ final Map<String, Object> testDD;
+ if (javaClass != null) {
+ final EjbModule testEjbModule = addTestClassAsManagedBean(javaClass, tempClassLoader, appModule);
+ testDD = testEjbModule.getAltDDs();
+ } else {
+ testDD = new HashMap<>(); // ignore
+ }
+
+ final EjbJar ejbJar = createEjbJar(prefix, archive);
+
+ if (ejbJar.getModuleName() == null) {
+ final String name = archive.getName();
+ if (name.endsWith("ar") && name.length() > 4) {
+ ejbJar.setModuleName(name.substring(0, name.length() - ".jar".length()));
+ } else {
+ ejbJar.setModuleName(name);
+ }
+ }
+
+ final EjbModule ejbModule = new EjbModule(ejbJar);
+ ejbModule.setClassLoader(tempClassLoader);
+
+ final Node beansXml = findBeansXml(archive, prefix);
+
+ final FinderFactory.OpenEJBAnnotationFinder finder = new FinderFactory.OpenEJBAnnotationFinder(
+ finderArchive(beansXml, archive, loader, scannedArchive, earMap, earBeans));
+ ejbModule.setFinder(finder);
+ ejbModule.setBeans(earBeans);
+ ejbModule.getAltDDs().put("beans.xml", earBeans);
+
+ if (appModule.isWebapp()) { // war
+ appModule.getWebModules().iterator().next().setFinder(ejbModule.getFinder());
+ }
+ appModule.getEjbModules().add(ejbModule);
+
+ addPersistenceXml(archive, prefix, appModule);
+ addOpenEJbJarXml(archive, prefix, ejbModule);
+ addValidationXml(archive, prefix, testDD, ejbModule);
+ addResourcesXml(archive, prefix, ejbModule);
+ addEnvEntries(archive, prefix, appModule, ejbModule);
+
+ if (!appModule.isWebapp()) {
+ appModule.getAdditionalLibraries().addAll(additionalPaths);
+ }
+
+ if (archive.getName().endsWith(".jar")) { // otherwise global naming will be broken
+ appModule.setStandloneWebModule();
+ }
+ return appModule;
+ }
+
+ private static EjbJar createEjbJar(final String prefix, final Archive<?> webArchive) {
+ final EjbJar webEjbJar;
+ final Node webEjbJarXml = webArchive.get(prefix.concat(EJB_JAR_XML));
+ if (webEjbJarXml != null) {
+ try {
+ webEjbJar = ReadDescriptors.readEjbJar(webEjbJarXml.getAsset().openStream());
+ } catch (final OpenEJBException e) {
+ throw new OpenEJBRuntimeException(e);
+ }
+ } else {
+ webEjbJar = new EjbJar();
+ }
+ return webEjbJar;
+ }
+
+ private static EjbModule addTestClassAsManagedBean(Class<?> javaClass, URLClassLoader tempClassLoader, AppModule appModule) {
+ final EjbJar ejbJar = new EjbJar();
+ final OpenejbJar openejbJar = new OpenejbJar();
+ final String ejbName = appModule.getModuleId() + "_" + javaClass.getName();
+ final ManagedBean bean = ejbJar.addEnterpriseBean(new ManagedBean(ejbName, javaClass.getName(), true));
+ bean.localBean();
+ bean.setTransactionType(TransactionType.BEAN);
+ final EjbDeployment ejbDeployment = openejbJar.addEjbDeployment(bean);
+ ejbDeployment.setDeploymentId(ejbName);
+ final EjbModule e = new EjbModule(ejbJar, openejbJar);
+ e.getProperties().setProperty("openejb.cdi.activated", "false");
+ e.getProperties().setProperty("openejb.test.module", "true");
+ e.setBeans(new Beans());
+ e.setClassLoader(tempClassLoader);
+ appModule.getEjbModules().add(e);
+ return e;
+ }
+
+ private static WebApp createWebApp(final Archive<?> archive) {
+ WebApp webApp;
+ final Node webXml = archive.get(WEB_INF + "web.xml");
+ if (webXml == null) {
+ webApp = new WebApp();
+ } else {
+ InputStream inputStream = null;
+ try {
+ inputStream = webXml.getAsset().openStream();
+ webApp = Sxc.unmarshalJavaee(new WebApp$JAXB(), inputStream);
+ } catch (final Exception e) {
+ webApp = new WebApp();
+ } finally {
+ IO.close(inputStream);
+ }
+ }
+ return webApp;
+ }
+
+ private static CompositeArchive analyzeLibs(final ClassLoader parent,
+ final List<URL> additionalPaths, final Map<URL, List<String>> earMap,
+ final List<Archive> earLibsArchives,
+ final CompositeBeans earBeans,
+ final Map<ArchivePath, Node> jars,
+ final Map<String, Object> altDD) {
+ final List<org.apache.xbean.finder.archive.Archive> archives = new ArrayList<>(jars.size());
+ for (final Map.Entry<ArchivePath, Node> node : jars.entrySet()) {
+ final Asset asset = node.getValue().getAsset();
+ if (ArchiveAsset.class.isInstance(asset)) {
+ final Archive<?> libArchive = ArchiveAsset.class.cast(asset).getArchive();
+ if (!isExcluded(libArchive.getName())) {
+ earLibsArchives.add(libArchive);
+ final List<Class<?>> earClasses = new ArrayList<>();
+ final List<String> earClassNames = new ArrayList<>();
+ final Map<ArchivePath, Node> content = libArchive.getContent(new IncludeRegExpPaths(".*.class"));
+ for (final Map.Entry<ArchivePath, Node> classNode : content.entrySet()) {
+ final String classname = name(classNode.getKey().get());
+ try {
+ earClasses.add(parent.loadClass(classname));
+ earClassNames.add(classname);
+ } catch (final ClassNotFoundException e) {
+ LOGGER.fine("Can't load class " + classname);
+ } catch (final NoClassDefFoundError ncdfe) {
+ // no-op
+ }
+ }
+ try { // ends with !/META-INF/beans.xml to force it to be used as a cdi module *with bda*
+ final Node beansNode = libArchive.get(META_INF + BEANS_XML);
+ final URL arUrl = new URL("jar:file://!/lib/" + libArchive.getName() + (beansNode != null ? "!/META-INF/beans.xml" : ""));
+ if (beansNode != null) {
+ try {
+ DeploymentLoader.doMerge(arUrl, earBeans, ReadDescriptors.readBeans(beansNode.getAsset().openStream()));
+ } catch (final OpenEJBException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ earMap.put(arUrl, earClassNames);
+ } catch (final MalformedURLException e) {
+ // no-op
+ }
+ archives.add(new ClassesArchive(earClasses));
+ }
+
+ final Node ejbJarXml = libArchive.get(META_INF + EJB_JAR_XML);
+ if (ejbJarXml != null) { // not super, we should merge them surely but ok for use cases we met until today
+ altDD.put("ejb-jar.xml", new AssetSource(ejbJarXml.getAsset(), null));
+ }
+ } if (UrlAsset.class.isInstance(asset) || FileAsset.class.isInstance(asset)) {
+ try {
+ final URL url = UrlAsset.class.isInstance(asset) ? get(URL.class, "url", asset) : get(File.class, "file", asset).toURI().toURL();
+ final List<String> classes = new ArrayList<String>();
+ archives.add(new FilteredArchive(
+ new JarArchive(parent, url),
+ new WebappAggregatedArchive.ScanXmlSaverFilter(false, null, classes, null)));
+ additionalPaths.add(url);
+
+ final URLClassLoader loader = new URLClassLoader(new URL[] { url }, EMPTY_LOADER);
+ for (final String beans : asList("META-INF/beans.xml", "/META-INF/beans.xml")) {
+ final URL u = loader.getResource(beans);
+ if (u != null) {
+ try {
+ DeploymentLoader.doMerge(u, earBeans, ReadDescriptors.readBeans(u.openStream()));
+ } catch (final OpenEJBException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final IOException e) {
+ // no-op
+ }
+ earMap.put(u, classes);
+ }
+ }
+ try {
+ loader.close();
+ } catch (final IOException e) {
+ // no-op
+ }
+ } catch (final MalformedURLException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+ return new CompositeArchive(archives);
+ }
+
+ private static Node findBeansXml(final Archive<?> archive, final String prefix) {
+ Node beansXml = archive.get(prefix.concat(BEANS_XML));
+ if (beansXml == null && WEB_INF.equals(prefix)) {
+ beansXml = archive.get(WEB_INF_CLASSES.concat(META_INF).concat(BEANS_XML));
+ }
+ return beansXml;
+ }
+
+ private static void addPersistenceXml(final Archive<?> archive, final String prefix, final AppModule appModule) {
+ Node persistenceXml = archive.get(prefix.concat(PERSISTENCE_XML));
+ if (persistenceXml == null && WEB_INF.equals(prefix)) {
+ persistenceXml = archive.get(WEB_INF_CLASSES.concat(META_INF).concat(PERSISTENCE_XML));
+ }
+ if (persistenceXml != null) {
+ final Asset asset = persistenceXml.getAsset();
+ if (UrlAsset.class.isInstance(asset)) {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(get(URL.class, "url", asset)));
+ } else if (FileAsset.class.isInstance(asset)) {
+ try {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(get(File.class, "file", asset).toURI().toURL()));
+ } catch (final MalformedURLException e) {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(new AssetSource(persistenceXml.getAsset(), null)));
+ }
+ } else if (ClassLoaderAsset.class.isInstance(asset)) {
+ final URL url = get(ClassLoader.class, "classLoader", asset).getResource(get(String.class, "resourceName", asset));
+ if (url != null) {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(url));
+ } else {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(new AssetSource(persistenceXml.getAsset(), null)));
+ }
+ } else {
+ appModule.getAltDDs().put(PERSISTENCE_XML, Arrays.asList(new AssetSource(persistenceXml.getAsset(), null)));
+ }
+ }
+ }
+
+ private static void addOpenEJbJarXml(final Archive<?> archive, final String prefix, final EjbModule ejbModule) {
+ final Node openejbJarXml = archive.get(prefix.concat(OPENEJB_JAR_XML));
+ if (openejbJarXml != null) {
+ ejbModule.getAltDDs().put(OPENEJB_JAR_XML, new AssetSource(openejbJarXml.getAsset(), null));
+ }
+ }
+
+ private static void addValidationXml(final Archive<?> archive, final String prefix, final Map<String, Object> testDD, final EjbModule ejbModule) {
+ Node validationXml = archive.get(prefix.concat(VALIDATION_XML));
+ // bval tcks
+ if (validationXml == null && WEB_INF == prefix) { // we can use == here
+ validationXml = archive.get(WEB_INF_CLASSES.concat(META_INF).concat(VALIDATION_XML));
+ }
+ if (validationXml != null) {
+ testDD.put(VALIDATION_XML, new AssetSource(validationXml.getAsset(), null)); // use same config otherwise behavior is weird
+ ejbModule.getAltDDs().put(VALIDATION_XML, new AssetSource(validationXml.getAsset(), null));
+ }
+ }
+
+ private static void addResourcesXml(final Archive<?> archive, final String prefix, final EjbModule ejbModule) {
+ final Node resourcesXml = archive.get(prefix.concat(RESOURCES_XML));
+ if (resourcesXml != null) {
+ ejbModule.getAltDDs().put(RESOURCES_XML, new AssetSource(resourcesXml.getAsset(), null));
+ }
+ }
+
+ private static void addEnvEntries(final Archive<?> archive, final String prefix, final AppModule appModule, final EjbModule ejbModule) {
+ final Node envEntriesProperties = archive.get(prefix.concat(ENV_ENTRIES_PROPERTIES));
+ if (envEntriesProperties != null) {
+ InputStream is = null;
+ final Properties properties = new Properties();
+ try {
+ is = envEntriesProperties.getAsset().openStream();
+ properties.load(is);
+ ejbModule.getAltDDs().put(ENV_ENTRIES_PROPERTIES, properties);
+
+ // do it for test class too
+ appModule.getEjbModules().iterator().next().getAltDDs().put(ENV_ENTRIES_PROPERTIES, properties);
+ } catch (final Exception e) {
+ LOGGER.log(Level.SEVERE, "can't read env-entries.properties", e);
+ } finally {
+ IO.close(is);
+ }
+ }
+ }
+
+ private static String contextRoot(final String name) {
+ if (name.endsWith(".war")) {
+ return name.substring(0, name.length() - ".war".length());
+ }
+ return name;
+ }
+
+ private static org.apache.xbean.finder.archive.Archive finderArchive(
+ final Node beansXml, final Archive<?> archive,
+ final ClassLoader cl, final CompositeArchive libs,
+ final Map<URL, List<String>> webAppClassesByUrl,
+ final CompositeBeans compositeBeans) {
+ final List<Class<?>> classes = new ArrayList<>();
+ final Map<ArchivePath, Node> content = archive.getContent(new IncludeRegExpPaths(".*.class"));
+ for (final Map.Entry<ArchivePath, Node> node : content.entrySet()) {
+ final String classname = name(node.getKey().get());
+ try {
+ classes.add(cl.loadClass(classname));
+ } catch (final ClassNotFoundException e) {
+ LOGGER.fine("Can't load class " + classname);
+ if (LOGGER.isLoggable(Level.FINEST)) {
+ e.printStackTrace(System.err);
+ }
+ } catch (final NoClassDefFoundError ncdfe) {
+ // no-op
+ }
+ }
+
+ final List<org.apache.xbean.finder.archive.Archive> archives = new ArrayList<>();
+
+ archives.add(new ClassesArchive(classes));
+ if (beansXml != null) {
+ try {
+ final URL key = new URL("jar:file://!/WEB-INF/beans.xml"); // no host avoid host resolution in hashcode()
+ try {
+ DeploymentLoader.doMerge(key, compositeBeans, ReadDescriptors.readBeans(beansXml.getAsset().openStream()));
+ } catch (final OpenEJBException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ final List<String> mainClasses = new ArrayList<>();
+ for (final Class<?> clazz : classes) {
+ mainClasses.add(clazz.getName());
+ }
+
+ webAppClassesByUrl.put(key, mainClasses);
+ } catch (final MalformedURLException mue) {
+ // no-op
+ }
+ }
+
+ if (libs != null) {
+ archives.add(libs);
+ }
+
+ return new SimpleWebappAggregatedArchive(cl, new CompositeArchive(archives), webAppClassesByUrl);
+ }
+
+ private static boolean isExcluded(final String archiveName) {
+ return "arquillian-junit.jar".equals(archiveName) || "arquillian-protocol.jar".equals(archiveName)
+ || "arquillian-core.jar".equals(archiveName);
+ }
+
+ private static String name(final String raw) {
+ String name = raw;
+ if (name.startsWith(WEB_INF_CLASSES)) {
+ name = name.substring(WEB_INF_CLASSES.length() - 1);
+ }
+ name = name.replace('/', '.');
+ return name.substring(1, name.length() - 6);
+ }
+
+ private static final class AssetSource extends ReadDescriptors.UrlSource {
+ private Asset asset;
+
+ private AssetSource(final Asset asset, final URL url) {
+ super(url);
+ this.asset = asset;
+ }
+
+ @Override
+ public InputStream get() throws IOException {
+ return asset.openStream();
+ }
+ }
+
+ // mainly extended to be sure to reuse our tip about scanning for CDI
+ private static class SimpleWebappAggregatedArchive extends WebappAggregatedArchive {
+ private final CompositeArchive delegate;
+ private final Map<URL, List<String>> classesMap;
+
+ public SimpleWebappAggregatedArchive(final ClassLoader cl, final CompositeArchive archive, final Map<URL, List<String>> map) {
+ super(cl, new HashMap<String, Object>(), new ArrayList<URL>());
+
+ delegate = archive;
+ classesMap = map;
+ }
+
+ @Override
+ public Map<URL, List<String>> getClassesMap() {
+ return classesMap;
+ }
+
+ @Override
+ public InputStream getBytecode(final String s) throws IOException, ClassNotFoundException {
+ return delegate.getBytecode(s);
+ }
+
+ @Override
+ public Class<?> loadClass(final String s) throws ClassNotFoundException {
+ return delegate.loadClass(s);
+ }
+
+ @Override
+ public Iterator<Entry> iterator() {
+ return delegate.iterator();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBConfiguration.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBConfiguration.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBConfiguration.java
new file mode 100644
index 0000000..093caca
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBConfiguration.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import org.jboss.arquillian.config.descriptor.api.Multiline;
+import org.jboss.arquillian.container.spi.ConfigurationException;
+import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import static java.util.Arrays.asList;
+
+public class OpenEJBConfiguration implements ContainerConfiguration {
+ private String properties = "";
+ private String preloadClasses;
+ private boolean startDefaultScopes;
+ private Collection<String> singleDeploymentByArchiveName = Collections.emptyList();
+
+ @Override
+ public void validate() throws ConfigurationException {
+ // no-op
+ }
+
+ public boolean isStartDefaultScopes() {
+ return startDefaultScopes;
+ }
+
+ public void setStartDefaultScopes(final boolean startDefaultScopes) {
+ this.startDefaultScopes = startDefaultScopes;
+ }
+
+ public String getProperties() {
+ return properties;
+ }
+
+ @Multiline
+ public void setProperties(final String properties) {
+ this.properties = properties;
+ }
+
+ public String getPreloadClasses() {
+ return preloadClasses;
+ }
+
+ public void setPreloadClasses(final String preloadClasses) {
+ this.preloadClasses = preloadClasses;
+ }
+
+ public boolean isSingleDeploymentByArchiveName(final String name) {
+ return singleDeploymentByArchiveName.contains(name) || singleDeploymentByArchiveName.contains("*") || singleDeploymentByArchiveName.contains("true");
+ }
+
+ public void setSingleDeploymentByArchiveName(final String singleDeploymentByArchiveName) {
+ this.singleDeploymentByArchiveName = singleDeploymentByArchiveName == null || singleDeploymentByArchiveName.trim().isEmpty() ?
+ Collections.<String>emptyList() : new HashSet<String>(asList(singleDeploymentByArchiveName.split(" *, *")));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
new file mode 100644
index 0000000..f999c20
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
@@ -0,0 +1,435 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import org.apache.openejb.AppContext;
+import org.apache.openejb.BeanContext;
+import org.apache.openejb.ModuleTestContext;
+import org.apache.openejb.OpenEJB;
+import org.apache.openejb.OpenEJBRuntimeException;
+import org.apache.openejb.OpenEjbContainer;
+import org.apache.openejb.arquillian.common.ArquillianUtil;
+import org.apache.openejb.arquillian.openejb.server.ServiceManagers;
+import org.apache.openejb.assembler.classic.AppInfo;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ClassListInfo;
+import org.apache.openejb.assembler.classic.OpenEjbConfigurationFactory;
+import org.apache.openejb.assembler.classic.ServletInfo;
+import org.apache.openejb.assembler.classic.WebAppBuilder;
+import org.apache.openejb.assembler.classic.WebAppInfo;
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.DeploymentFilterable;
+import org.apache.openejb.config.WebModule;
+import org.apache.openejb.core.LocalInitialContext;
+import org.apache.openejb.core.LocalInitialContextFactory;
+import org.apache.openejb.core.WebContext;
+import org.apache.openejb.loader.IO;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.server.httpd.session.SessionManager;
+import org.apache.openejb.web.LightweightWebAppBuilder;
+import org.apache.webbeans.web.lifecycle.test.MockHttpSession;
+import org.apache.webbeans.web.lifecycle.test.MockServletContext;
+import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
+import org.jboss.arquillian.container.spi.client.container.DeploymentException;
+import org.jboss.arquillian.container.spi.client.container.LifecycleException;
+import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
+import org.jboss.arquillian.container.spi.context.annotation.DeploymentScoped;
+import org.jboss.arquillian.core.api.Instance;
+import org.jboss.arquillian.core.api.InstanceProducer;
+import org.jboss.arquillian.core.api.annotation.Inject;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.arquillian.test.spi.annotation.SuiteScoped;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptor;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+
+import static org.apache.openejb.cdi.ScopeHelper.startContexts;
+import static org.apache.openejb.cdi.ScopeHelper.stopContexts;
+
+public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBConfiguration> {
+ private static final Properties PROPERTIES = new Properties();
+
+ static {
+ // global properties
+ PROPERTIES.setProperty(Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
+ PROPERTIES.setProperty(LocalInitialContext.ON_CLOSE, LocalInitialContext.Close.DESTROY.name());
+ PROPERTIES.setProperty(DeploymentFilterable.DEPLOYMENTS_CLASSPATH_PROPERTY, "false");
+ try {
+ OpenEJBDeployableContainer.class.getClassLoader().loadClass("org.apache.openejb.server.ServiceManager");
+ PROPERTIES.setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "true");
+ } catch (final Exception e) {
+ // ignored
+ }
+ }
+
+ private static final ConcurrentMap<String, DeploymentInfo> DEPLOYMENT_INFO = new ConcurrentHashMap<String, DeploymentInfo>();
+ public static final AppContext NO_APP_CTX = new AppContext(null, SystemInstance.get(), null, null, null, false);
+
+ // config
+ private Properties properties;
+
+ // system
+ private Assembler assembler;
+ private InitialContext initialContext;
+ private ConfigurationFactory configurationFactory;
+ private Collection<Archive<?>> containerArchives;
+
+ // suite
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer<AppInfo> appInfoProducer;
+
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer<AppContext> appContextProducer;
+
+ @Inject
+ @SuiteScoped
+ private InstanceProducer<Context> contextProducer;
+
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer<ServletContext> servletContextProducer;
+
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer<HttpSession> sessionProducer;
+
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer<Closeables> closeablesProducer;
+
+ @Inject
+ @SuiteScoped
+ private InstanceProducer<ClassLoader> classLoader;
+
+ @Inject
+ private Instance<Closeables> closeables;
+
+ @Inject
+ private Instance<ServletContext> servletContext;
+
+ @Inject
+ private Instance<HttpSession> session;
+
+ @Inject
+ private Instance<AppInfo> info;
+
+ @Inject
+ private Instance<AppContext> appContext;
+
+ @Inject
+ private Instance<TestClass> testClass;
+
+ private OpenEJBConfiguration configuration;
+
+ @Override
+ public Class<OpenEJBConfiguration> getConfigurationClass() {
+ return OpenEJBConfiguration.class;
+ }
+
+ @Override
+ public void setup(final OpenEJBConfiguration openEJBConfiguration) {
+ properties = new Properties();
+ configuration = openEJBConfiguration;
+
+ final ByteArrayInputStream bais = new ByteArrayInputStream(openEJBConfiguration.getProperties().getBytes());
+ try {
+ properties.load(bais);
+ } catch (final IOException e) {
+ throw new OpenEJBRuntimeException(e);
+ } finally {
+ IO.close(bais);
+ }
+
+ for (final Map.Entry<Object, Object> defaultKey : PROPERTIES.entrySet()) {
+ final String key = defaultKey.getKey().toString();
+ if (!properties.containsKey(key)) {
+ properties.setProperty(key, defaultKey.getValue().toString());
+ }
+ }
+
+ ArquillianUtil.preLoadClassesAsynchronously(openEJBConfiguration.getPreloadClasses());
+ }
+
+ @Override
+ public void start() throws LifecycleException {
+ try {
+ initialContext = new InitialContext(properties);
+ } catch (final NamingException e) {
+ throw new LifecycleException("can't start the OpenEJB container", e);
+ }
+
+ assembler = SystemInstance.get().getComponent(Assembler.class);
+ configurationFactory = (ConfigurationFactory) SystemInstance.get().getComponent(OpenEjbConfigurationFactory.class);
+
+ if ("true".equalsIgnoreCase(PROPERTIES.getProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE))
+ && SystemInstance.get().getComponent(WebAppBuilder.class) == null) {
+ SystemInstance.get().setComponent(WebAppBuilder.class, new LightweightWebAppBuilder());
+ }
+
+ contextProducer.set(initialContext);
+
+ containerArchives = ArquillianUtil.toDeploy(properties);
+ final Closeables globalScopeCloseables = new Closeables();
+ SystemInstance.get().setComponent(Closeables.class, globalScopeCloseables);
+ for (final Archive<?> archive : containerArchives) {
+ try {
+ quickDeploy(archive, testClass.get(), globalScopeCloseables);
+ } catch (final DeploymentException e) {
+ Logger.getLogger(OpenEJBDeployableContainer.class.getName()).log(Level.SEVERE, e.getMessage(), e);
+ }
+ }
+ }
+
+ @Override
+ public ProtocolMetaData deploy(final Archive<?> archive) throws DeploymentException {
+ final DeploymentInfo info;
+ try {
+ final Closeables cl = new Closeables();
+ closeablesProducer.set(cl);
+ info = quickDeploy(archive, testClass.get(), cl);
+
+ // try to switch module context jndi to let test use java:module naming
+ // we could put the managed bean in the war but then test class should respect all the
+ // container rules (CDI) which is not the case with this solution
+ if (archive.getName().endsWith(".war")) {
+ final List<BeanContext> beanContexts = info.appCtx.getBeanContexts();
+ if (beanContexts.size() > 1) {
+ final Iterator<BeanContext> it = beanContexts.iterator();
+ while (it.hasNext()) {
+ final BeanContext next = it.next();
+ if (ModuleTestContext.class.isInstance(next.getModuleContext()) && BeanContext.Comp.class != next.getBeanClass()) {
+ for (final BeanContext b : beanContexts) {
+ if (b.getModuleContext() != next.getModuleContext()) {
+ ModuleTestContext.class.cast(next.getModuleContext())
+ .setModuleJndiContextOverride(b.getModuleContext().getModuleJndiContext());
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ servletContextProducer.set(info.appServletContext);
+ sessionProducer.set(info.appSession);
+ appInfoProducer.set(info.appInfo);
+ appContextProducer.set(info.appCtx);
+ final ClassLoader loader = info.appCtx.getWebContexts().isEmpty() ? info.appCtx.getClassLoader() : info.appCtx.getWebContexts().iterator().next().getClassLoader();
+ classLoader.set(loader == null ? info.appCtx.getClassLoader() : loader);
+ } catch (final Exception e) {
+ throw new DeploymentException("can't deploy " + archive.getName(), e);
+ }
+
+ // if service manager is started allow @ArquillianResource URL injection
+ if (PROPERTIES.containsKey(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE)) {
+ final ProtocolMetaData metaData = ServiceManagers.protocolMetaData(appInfoProducer.get());
+ HTTPContext http = null;
+ for (final WebAppInfo webapp : info.appInfo.webApps) {
+ for (final ServletInfo servletInfo : webapp.servlets) {
+ if (http == null) {
+ http = HTTPContext.class.cast(metaData.getContexts().iterator().next());
+ http.add(new Servlet(servletInfo.servletName, webapp.contextRoot));
+ }
+ }
+ for (final ClassListInfo classListInfo : webapp.webAnnotatedClasses) {
+ for (final String path : classListInfo.list) {
+ if (!path.contains("!")) {
+ continue;
+ }
+ if (http == null) {
+ http = HTTPContext.class.cast(metaData.getContexts().iterator().next());
+ }
+ http.add(new Servlet(path.substring(path.lastIndexOf('!') + 2).replace(".class", "").replace("/", "."), webapp.contextRoot));
+ }
+ }
+ }
+ if (metaData != null) {
+ return metaData;
+ }
+ }
+ return new ProtocolMetaData();
+ }
+
+ private DeploymentInfo quickDeploy(final Archive<?> archive, final TestClass testClass, final Closeables cls) throws DeploymentException {
+ final String name = archive.getName();
+ DeploymentInfo info = DEPLOYMENT_INFO.get(name);
+ if (info == null) {
+ try {
+ final AppModule module = OpenEJBArchiveProcessor.createModule(archive, testClass, cls);
+ final AppInfo appInfo = configurationFactory.configureApplication(module);
+
+ final WebAppBuilder webAppBuilder = SystemInstance.get().getComponent(WebAppBuilder.class);
+ final boolean isEmbeddedWebAppBuilder = webAppBuilder != null && LightweightWebAppBuilder.class.isInstance(webAppBuilder);
+ if (isEmbeddedWebAppBuilder) {
+ // for now we keep the same classloader, open to discussion if we should recreate it, not sure it does worth it
+ final LightweightWebAppBuilder lightweightWebAppBuilder = LightweightWebAppBuilder.class.cast(webAppBuilder);
+ for (final WebModule w : module.getWebModules()) {
+ final String moduleId = w.getModuleId();
+ lightweightWebAppBuilder.setClassLoader(moduleId, w.getClassLoader());
+ cls.add(new Closeable() {
+ @Override
+ public void close() throws IOException {
+ lightweightWebAppBuilder.removeClassLoader(moduleId);
+ }
+ });
+ }
+ }
+ final AppContext appCtx = assembler.createApplication(appInfo, module.getClassLoader());
+ if (isEmbeddedWebAppBuilder && PROPERTIES.containsKey(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE) && !appCtx.getWebContexts().isEmpty()) {
+ cls.add(new Closeable() {
+ @Override
+ public void close() throws IOException {
+ try {
+ final SessionManager sessionManager = SystemInstance.get().getComponent(SessionManager.class);
+ if (sessionManager != null) {
+ for (final WebContext web : appCtx.getWebContexts()) {
+ sessionManager.destroy(web);
+ }
+ }
+ } catch (final Throwable e) {
+ // no-op
+ }
+ }
+ });
+ }
+
+ final ServletContext appServletContext = new MockServletContext();
+ final HttpSession appSession = new MockHttpSession();
+
+ if (configuration.isStartDefaultScopes()) {
+ startContexts(appCtx.getWebBeansContext().getContextsService(), appServletContext, appSession);
+ }
+
+ info = new DeploymentInfo(appServletContext, appSession, appInfo, appCtx);
+ if (configuration.isSingleDeploymentByArchiveName(name)) {
+ DEPLOYMENT_INFO.putIfAbsent(name, info);
+ }
+ } catch (final Exception e) {
+ throw new DeploymentException("can't deploy " + name, e);
+ }
+ }
+ return info;
+ }
+
+ @Override
+ public void undeploy(final Archive<?> archive) throws DeploymentException {
+ final Closeables cl = closeables.get();
+ if (cl != null) {
+ try {
+ cl.close();
+ } catch (final IOException e) {
+ // no-op
+ }
+ }
+
+ // reset classloader for next text
+ // otherwise if it was closed something can fail
+ classLoader.set(OpenEJBDeployableContainer.class.getClassLoader());
+
+ final AppContext ctx = appContext.get();
+ if (ctx == null) {
+ return;
+ } else {
+ appContextProducer.set(NO_APP_CTX); // release all references of the previous one - classloaders whatever arquillian Instance impl is etc
+ }
+
+ try {
+ if (!configuration.isSingleDeploymentByArchiveName(archive.getName())) {
+ assembler.destroyApplication(info.get().path);
+ }
+ if (configuration.isStartDefaultScopes()) {
+ stopContexts(ctx.getWebBeansContext().getContextsService(), servletContext.get(), session.get());
+ }
+ } catch (final Exception e) {
+ throw new DeploymentException("can't undeploy " + archive.getName(), e);
+ }
+ }
+
+ @Override
+ public void stop() throws LifecycleException {
+ ArquillianUtil.undeploy(this, containerArchives);
+
+ try {
+ if (initialContext != null) {
+ initialContext.close();
+ }
+ Closeables closeables = SystemInstance.get().getComponent(Closeables.class);
+ if (closeables != null) {
+ closeables.close();
+ }
+ } catch (final NamingException e) {
+ throw new LifecycleException("can't close the OpenEJB container", e);
+ } catch (final IOException e) {
+ // no-op: close() of classloaders, not a big deal at this moment
+ } finally {
+ OpenEJB.destroy();
+ }
+ }
+
+ @Override
+ public ProtocolDescription getDefaultProtocol() {
+ return new ProtocolDescription("Local");
+ }
+
+ @Override
+ public void deploy(final Descriptor descriptor) throws DeploymentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void undeploy(final Descriptor descriptor) throws DeploymentException {
+ throw new UnsupportedOperationException();
+ }
+
+ private static final class DeploymentInfo {
+ public final ServletContext appServletContext;
+ public final HttpSession appSession;
+ public final AppInfo appInfo;
+ public final AppContext appCtx;
+
+ private DeploymentInfo(final ServletContext appServletContext, final HttpSession appSession, final AppInfo appInfo, final AppContext appCtx) {
+ this.appServletContext = appServletContext;
+ this.appSession = appSession;
+ this.appInfo = appInfo;
+ this.appCtx = appCtx;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBExtension.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBExtension.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBExtension.java
new file mode 100644
index 0000000..6bb944d
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBExtension.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import org.apache.openejb.arquillian.common.ArquillianUtil;
+import org.apache.openejb.arquillian.common.TestObserver;
+import org.apache.openejb.arquillian.common.deployment.DeploymentExceptionObserver;
+import org.apache.openejb.arquillian.common.deployment.DeploymentExceptionProvider;
+import org.apache.openejb.arquillian.transaction.OpenEJBTransactionProvider;
+import org.apache.openejb.util.JuliLogStreamFactory;
+import org.apache.openejb.util.LogCategory;
+import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
+import org.jboss.arquillian.core.spi.LoadableExtension;
+import org.jboss.arquillian.test.spi.TestEnricher;
+import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
+import org.jboss.arquillian.transaction.spi.provider.TransactionProvider;
+
+import java.util.Enumeration;
+import java.util.logging.Handler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+public class OpenEJBExtension implements LoadableExtension {
+ private static final String OPENEJB_ADAPTER_NAME = "openejb";
+
+ static { // logging conf
+ if (ArquillianUtil.isCurrentAdapter(OPENEJB_ADAPTER_NAME)) {
+ if (System.getProperty("java.util.logging.config.class") == null || System.getProperty("java.util.logging.config.file") == null) {
+ final Enumeration<String> list = LogManager.getLogManager().getLoggerNames();
+ while (list.hasMoreElements()) {
+ initLogger(list.nextElement());
+ }
+ initLogger(LogCategory.OPENEJB.getName());
+ }
+ }
+ }
+
+ private static void initLogger(final String name) {
+ final Logger logger = Logger.getLogger(name);
+ final Handler[] handlers = logger.getHandlers();
+ if (handlers != null) {
+ for (final Handler handler : handlers) {
+ logger.removeHandler(handler);
+ }
+ }
+ logger.setUseParentHandlers(false);
+ logger.addHandler(new JuliLogStreamFactory.OpenEJBSimpleLayoutHandler());
+
+ }
+
+ @Override
+ public void register(final ExtensionBuilder extensionBuilder) {
+ if (ArquillianUtil.isCurrentAdapter(OPENEJB_ADAPTER_NAME)) {
+ extensionBuilder.service(DeployableContainer.class, OpenEJBDeployableContainer.class)
+ .service(TestEnricher.class, OpenEJBInjectionEnricher.class)
+ .service(ResourceProvider.class, DeploymentExceptionProvider.class)
+ .service(TransactionProvider.class, OpenEJBTransactionProvider.class)
+ .observer(TestObserver.class)
+ .observer(DeploymentExceptionObserver.class);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/5b16879e/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBInjectionEnricher.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBInjectionEnricher.java b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBInjectionEnricher.java
new file mode 100644
index 0000000..a571381
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBInjectionEnricher.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.arquillian.openejb;
+
+import org.apache.openejb.AppContext;
+import org.apache.openejb.arquillian.common.enrichment.OpenEJBEnricher;
+import org.apache.openejb.arquillian.common.mockito.MockitoEnricher;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.apache.webbeans.inject.OWBInjector;
+import org.jboss.arquillian.core.api.Instance;
+import org.jboss.arquillian.core.api.annotation.Inject;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.arquillian.test.spi.TestEnricher;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class OpenEJBInjectionEnricher implements TestEnricher {
+ @Inject
+ private Instance<AppContext> appContext;
+
+ @Inject
+ private Instance<TestClass> testClass;
+
+ @Override
+ public void enrich(final Object testInstance) {
+ if (!SystemInstance.isInitialized()) {
+ return;
+ }
+
+ new MockitoEnricher().enrich(testInstance);
+
+ final AppContext context = appContext.get();
+ if (context != null) {
+ OpenEJBEnricher.enrich(testInstance, context);
+ } else { // try to enrich with all for deployment at startup feature - only once context can be used in a class
+ final List<AppContext> appContexts = SystemInstance.get().getComponent(ContainerSystem.class).getAppContexts();
+ final Class<?> clazz = testInstance.getClass();
+ for (final AppContext appContext : appContexts) {
+ try {
+ final BeanManager bm = appContext.getWebBeansContext().getBeanManagerImpl();
+ final AnnotatedType<?> at = bm.createAnnotatedType(clazz);
+ bm.createInjectionTarget(at);
+ final CreationalContext<Object> cc = bm.createCreationalContext(null);
+ OWBInjector.inject(bm, testInstance, cc);
+ cc.release();
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+ }
+ }
+
+ @Override
+ public Object[] resolve(final Method method) {
+ return OpenEJBEnricher.resolve(appContext.get(), testClass.get(), method);
+ }
+}