Author: rmannibucau
Date: Tue Oct 18 20:49:19 2016
New Revision: 1765505

URL: http://svn.apache.org/viewvc?rev=1765505&view=rev
Log:
initial import

Added:
    openwebbeans/microwave/trunk/.gitignore   (with props)
    openwebbeans/microwave/trunk/TODO.txt
    openwebbeans/microwave/trunk/pom.xml
    openwebbeans/microwave/trunk/src/
    openwebbeans/microwave/trunk/src/main/
    openwebbeans/microwave/trunk/src/main/java/
    openwebbeans/microwave/trunk/src/main/java/org/
    openwebbeans/microwave/trunk/src/main/java/org/apache/
    openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/Microwave.java
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/MicrowaveExplosion.java
    openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/BusInstance.java
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/CxfCdiAutoSetup.java
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/JAXRSCdiResourceExtensionWorkaround.java
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/MicrowaveLoader.java
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/OWBAutoSetup.java
    openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/
    
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/ProvidedLoader.java
    openwebbeans/microwave/trunk/src/main/resources/
    openwebbeans/microwave/trunk/src/main/resources/META-INF/
    openwebbeans/microwave/trunk/src/main/resources/META-INF/beans.xml
    openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/
    
openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/openwebbeans.properties
    openwebbeans/microwave/trunk/src/main/resources/META-INF/services/
    
openwebbeans/microwave/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
    openwebbeans/microwave/trunk/src/test/
    openwebbeans/microwave/trunk/src/test/java/
    openwebbeans/microwave/trunk/src/test/java/org/
    openwebbeans/microwave/trunk/src/test/java/org/apache/
    openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/
    
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/MicrowaveTest.java
    openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/
    
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/Endpoint.java
    
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/RsApp.java

Added: openwebbeans/microwave/trunk/.gitignore
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/.gitignore?rev=1765505&view=auto
==============================================================================
--- openwebbeans/microwave/trunk/.gitignore (added)
+++ openwebbeans/microwave/trunk/.gitignore Tue Oct 18 20:49:19 2016
@@ -0,0 +1,9 @@
+target
+.classpath
+.project
+.settings
+.idea
+*.ipr
+*.iml
+*.log
+*~

Propchange: openwebbeans/microwave/trunk/.gitignore
------------------------------------------------------------------------------
    svn:executable = *

Added: openwebbeans/microwave/trunk/TODO.txt
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/TODO.txt?rev=1765505&view=auto
==============================================================================
--- openwebbeans/microwave/trunk/TODO.txt (added)
+++ openwebbeans/microwave/trunk/TODO.txt Tue Oct 18 20:49:19 2016
@@ -0,0 +1,2 @@
+- maven plugin
+- main

Added: openwebbeans/microwave/trunk/pom.xml
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/pom.xml?rev=1765505&view=auto
==============================================================================
--- openwebbeans/microwave/trunk/pom.xml (added)
+++ openwebbeans/microwave/trunk/pom.xml Tue Oct 18 20:49:19 2016
@@ -0,0 +1,150 @@
+<?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>org.apache.microwave</groupId>
+  <artifactId>microwave</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>Microwave</name>
+  <description>A Microprofile server @ ASF</description>
+
+  <properties>
+    <openwebbeans.version>1.7.0</openwebbeans.version>
+    <tomcat.version>8.5.6</tomcat.version>
+    <cxf.version>3.1.7</cxf.version>
+    <johnzon.version>0.9.5</johnzon.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <version>1.16.10</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-annotation_1.2_spec</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.1_spec</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-atinject_1.0_spec</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-json_1.0_spec</artifactId>
+      <version>1.0-alpha-1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat</groupId>
+      <artifactId>tomcat-servlet-api</artifactId>
+      <version>${tomcat.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.4</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.xbean</groupId>
+      <artifactId>xbean-reflect</artifactId>
+      <version>4.5</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-impl</artifactId>
+      <version>${openwebbeans.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-web</artifactId>
+      <version>${openwebbeans.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat.embed</groupId>
+      <artifactId>tomcat-embed-core</artifactId>
+      <version>${tomcat.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+      <version>${cxf.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-integration-cdi</artifactId>
+      <version>${cxf.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-client</artifactId>
+      <version>${cxf.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.johnzon</groupId>
+      <artifactId>johnzon-jaxrs</artifactId>
+      <version>${johnzon.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.5.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/Microwave.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/Microwave.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/Microwave.java 
(added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/Microwave.java 
Tue Oct 18 20:49:19 2016
@@ -0,0 +1,1085 @@
+/*
+ * 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.microwave;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Globals;
+import org.apache.catalina.Host;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Manager;
+import org.apache.catalina.Realm;
+import org.apache.catalina.Server;
+import org.apache.catalina.Service;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.session.ManagerBase;
+import org.apache.catalina.session.StandardManager;
+import org.apache.catalina.startup.Catalina;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.text.StrLookup;
+import org.apache.commons.lang3.text.StrSubstitutor;
+import org.apache.coyote.http2.Http2Protocol;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.microwave.cxf.CxfCdiAutoSetup;
+import org.apache.microwave.openwebbeans.OWBAutoSetup;
+import org.apache.microwave.tomcat.ProvidedLoader;
+import org.apache.tomcat.util.descriptor.web.LoginConfig;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.xbean.finder.ResourceFinder;
+import org.apache.xbean.recipe.ObjectRecipe;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.function.Consumer;
+
+import static java.util.Collections.emptySet;
+import static java.util.Optional.ofNullable;
+
+public class Microwave implements AutoCloseable {
+    @Getter
+    private final Builder configuration;
+
+    private InternalTomcat tomcat;
+    private File base;
+
+    // we can undeploy webapps with that later
+    private final Map<String, Context> contexts = new HashMap<>();
+
+    public Microwave(final Builder builder) {
+        this.configuration = builder;
+    }
+
+    public Microwave deployClasspath() {
+        return deployClasspath("");
+    }
+
+    public Microwave deployClasspath(final String context) {
+        final File dir = new File(configuration.tempDir, "classpath/fake-" + 
context.replace("/", ""));
+        FileUtils.mkDir(dir);
+        return deployWebapp(context, dir, c -> c.setLoader(new 
ProvidedLoader(Thread.currentThread().getContextClassLoader())));
+    }
+
+    public Microwave deployWebapp(final File warOrDir) {
+        return deployWebapp("", warOrDir, null);
+    }
+
+    public Microwave deployWebapp(final String context, final File warOrDir) {
+        return deployWebapp(context, warOrDir, null);
+    }
+
+    public Microwave deployWebapp(final String context, final File warOrDir, 
final Consumer<Context> customizer) {
+        if (contexts.containsKey(context)) {
+            throw new IllegalArgumentException("Already deployed: '" + context 
+ "'");
+        }
+
+        final Context ctx = new StandardContext();
+        ctx.setPath(context);
+        ctx.setName(context);
+        try {
+            ctx.setDocBase(warOrDir.getCanonicalPath());
+        } catch (final IOException e) {
+            ctx.setDocBase(warOrDir.getAbsolutePath());
+        }
+        ctx.addLifecycleListener(new Tomcat.FixContextListener());
+        ctx.addLifecycleListener(event -> {
+            switch (event.getType()) {
+                case Lifecycle.AFTER_START_EVENT:
+                    
ctx.getResources().setCachingAllowed(configuration.webResourceCached);
+                    break;
+                case Lifecycle.BEFORE_START_EVENT:
+                    if (configuration.loginConfig() != null) {
+                        
ctx.setLoginConfig(configuration.loginConfig().build());
+                    }
+                    for (final SecurityConstaintBuilder sc : 
configuration.securityConstraints) {
+                        ctx.addConstraint(sc.build());
+                    }
+                    if (configuration.webXml != null) {
+                        
ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.webXml);
+                    }
+                    break;
+                default:
+            }
+
+        });
+
+        ctx.addServletContainerInitializer((c, ctx1) -> {
+            ctx.getServletContext().setAttribute("microwave.configuration", 
configuration);
+            try {
+                new OWBAutoSetup().onStartup(c, ctx1);
+                new CxfCdiAutoSetup().onStartup(c, ctx1);
+            } finally {
+                
ctx.getServletContext().removeAttribute("microwave.configuration");
+            }
+        }, emptySet());
+
+        ofNullable(customizer).ifPresent(c -> c.accept(ctx));
+
+        tomcat.getHost().addChild(ctx);
+        contexts.put(context, ctx);
+        return this;
+    }
+
+    public Microwave bake() {
+        start();
+        return deployClasspath();
+    }
+
+    public Microwave start() {
+        if (configuration.quickSession) {
+            tomcat = new TomcatWithFastSessionIDs();
+        } else {
+            tomcat = new InternalTomcat();
+        }
+
+        { // setup
+            base = new File(getBaseDir());
+            if (base.exists() && configuration.deleteBaseOnStartup) {
+                FileUtils.delete(base);
+            } else if (!base.exists()) {
+                FileUtils.mkDir(base);
+            }
+
+            final File conf = createDirectory(base, "conf");
+            createDirectory(base, "lib");
+            createDirectory(base, "logs");
+            createDirectory(base, "temp");
+            createDirectory(base, "work");
+            createDirectory(base, "webapps");
+
+            synchronize(conf, configuration.conf);
+        }
+
+        final Properties props = configuration.properties;
+        StrSubstitutor substitutor = null;
+        for (final String s : props.stringPropertyNames()) {
+            final String v = props.getProperty(s);
+            if (v != null && v.contains("${")) {
+                if (substitutor == null) {
+                    final Map<String, String> placeHolders = new HashMap<>();
+                    placeHolders.put("microwave.embedded.http", 
Integer.toString(configuration.httpPort));
+                    placeHolders.put("microwave.embedded.https", 
Integer.toString(configuration.httpsPort));
+                    placeHolders.put("microwave.embedded.stop", 
Integer.toString(configuration.stopPort));
+                    substitutor = new StrSubstitutor(placeHolders);
+                }
+                props.put(s, substitutor.replace(v));
+            }
+        }
+
+        final File conf = new File(base, "conf");
+        final File webapps = new File(base, "webapps");
+
+        final boolean initialized;
+        if (configuration.serverXml != null) {
+            final File file = new File(conf, "server.xml");
+            if (!file.equals(configuration.serverXml)) {
+                try (final InputStream is = new 
FileInputStream(configuration.serverXml);
+                     final FileOutputStream fos = new FileOutputStream(file)) {
+                    IOUtils.copy(is, fos);
+                } catch (final IOException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+
+            // respect config (host/port) of the Configuration
+            final QuickServerXmlParser ports = 
QuickServerXmlParser.parse(file);
+            if (configuration.keepServerXmlAsThis) {
+                configuration.httpPort = Integer.parseInt(ports.http());
+                configuration.stopPort = Integer.parseInt(ports.stop());
+            } else {
+                final Map<String, String> replacements = new HashMap<>();
+                replacements.put(ports.http(), 
String.valueOf(configuration.httpPort));
+                replacements.put(ports.https(), 
String.valueOf(configuration.httpsPort));
+                replacements.put(ports.stop(), 
String.valueOf(configuration.stopPort));
+
+                String serverXmlContent;
+                try (final InputStream stream = new FileInputStream(file)) {
+                    serverXmlContent = IOUtils.toString(stream, 
StandardCharsets.UTF_8);
+                    for (final Map.Entry<String, String> pair : 
replacements.entrySet()) {
+                        serverXmlContent = 
serverXmlContent.replace(pair.getKey(), pair.getValue());
+                    }
+                } catch (final IOException e) {
+                    throw new IllegalStateException(e);
+                }
+                try (final OutputStream os = new FileOutputStream(file)) {
+                    IOUtils.write(serverXmlContent, os);
+                } catch (final IOException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+
+            tomcat.server(createServer(file.getAbsolutePath()));
+            initialized = true;
+        } else {
+            initialized = false;
+        }
+
+        tomcat.setBaseDir(base.getAbsolutePath());
+        tomcat.setHostname(configuration.host);
+        if (!initialized) {
+            tomcat.getHost().setAppBase(webapps.getAbsolutePath());
+            tomcat.getEngine().setDefaultHost(configuration.host);
+            tomcat.setHostname(configuration.host);
+        }
+
+        if (configuration.realm != null) {
+            tomcat.getEngine().setRealm(configuration.realm);
+        }
+
+        if (tomcat.getRawConnector() == null && !configuration.skipHttp) {
+            final Connector connector = createConnector();
+            connector.setPort(configuration.httpPort);
+            if (connector.getAttribute("connectionTimeout") == null) {
+                connector.setAttribute("connectionTimeout", "3000");
+            }
+            if (configuration.http2) { // would likely need SSLHostConfig 
programmatically
+                connector.addUpgradeProtocol(new Http2Protocol());
+            }
+
+            tomcat.getService().addConnector(connector);
+            tomcat.setConnector(connector);
+        }
+
+        // create https connector
+        if (configuration.ssl) {
+            final Connector httpsConnector = createConnector();
+            httpsConnector.setPort(configuration.httpsPort);
+            httpsConnector.setSecure(true);
+            httpsConnector.setProperty("SSLEnabled", "true");
+            httpsConnector.setProperty("sslProtocol", 
configuration.sslProtocol);
+
+            if (configuration.keystoreFile != null) {
+                httpsConnector.setAttribute("", configuration.keystoreFile);
+            }
+            if (configuration.keystorePass != null) {
+                httpsConnector.setAttribute("keystorePass", 
configuration.keystorePass);
+            }
+            httpsConnector.setAttribute("keystoreType", 
configuration.keystoreType);
+            if (configuration.clientAuth != null) {
+                httpsConnector.setAttribute("clientAuth", 
configuration.clientAuth);
+            }
+            if (configuration.keyAlias != null) {
+                httpsConnector.setAttribute("keyAlias", 
configuration.keyAlias);
+            }
+
+            if (configuration.http2) { // would likely need SSLHostConfig 
programmatically
+                httpsConnector.addUpgradeProtocol(new Http2Protocol());
+            }
+
+            tomcat.getService().addConnector(httpsConnector);
+
+            if (configuration.skipHttp) {
+                tomcat.setConnector(httpsConnector);
+            }
+        }
+
+        for (final Connector c : configuration.connectors) {
+            tomcat.getService().addConnector(c);
+        }
+        if (!configuration.skipHttp && !configuration.ssl && 
!configuration.connectors.isEmpty()) {
+            tomcat.setConnector(configuration.connectors.iterator().next());
+        }
+
+        if (configuration.users != null) {
+            for (final Map.Entry<String, String> user : 
configuration.users.entrySet()) {
+                tomcat.addUser(user.getKey(), user.getValue());
+            }
+        }
+        if (configuration.roles != null) {
+            for (final Map.Entry<String, String> user : 
configuration.roles.entrySet()) {
+                for (final String role : user.getValue().split(" *, *")) {
+                    tomcat.addRole(user.getKey(), role);
+                }
+            }
+        }
+
+        try {
+            if (!initialized) {
+                tomcat.init();
+            }
+            tomcat.start();
+        } catch (final LifecycleException e) {
+            throw new IllegalStateException(e);
+        }
+        return this;
+    }
+
+    @Override
+    public void close() {
+        if (tomcat == null) {
+            return;
+        }
+        try {
+            tomcat.stop();
+            tomcat.destroy();
+        } catch (final LifecycleException e) {
+            throw new IllegalStateException(e);
+        } finally {
+            FileUtils.delete(base);
+        }
+    }
+
+    protected Connector createConnector() {
+        final Connector connector;
+        final Properties properties = configuration.properties;
+        if (properties != null) {
+            final Map<String, String> attributes = new HashMap<>();
+            final ObjectRecipe recipe = new ObjectRecipe(Connector.class);
+            for (final String key : properties.stringPropertyNames()) {
+                if (!key.startsWith("connector.")) {
+                    continue;
+                }
+                final String substring = key.substring("connector.".length());
+                if (!substring.startsWith("attributes.")) {
+                    recipe.setProperty(substring, properties.getProperty(key));
+                } else {
+                    
attributes.put(substring.substring("attributes.".length()), 
properties.getProperty(key));
+                }
+            }
+            connector = recipe.getProperties().isEmpty() ? new Connector() : 
Connector.class.cast(recipe.create());
+            for (final Map.Entry<String, String> attr : attributes.entrySet()) 
{
+                connector.setAttribute(attr.getKey(), attr.getValue());
+            }
+        } else {
+            connector = new Connector();
+        }
+        return connector;
+    }
+
+    private static Server createServer(final String serverXml) {
+        final Catalina catalina = new Catalina() {
+            // skip few init we don't need *here*
+            @Override
+            protected void initDirs() {
+                // no-op
+            }
+
+            @Override
+            protected void initStreams() {
+                // no-op
+            }
+
+            @Override
+            protected void initNaming() {
+                // no-op
+            }
+        };
+        catalina.setConfigFile(serverXml);
+        catalina.load();
+        return catalina.getServer();
+    }
+
+    private File createDirectory(final File parent, final String directory) {
+        final File dir = new File(parent, directory);
+        if (!dir.exists() && !dir.mkdirs()) {
+            throw new IllegalStateException("Unable to make dir " + 
dir.getAbsolutePath());
+        }
+
+        return dir;
+    }
+
+    private void synchronize(final File base, final String resourceBase) {
+        if (resourceBase == null) {
+            return;
+        }
+
+        try {
+            final Map<String, URL> urls = new 
ResourceFinder("").getResourcesMap(resourceBase);
+            for (final Map.Entry<String, URL> u : urls.entrySet()) {
+                try (final InputStream is = u.getValue().openStream()) {
+                    final File to = new File(base, u.getKey());
+                    try (final OutputStream os = new FileOutputStream(to)) {
+                        IOUtils.copy(is, os);
+                    }
+                    if ("server.xml".equals(u.getKey())) {
+                        configuration.setServerXml(to.getAbsolutePath());
+                    }
+                }
+            }
+        } catch (final IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    private String getBaseDir() {
+        File file;
+        try {
+
+            final String dir = configuration.dir;
+            if (dir != null) {
+                final File dirFile = new File(dir);
+                if (dirFile.exists()) {
+                    return dir;
+                }
+                FileUtils.mkDir(dirFile);
+                return dirFile.getAbsolutePath();
+            }
+
+            try {
+                final File target = new File("target");
+                file = File.createTempFile("microwave", "-home", 
target.exists() ? target : null);
+            } catch (final Exception e) {
+
+                final File tmp = new File(configuration.tempDir);
+                if (!tmp.exists() && !tmp.mkdirs()) {
+                    throw new IOException("Failed to create local tmp 
directory: " + tmp.getAbsolutePath());
+                }
+
+                file = File.createTempFile("microwave", "-home", tmp);
+            }
+
+            return file.getAbsolutePath();
+
+        } catch (final IOException e) {
+            throw new MicrowaveExplosion("Failed to get or create base dir: " 
+ configuration.dir, e);
+        }
+    }
+
+    @Data
+    @Accessors(fluent = true)
+    public static class Builder {
+        private int httpPort = 8080;
+        private int httpsPort = 8443;
+        private int stopPort = 8005;
+        private String host = "localhost";
+        protected String dir;
+        private File serverXml;
+        private boolean keepServerXmlAsThis;
+        private Properties properties = new Properties();
+        private boolean quickSession = true;
+        private boolean skipHttp;
+        private boolean ssl;
+        private String keystoreFile;
+        private String keystorePass;
+        private String keystoreType = "JKS";
+        private String clientAuth;
+        private String keyAlias;
+        private String sslProtocol;
+        private String webXml;
+        private LoginConfigBuilder loginConfig;
+        private Collection<SecurityConstaintBuilder> securityConstraints = new 
LinkedList<>();
+        private Realm realm;
+        private Map<String, String> users;
+        private Map<String, String> roles;
+        private boolean http2;
+        private final Collection<Connector> connectors = new ArrayList<>();
+        private String tempDir = new 
File(System.getProperty("java.io.tmpdir"), "microwave_" + 
System.nanoTime()).getAbsolutePath();
+        private boolean webResourceCached = true;
+        private String conf;
+        private boolean deleteBaseOnStartup = true;
+        private String jaxrsMapping = "/*";
+        private boolean cdiConversation;
+
+        public Builder() { // load defaults
+            loadFrom("microwave.properties");
+        }
+
+        public Builder randomHttpPort() {
+            try (final ServerSocket serverSocket = new ServerSocket(0)) {
+                this.httpPort = serverSocket.getLocalPort();
+            } catch (final IOException e) {
+                throw new IllegalStateException(e);
+            }
+            return this;
+        }
+
+        public Builder loadFrom(final String resource) {
+            try (final InputStream is = findStream(resource)) {
+                if (is != null) {
+                    final Properties config = new Properties() {{
+                        load(is);
+                    }};
+                    loadFromProperties(config);
+                }
+                return this;
+            } catch (final IOException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        public void setServerXml(final String file) {
+            if (file == null) {
+                serverXml = null;
+            } else {
+                final File sXml = new File(file);
+                if (sXml.exists()) {
+                    serverXml = sXml;
+                }
+            }
+        }
+
+        public Builder property(final String key, final String value) {
+            properties.setProperty(key, value);
+            return this;
+        }
+
+        private InputStream findStream(final String resource) throws 
FileNotFoundException {
+            InputStream stream = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
+            if (stream == null) {
+                final File file = new File(resource);
+                if (file.exists()) {
+                    return new FileInputStream(file);
+                }
+            }
+            return stream;
+        }
+
+        public Builder user(final String name, final String pwd) {
+            if (users == null) {
+                users = new HashMap<>();
+            }
+            this.users.put(name, pwd);
+            return this;
+        }
+
+        public Builder role(final String user, final String roles) {
+            if (this.roles == null) {
+                this.roles = new HashMap<>();
+            }
+            this.roles.put(user, roles);
+            return this;
+        }
+
+        public void addCustomizer(final ConfigurationCustomizer 
configurationCustomizer) {
+            configurationCustomizer.customize(this);
+        }
+
+        public void loadFromProperties(final Properties config) {
+            // filtering properties with system properties or themself
+            final StrSubstitutor strSubstitutor = new StrSubstitutor(new 
StrLookup<String>() {
+                @Override
+                public String lookup(final String key) {
+                    final String property = System.getProperty(key);
+                    return property == null ? config.getProperty(key) : null;
+                }
+            });
+            for (final String key : config.stringPropertyNames()) {
+                final String val = config.getProperty(key);
+                if (val == null || val.trim().isEmpty()) {
+                    continue;
+                }
+                final String newVal = 
strSubstitutor.replace(config.getProperty(key));
+                if (!val.equals(newVal)) {
+                    config.setProperty(key, newVal);
+                }
+            }
+
+
+            final String http = config.getProperty("http");
+            if (http != null) {
+                httpPort = Integer.parseInt(http);
+            }
+            final String https = config.getProperty("https");
+            if (https != null) {
+                httpsPort = Integer.parseInt(https);
+            }
+            final String stop = config.getProperty("stop");
+            if (stop != null) {
+                stopPort = Integer.parseInt(stop);
+            }
+            final String host = config.getProperty("host");
+            if (host != null) {
+                this.host = host;
+            }
+            final String dir = config.getProperty("dir");
+            if (dir != null) {
+                this.dir = dir;
+            }
+            final String serverXml = config.getProperty("serverXml");
+            if (serverXml != null) {
+                setServerXml(serverXml);
+            }
+            final String keepServerXmlAsThis = 
config.getProperty("keepServerXmlAsThis");
+            if (keepServerXmlAsThis != null) {
+                this.keepServerXmlAsThis = 
Boolean.parseBoolean(keepServerXmlAsThis);
+            }
+            final String quickSession = config.getProperty("quickSession");
+            if (quickSession != null) {
+                this.quickSession = Boolean.parseBoolean(quickSession);
+            }
+            final String skipHttp = config.getProperty("skipHttp");
+            if (skipHttp != null) {
+                this.skipHttp = Boolean.parseBoolean(skipHttp);
+            }
+            final String ssl = config.getProperty("ssl");
+            if (ssl != null) {
+                this.ssl = Boolean.parseBoolean(ssl);
+            }
+            final String http2 = config.getProperty("http2");
+            if (http2 != null) {
+                this.http2 = Boolean.parseBoolean(http2);
+            }
+            final String deleteBaseOnStartup = 
config.getProperty("deleteBaseOnStartup");
+            if (deleteBaseOnStartup != null) {
+                this.deleteBaseOnStartup = 
Boolean.parseBoolean(deleteBaseOnStartup);
+            }
+            final String webResourceCached = 
config.getProperty("webResourceCached");
+            if (webResourceCached != null) {
+                this.webResourceCached = 
Boolean.parseBoolean(webResourceCached);
+            }
+            final String keystoreFile = config.getProperty("keystoreFile");
+            if (keystoreFile != null) {
+                this.keystoreFile = keystoreFile;
+            }
+            final String keystorePass = config.getProperty("keystorePass");
+            if (keystorePass != null) {
+                this.keystorePass = keystorePass;
+            }
+            final String keystoreType = config.getProperty("keystoreType");
+            if (keystoreType != null) {
+                this.keystoreType = keystoreType;
+            }
+            final String clientAuth = config.getProperty("clientAuth");
+            if (clientAuth != null) {
+                this.clientAuth = clientAuth;
+            }
+            final String keyAlias = config.getProperty("keyAlias");
+            if (keyAlias != null) {
+                this.keyAlias = keyAlias;
+            }
+            final String sslProtocol = config.getProperty("sslProtocol");
+            if (sslProtocol != null) {
+                this.sslProtocol = sslProtocol;
+            }
+            final String webXml = config.getProperty("webXml");
+            if (webXml != null) {
+                this.webXml = webXml;
+            }
+            final String tempDir = config.getProperty("tempDir");
+            if (tempDir != null) {
+                this.tempDir = tempDir;
+            }
+            final String conf = config.getProperty("conf");
+            if (conf != null) {
+                this.conf = conf;
+            }
+            for (final String prop : config.stringPropertyNames()) {
+                if (prop.startsWith("properties.")) {
+                    property(prop.substring("properties.".length()), 
config.getProperty(prop));
+                } else if (prop.startsWith("users.")) {
+                    user(prop.substring("users.".length()), 
config.getProperty(prop));
+                } else if (prop.startsWith("roles.")) {
+                    role(prop.substring("roles.".length()), 
config.getProperty(prop));
+                } else if (prop.startsWith("connector.")) { // created in 
container
+                    property(prop, config.getProperty(prop));
+                } else if (prop.equals("realm")) {
+                    final ObjectRecipe recipe = new 
ObjectRecipe(config.getProperty(prop));
+                    for (final String realmConfig : 
config.stringPropertyNames()) {
+                        if (realmConfig.startsWith("realm.")) {
+                            
recipe.setProperty(realmConfig.substring("realm.".length()), 
config.getProperty(realmConfig));
+                        }
+                    }
+                    this.realm = Realm.class.cast(recipe.create());
+                } else if (prop.equals("login")) {
+                    final ObjectRecipe recipe = new 
ObjectRecipe(LoginConfigBuilder.class.getName());
+                    for (final String nestedConfig : 
config.stringPropertyNames()) {
+                        if (nestedConfig.startsWith("login.")) {
+                            
recipe.setProperty(nestedConfig.substring("login.".length()), 
config.getProperty(nestedConfig));
+                        }
+                    }
+                    loginConfig = 
LoginConfigBuilder.class.cast(recipe.create());
+                } else if (prop.equals("securityConstraint")) {
+                    final ObjectRecipe recipe = new 
ObjectRecipe(SecurityConstaintBuilder.class.getName());
+                    for (final String nestedConfig : 
config.stringPropertyNames()) {
+                        if (nestedConfig.startsWith("securityConstraint.")) {
+                            
recipe.setProperty(nestedConfig.substring("securityConstraint.".length()), 
config.getProperty(nestedConfig));
+                        }
+                    }
+                    
securityConstraints.add(SecurityConstaintBuilder.class.cast(recipe.create()));
+                } else if (prop.equals("configurationCustomizer.")) {
+                    final String next = 
prop.substring("configurationCustomizer.".length());
+                    if (next.contains(".")) {
+                        continue;
+                    }
+                    final ObjectRecipe recipe = new 
ObjectRecipe(properties.getProperty(prop + ".class"));
+                    for (final String nestedConfig : 
config.stringPropertyNames()) {
+                        if (nestedConfig.startsWith(prop) && 
!prop.endsWith(".class")) {
+                            
recipe.setProperty(nestedConfig.substring(prop.length() + 1 /*dot*/), 
config.getProperty(nestedConfig));
+                        }
+                    }
+                    
addCustomizer(ConfigurationCustomizer.class.cast(recipe.create()));
+                }
+            }
+        }
+    }
+
+    public static class LoginConfigBuilder {
+        private final LoginConfig loginConfig = new LoginConfig();
+
+        public void setErrorPage(final String errorPage) {
+            loginConfig.setErrorPage(errorPage);
+        }
+
+        public void setLoginPage(final String loginPage) {
+            loginConfig.setLoginPage(loginPage);
+        }
+
+        public void setRealmName(final String realmName) {
+            loginConfig.setRealmName(realmName);
+        }
+
+        public void setAuthMethod(final String authMethod) {
+            loginConfig.setAuthMethod(authMethod);
+        }
+
+        public LoginConfigBuilder errorPage(final String errorPage) {
+            loginConfig.setErrorPage(errorPage);
+            return this;
+        }
+
+        public LoginConfigBuilder loginPage(final String loginPage) {
+            loginConfig.setLoginPage(loginPage);
+            return this;
+        }
+
+        public LoginConfigBuilder realmName(final String realmName) {
+            loginConfig.setRealmName(realmName);
+            return this;
+        }
+
+        public LoginConfigBuilder authMethod(final String authMethod) {
+            loginConfig.setAuthMethod(authMethod);
+            return this;
+        }
+
+        public LoginConfig build() {
+            return loginConfig;
+        }
+
+        public LoginConfigBuilder basic() {
+            return authMethod("BASIC");
+        }
+
+        public LoginConfigBuilder digest() {
+            return authMethod("DIGEST");
+        }
+
+        public LoginConfigBuilder clientCert() {
+            return authMethod("CLIENT-CERT");
+        }
+
+        public LoginConfigBuilder form() {
+            return authMethod("FORM");
+        }
+    }
+
+    public static class SecurityConstaintBuilder {
+        private final SecurityConstraint securityConstraint = new 
SecurityConstraint();
+
+        public SecurityConstaintBuilder authConstraint(final boolean 
authConstraint) {
+            securityConstraint.setAuthConstraint(authConstraint);
+            return this;
+        }
+
+        public SecurityConstaintBuilder displayName(final String displayName) {
+            securityConstraint.setDisplayName(displayName);
+            return this;
+        }
+
+        public SecurityConstaintBuilder userConstraint(final String 
constraint) {
+            securityConstraint.setUserConstraint(constraint);
+            return this;
+        }
+
+        public SecurityConstaintBuilder addAuthRole(final String authRole) {
+            securityConstraint.addAuthRole(authRole);
+            return this;
+        }
+
+        public SecurityConstaintBuilder addCollection(final String name, final 
String pattern, final String... methods) {
+            final SecurityCollection collection = new SecurityCollection();
+            collection.setName(name);
+            collection.addPattern(pattern);
+            for (final String httpMethod : methods) {
+                collection.addMethod(httpMethod);
+            }
+            securityConstraint.addCollection(collection);
+            return this;
+        }
+
+        public void setAuthConstraint(final boolean authConstraint) {
+            securityConstraint.setAuthConstraint(authConstraint);
+        }
+
+        public void setDisplayName(final String displayName) {
+            securityConstraint.setDisplayName(displayName);
+        }
+
+        public void setUserConstraint(final String userConstraint) {
+            securityConstraint.setUserConstraint(userConstraint);
+        }
+
+        public void setAuthRole(final String authRole) { // easier for config
+            addAuthRole(authRole);
+        }
+
+        // name:pattern:method1/method2
+        public void setCollection(final String value) { // for config
+            final String[] split = value.split(":");
+            if (split.length != 3 && split.length != 2) {
+                throw new IllegalArgumentException("Can't parse " + value + ", 
syntax is: name:pattern:method1/method2");
+            }
+            addCollection(split[0], split[1], split.length == 2 ? new 
String[0] : split[2].split("/"));
+        }
+
+        public SecurityConstraint build() {
+            return securityConstraint;
+        }
+    }
+
+    public interface ConfigurationCustomizer {
+        void customize(Builder configuration);
+    }
+
+    private static class InternalTomcat extends Tomcat {
+        private void server(final Server s) {
+            server = s;
+            if (service == null) {
+                final Service[] services = server.findServices();
+                if (services.length > 0) {
+                    service = services[0];
+                    if (service.getContainer() != null) {
+                        engine = Engine.class.cast(service.getContainer());
+                        final org.apache.catalina.Container[] hosts = 
engine.findChildren();
+                        if (hosts.length > 0) {
+                            host = Host.class.cast(hosts[0]);
+                        }
+                    }
+                }
+                if (service.findConnectors().length > 0) {
+                    connector = service.findConnectors()[0];
+                }
+            }
+        }
+
+        public Connector getRawConnector() {
+            return connector;
+        }
+    }
+
+    private static class TomcatWithFastSessionIDs extends InternalTomcat {
+        @Override
+        public void start() throws LifecycleException {
+            // Use fast, insecure session ID generation for all tests
+            final Server server = getServer();
+            for (final Service service : server.findServices()) {
+                final org.apache.catalina.Container e = service.getContainer();
+                for (final org.apache.catalina.Container h : e.findChildren()) 
{
+                    for (final org.apache.catalina.Container c : 
h.findChildren()) {
+                        Manager m = ((org.apache.catalina.Context) 
c).getManager();
+                        if (m == null) {
+                            m = new StandardManager();
+                            
org.apache.catalina.Context.class.cast(c).setManager(m);
+                        }
+                        if (m instanceof ManagerBase) {
+                            ManagerBase.class.cast(m).setSecureRandomClass(
+                                    
"org.apache.catalina.startup.FastNonSecureRandom");
+                        }
+                    }
+                }
+            }
+            super.start();
+        }
+    }
+
+    private static class QuickServerXmlParser extends DefaultHandler {
+        private static final SAXParserFactory FACTORY = 
SAXParserFactory.newInstance();
+
+        static {
+            FACTORY.setNamespaceAware(true);
+            FACTORY.setValidating(false);
+        }
+
+        private static final String STOP_KEY = "STOP";
+        private static final String HTTP_KEY = "HTTP";
+        private static final String SECURED_SUFFIX = "S";
+        private static final String AJP_KEY = "AJP";
+        private static final String HOST_KEY = "host";
+        private static final String APP_BASE_KEY = "app-base";
+        private static final String DEFAULT_CONNECTOR_KEY = HTTP_KEY;
+        private static final String KEYSTORE_KEY = "keystoreFile";
+
+        public static final String DEFAULT_HTTP_PORT = "8080";
+        public static final String DEFAULT_HTTPS_PORT = "8443";
+        public static final String DEFAULT_STOP_PORT = "8005";
+        public static final String DEFAULT_AJP_PORT = "8009";
+        public static final String DEFAULT_HOST = "localhost";
+        public static final String DEFAULT_APP_BASE = "webapps";
+        public static final String DEFAULT_KEYSTORE = null;
+
+        private final Map<String, String> values = new TreeMap<String, 
String>(String.CASE_INSENSITIVE_ORDER);
+
+        public QuickServerXmlParser() { // ensure defaults are present
+            this(true);
+        }
+
+        public QuickServerXmlParser(final boolean useDefaults) {
+            if (useDefaults) {
+                values.put(STOP_KEY, DEFAULT_STOP_PORT);
+                values.put(HTTP_KEY, DEFAULT_HTTP_PORT);
+                values.put(AJP_KEY, DEFAULT_AJP_PORT);
+                values.put(HOST_KEY, DEFAULT_HOST);
+                values.put(APP_BASE_KEY, DEFAULT_APP_BASE);
+                values.put(KEYSTORE_KEY, DEFAULT_KEYSTORE);
+            }
+        }
+
+        @Override
+        public void startElement(final String uri, final String localName,
+                                 final String qName, final Attributes 
attributes) throws SAXException {
+            if ("Server".equalsIgnoreCase(localName)) {
+                final String port = attributes.getValue("port");
+                if (port != null) {
+                    values.put(STOP_KEY, port);
+                } else {
+                    values.put(STOP_KEY, DEFAULT_STOP_PORT);
+                }
+            } else if ("Connector".equalsIgnoreCase(localName)) {
+                String protocol = attributes.getValue("protocol");
+                if (protocol == null) {
+                    protocol = DEFAULT_CONNECTOR_KEY;
+                } else if (protocol.contains("/")) {
+                    protocol = protocol.substring(0, protocol.indexOf("/"));
+                }
+                final String port = attributes.getValue("port");
+                final String ssl = attributes.getValue("secure");
+
+                if (ssl == null || "false".equalsIgnoreCase(ssl)) {
+                    values.put(protocol.toUpperCase(), port);
+                } else {
+                    values.put(protocol.toUpperCase() + SECURED_SUFFIX, port);
+                }
+
+                final String keystore = attributes.getValue("keystoreFile");
+                if (null != keystore) {
+                    values.put(KEYSTORE_KEY, keystore);
+                }
+            } else if ("Host".equalsIgnoreCase(localName)) {
+                final String host = attributes.getValue("name");
+                if (host != null) {
+                    values.put(HOST_KEY, host);
+                }
+
+                final String appBase = attributes.getValue("appBase");
+                if (appBase != null) {
+                    values.put(APP_BASE_KEY, appBase);
+                }
+            }
+        }
+
+        public static QuickServerXmlParser parse(final File serverXml) {
+            return parse(serverXml, true);
+        }
+
+        public static QuickServerXmlParser parse(final File serverXml, final 
boolean defaults) {
+            final QuickServerXmlParser handler = new 
QuickServerXmlParser(defaults);
+            try {
+                final SAXParser parser = FACTORY.newSAXParser();
+                parser.parse(serverXml, handler);
+            } catch (final Exception e) {
+                // no-op: using defaults
+            }
+            return handler;
+        }
+
+        public static QuickServerXmlParser parse(final String 
serverXmlContents) {
+            final QuickServerXmlParser handler = new QuickServerXmlParser();
+            try {
+                final SAXParser parser = FACTORY.newSAXParser();
+                parser.parse(new 
ByteArrayInputStream(serverXmlContents.getBytes()), handler);
+            } catch (final Exception e) {
+                // no-op: using defaults
+            }
+            return handler;
+        }
+
+        public String http() {
+            return value(HTTP_KEY, DEFAULT_HTTP_PORT);
+        }
+
+        public String https() { // enough common to be exposed as method
+            return securedValue(HTTP_KEY, DEFAULT_HTTPS_PORT);
+        }
+
+        public String ajp() {
+            return value(AJP_KEY, DEFAULT_AJP_PORT);
+        }
+
+        public String stop() {
+            return value(STOP_KEY, DEFAULT_STOP_PORT);
+        }
+
+        public String appBase() {
+            return value(APP_BASE_KEY, DEFAULT_APP_BASE);
+        }
+
+        public String host() {
+            return value(HOST_KEY, DEFAULT_HOST);
+        }
+
+        public String keystore() {
+            return value(KEYSTORE_KEY, DEFAULT_KEYSTORE);
+        }
+
+        public String value(final String key, final String defaultValue) {
+            final String val = values.get(key);
+            if (val == null) {
+                return defaultValue;
+            }
+            return val;
+        }
+
+        public String securedValue(final String key, final String 
defaultValue) {
+            return value(key + SECURED_SUFFIX, defaultValue);
+        }
+
+        @Override
+        public String toString() {
+            return "QuickServerXmlParser: " + values;
+        }
+    }
+
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/MicrowaveExplosion.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/MicrowaveExplosion.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/MicrowaveExplosion.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/MicrowaveExplosion.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,25 @@
+/*
+ * 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.microwave;
+
+public class MicrowaveExplosion extends RuntimeException {
+    public MicrowaveExplosion(final String msg, final Exception e) {
+        super(msg, e);
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/BusInstance.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/BusInstance.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/BusInstance.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/BusInstance.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,33 @@
+/*
+ * 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.microwave.cxf;
+
+import lombok.experimental.Delegate;
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.extension.ExtensionManagerBus;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+
+@Named("cxf")
+@ApplicationScoped
+public class BusInstance implements Bus {
+    @Delegate
+    private Bus delegate = new ExtensionManagerBus();
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/CxfCdiAutoSetup.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/CxfCdiAutoSetup.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/CxfCdiAutoSetup.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/CxfCdiAutoSetup.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,72 @@
+/*
+ * 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.microwave.cxf;
+
+import org.apache.cxf.cdi.CXFCdiServlet;
+import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
+import org.apache.cxf.transport.ChainInitiationObserver;
+import org.apache.johnzon.jaxrs.DelegateProvider;
+import org.apache.johnzon.jaxrs.JohnzonProvider;
+import org.apache.johnzon.jaxrs.JsrProvider;
+import org.apache.microwave.Microwave;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+public class CxfCdiAutoSetup implements ServletContainerInitializer {
+    @Override
+    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) 
throws ServletException {
+        final Microwave.Builder builder = 
Microwave.Builder.class.cast(ctx.getAttribute("microwave.configuration"));
+        final ServletRegistration.Dynamic jaxrs = ctx.addServlet("cxf-cdi", 
new CXFCdiServlet() {
+            @Override
+            protected void loadBus(final ServletConfig servletConfig) {
+                super.loadBus(servletConfig);
+                if 
(!"true".equalsIgnoreCase(builder.properties().getProperty("microwave.jaxrs.providers.setup",
 "true"))) {
+                    return;
+                }
+
+                final List<DelegateProvider<?>> providers = asList(new 
JohnzonProvider<>(), new JsrProvider());
+
+                // client
+                if (bus.getProperty("org.apache.cxf.jaxrs.bus.providers") == 
null) {
+                    bus.setProperty("skip.default.json.provider.registration", 
"true");
+                    bus.setProperty("org.apache.cxf.jaxrs.bus.providers", 
providers);
+                }
+
+                // server
+                getDestinationRegistryFromBus().getDestinations()
+                        .forEach(d -> {
+                            final ChainInitiationObserver observer = 
ChainInitiationObserver.class.cast(d.getMessageObserver());
+                            final ServerProviderFactory providerFactory = 
ServerProviderFactory.class.cast(observer.getEndpoint().get(ServerProviderFactory.class.getName()));
+                            providerFactory.setUserProviders(providers);
+                        });
+            }
+        });
+        jaxrs.setLoadOnStartup(1);
+        jaxrs.setAsyncSupported(true);
+        jaxrs.addMapping(builder.jaxrsMapping());
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/JAXRSCdiResourceExtensionWorkaround.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/JAXRSCdiResourceExtensionWorkaround.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/JAXRSCdiResourceExtensionWorkaround.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/cxf/JAXRSCdiResourceExtensionWorkaround.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,41 @@
+/*
+ * 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.microwave.cxf;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.cdi.JAXRSCdiResourceExtension;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.BeanManager;
+
+// just there to ensure we use a single bus even for 
ResourceUtils.createApplication, should be removed with 3.1.9 hopefully
+public class JAXRSCdiResourceExtensionWorkaround extends 
JAXRSCdiResourceExtension {
+    @Override
+    public void load(@Observes final AfterDeploymentValidation event, final 
BeanManager beanManager) {
+        final Bus bus = 
Bus.class.cast(beanManager.getReference(beanManager.resolve(beanManager.getBeans(Bus.class)),
 Bus.class, null));
+        BusFactory.setThreadDefaultBus(bus); // cause app class will rely on 
that and would create multiple bus and then deployment would be broken
+        try {
+            super.load(event, beanManager);
+        } finally {
+            BusFactory.clearDefaultBusForAnyThread(bus);
+        }
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/MicrowaveLoader.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/MicrowaveLoader.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/MicrowaveLoader.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/MicrowaveLoader.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,52 @@
+/*
+ * 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.microwave.openwebbeans;
+
+import org.apache.cxf.cdi.JAXRSCdiResourceExtension;
+import org.apache.webbeans.service.DefaultLoaderService;
+import org.apache.webbeans.spi.LoaderService;
+
+import javax.enterprise.inject.spi.Extension;
+import java.util.Iterator;
+import java.util.List;
+
+// just there to get rid of the original cxf extension, to remove with 3.1.9 
hopefully
+public class MicrowaveLoader implements LoaderService {
+    private final LoaderService defaultService = new DefaultLoaderService();
+
+    @Override
+    public <T> List<T> load(final Class<T> serviceType) {
+        return defaultService.load(serviceType);
+    }
+
+    @Override
+    public <T> List<T> load(final Class<T> serviceType, final ClassLoader 
classLoader) {
+        final List<T> load = defaultService.load(serviceType, classLoader);
+        if (Extension.class == serviceType) {
+            final Iterator<T> e = load.iterator();
+            while (e.hasNext()) {
+                if (JAXRSCdiResourceExtension.class == e.next().getClass()) {
+                    e.remove();
+                    break;
+                }
+            }
+        }
+        return load;
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/OWBAutoSetup.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/OWBAutoSetup.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/OWBAutoSetup.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/openwebbeans/OWBAutoSetup.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,43 @@
+/*
+ * 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.microwave.openwebbeans;
+
+import org.apache.microwave.Microwave;
+import org.apache.webbeans.servlet.WebBeansConfigurationListener;
+import org.apache.webbeans.web.context.WebConversationFilter;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.FilterRegistration;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import java.util.EnumSet;
+import java.util.Set;
+
+public class OWBAutoSetup implements ServletContainerInitializer {
+    @Override
+    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) 
throws ServletException {
+        final Microwave.Builder builder = 
Microwave.Builder.class.cast(ctx.getAttribute("microwave.configuration"));
+        if (builder.cdiConversation()) {
+            final FilterRegistration.Dynamic filter = 
ctx.addFilter("owb-conversation", WebConversationFilter.class);
+            
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, 
"/*");
+        }
+        ctx.addListener(WebBeansConfigurationListener.class);
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/ProvidedLoader.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/ProvidedLoader.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/ProvidedLoader.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/java/org/apache/microwave/tomcat/ProvidedLoader.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,89 @@
+/*
+ * 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.microwave.tomcat;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Loader;
+
+import java.beans.PropertyChangeListener;
+
+public class ProvidedLoader implements Loader {
+    private final ClassLoader delegate;
+    private Context context;
+
+    public ProvidedLoader(final ClassLoader loader) {
+        this.delegate = loader == null ? ClassLoader.getSystemClassLoader() : 
loader;
+    }
+
+    @Override
+    public void backgroundProcess() {
+        // no-op
+    }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return delegate;
+    }
+
+    @Override
+    public Context getContext() {
+        return context;
+    }
+
+    @Override
+    public void setContext(final Context context) {
+        this.context = context;
+    }
+
+    @Override
+    public boolean modified() {
+        return false;
+    }
+
+    @Override
+    public boolean getDelegate() {
+        return false;
+    }
+
+    @Override
+    public void setDelegate(final boolean delegate) {
+        // ignore
+    }
+
+    @Override
+    public boolean getReloadable() {
+        return false;
+    }
+
+    @Override
+    public void setReloadable(final boolean reloadable) {
+        // no-op
+    }
+
+    @Override
+    public void addPropertyChangeListener(final PropertyChangeListener 
listener) {
+        // no-op
+    }
+
+    @Override
+    public void removePropertyChangeListener(final PropertyChangeListener 
listener) {
+        // no-op
+    }
+}
+

Added: openwebbeans/microwave/trunk/src/main/resources/META-INF/beans.xml
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/resources/META-INF/beans.xml?rev=1765505&view=auto
==============================================================================
--- openwebbeans/microwave/trunk/src/main/resources/META-INF/beans.xml (added)
+++ openwebbeans/microwave/trunk/src/main/resources/META-INF/beans.xml Tue Oct 
18 20:49:19 2016
@@ -0,0 +1,19 @@
+<!--
+    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.
+-->
+<beans />

Added: 
openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/openwebbeans.properties
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/openwebbeans.properties?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/openwebbeans.properties
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/resources/META-INF/openwebbeans/openwebbeans.properties
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,91 @@
+#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.
+configuration.ordinal=1000
+org.apache.webbeans.spi.LoaderService=org.apache.microwave.openwebbeans.MicrowaveLoader
+org.apache.webbeans.scanExclusionPaths=\
+        /jre/lib, \
+        /Contents/Home/, \
+        /dt.jar, \
+        /tools.jar, \
+        /bootstrap.jar, \
+        /asm, \
+        /javassist, \
+        /xbean-, \
+        /jconsole.jar, \
+        /geronimo-, \
+        /commons-, \
+        /arquillian-, \
+        /bsh-, \
+        /shrinkwrap-, \
+        /junit-, \
+        /testng-, \
+        /openjpa-, \
+        /bcel, \
+        /hamcrest, \
+        /mysql-connector, \
+        /testng, \
+        /idea_rt, \
+        /eclipse, \
+        /jcommander, \
+        /tomcat, \
+        /catalina, \
+        /jasper, \
+        /jsp-api, \
+        /myfaces-api, \
+        /myfaces-impl, \
+        /servlet-api, \
+        /javax, \
+        /annotation-api, \
+        /el-api, \
+        /mojarra, \
+        /sisu-guice-, \
+        /sisu-inject-, \
+        /aether-, \
+        /plexus-, \
+        /maven-, \
+        /guava-, \
+        /openwebbeans-, \
+        /bcprov-jdk14-, \
+        /bcmail-jdk14-, \
+        /bctsp-jdk14-, \
+        /bcmail-jdk14-, \
+        /ss_css2-, \
+        /itext-, \
+        /pd4ml-, \
+        /xmlpull-, \
+        /log4j-, \
+        /slf4j-, \
+        /logkit, \
+        /gson-, \
+        /xstream-, \
+        /httpclient-, \
+        /httpcore-, \
+        /backport-util-concurrent-, \
+        /xml-apis, \
+        /xpp3_min-, \
+        /bval-core, \
+        /bval-jsr, \
+        /hsqldb, \
+        /quartz-2, \
+        /jetty-, \
+        /plexus-,\
+        /johnzon-,\
+        /cxf-,\
+        /woodstox-,\
+        /stax,\
+        /xmlschema,\
+        /lombok

Added: 
openwebbeans/microwave/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
 (added)
+++ 
openwebbeans/microwave/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1 @@
+org.apache.microwave.cxf.JAXRSCdiResourceExtensionWorkaround

Added: 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/MicrowaveTest.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/MicrowaveTest.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/MicrowaveTest.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/MicrowaveTest.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,79 @@
+/*
+ * 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.microwave;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.microwave.app.Endpoint;
+import org.apache.microwave.app.RsApp;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.stream.Stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class MicrowaveTest {
+    @Test
+    public void simpleWebapp() {
+        final File root = new File("target/MicrowaveTest/simpleWebapp/app");
+        FileUtils.mkDir(root);
+        Stream.of(Endpoint.class, RsApp.class).forEach(type -> {
+            final String target = type.getName().replace(".", "/");
+            File targetFile = new File(root, "WEB-INF/classes/" + target + 
".class");
+            FileUtils.mkDir(targetFile.getParentFile());
+            try (final InputStream from = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(target + 
".class");
+                 final OutputStream to = new FileOutputStream(targetFile)) {
+                IOUtils.copy(from, to);
+            } catch (final IOException e) {
+                fail();
+            }
+        });
+        try (final Microwave microwave = new Microwave(new 
Microwave.Builder().randomHttpPort()).start()) {
+            microwave.deployWebapp("", root);
+            assertEquals("simple", IOUtils.toString(new 
URL("http://localhost:"; + microwave.getConfiguration().httpPort() + 
"/api/test")));
+        } catch (final IOException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public void classpath() {
+        try (final Microwave microwave = new Microwave(new 
Microwave.Builder().randomHttpPort()).bake()) {
+            assertEquals("simple", IOUtils.toString(new 
URL("http://localhost:"; + microwave.getConfiguration().httpPort() + 
"/api/test")));
+        } catch (final IOException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public void json() {
+        try (final Microwave microwave = new Microwave(new 
Microwave.Builder().randomHttpPort()).bake()) {
+            assertEquals("{\"name\":\"test\"}", IOUtils.toString(new 
URL("http://localhost:"; + microwave.getConfiguration().httpPort() + 
"/api/test/json")));
+        } catch (final IOException e) {
+            fail(e.getMessage());
+        }
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/Endpoint.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/Endpoint.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/Endpoint.java
 (added)
+++ 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/Endpoint.java
 Tue Oct 18 20:49:19 2016
@@ -0,0 +1,53 @@
+/*
+ * 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.microwave.app;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Path("test")
+@ApplicationScoped
+public class Endpoint {
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String simple() {
+        return "simple";
+    }
+
+    @GET
+    @Path("json")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Simple json() {
+        return new Simple("test");
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Simple {
+        private String name;
+    }
+}

Added: 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/RsApp.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/RsApp.java?rev=1765505&view=auto
==============================================================================
--- 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/RsApp.java 
(added)
+++ 
openwebbeans/microwave/trunk/src/test/java/org/apache/microwave/app/RsApp.java 
Tue Oct 18 20:49:19 2016
@@ -0,0 +1,28 @@
+/*
+ * 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.microwave.app;
+
+import javax.enterprise.context.Dependent;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@Dependent
+@ApplicationPath("api")
+public class RsApp extends Application {
+}


Reply via email to