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 2016/04/17 20:05:47 UTC

tomee git commit: TOMEE-1780 TOMEE-1781 gradle tomee embedded plugin + slf4j upgrade

Repository: tomee
Updated Branches:
  refs/heads/master 9cae46622 -> 24900b1e3


TOMEE-1780 TOMEE-1781 gradle tomee embedded plugin + slf4j upgrade


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/24900b1e
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/24900b1e
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/24900b1e

Branch: refs/heads/master
Commit: 24900b1e314b9186e50d2fcf7190d65f9387ac85
Parents: 9cae466
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Sun Apr 17 20:05:22 2016 +0200
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Sun Apr 17 20:05:22 2016 +0200

----------------------------------------------------------------------
 gradle/gradle-tomee-embedded/pom.xml            |  36 +
 .../gradle/embedded/TomEEEmbeddedExtension.java |  56 ++
 .../gradle/embedded/TomEEEmbeddedPlugin.java    |  65 ++
 .../gradle/embedded/TomEEEmbeddedTask.java      | 698 +++++++++++++++++++
 .../classloader/FilterGradleClassLoader.java    | 124 ++++
 .../org.apache.tomee.tomee-embedded.properties  |  17 +
 gradle/pom.xml                                  |  60 ++
 pom.xml                                         |   5 +-
 8 files changed, 1060 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/pom.xml
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/pom.xml b/gradle/gradle-tomee-embedded/pom.xml
new file mode 100644
index 0000000..d9fc6b5
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/pom.xml
@@ -0,0 +1,36 @@
+<?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>gradle</artifactId>
+    <groupId>org.apache.tomee.gradle</groupId>
+    <version>7.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>tomee-embedded</artifactId>
+  <name>OpenEJB :: Gradle Plugins :: TomEE Embedded</name>
+
+  <dependencies>
+    <!-- don't put any tomee dependency there -->
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedExtension.java
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedExtension.java b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedExtension.java
new file mode 100644
index 0000000..d27609f
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedExtension.java
@@ -0,0 +1,56 @@
+/*
+ * 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.tomee.gradle.embedded;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+public class TomEEEmbeddedExtension {
+    public static final String NAME = "tomee-embedded";
+
+    private boolean skipDefaultRepository = false;
+    private String tomeeVersion;
+
+    public boolean isSkipDefaultRepository() {
+        return skipDefaultRepository;
+    }
+
+    public void setSkipDefaultRepository(final boolean skipDefaultRepository) {
+        this.skipDefaultRepository = skipDefaultRepository;
+    }
+
+    public String getTomeeVersion() {
+        if (tomeeVersion == null) {
+            tomeeVersion = "7.0.0-M3";
+            try {
+                try (final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/maven/org.apache.tomee.gradle/tomee-embedded/pom.properties")) {
+                    final Properties p = new Properties();
+                    p.load(is);
+                    tomeeVersion = p.getProperty("version", tomeeVersion);
+                }
+            } catch (IOException e) {
+                // no-op
+            }
+        }
+        return tomeeVersion;
+    }
+
+    public void setTomeeVersion(final String tomeeVersion) {
+        this.tomeeVersion = tomeeVersion;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedPlugin.java
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedPlugin.java b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedPlugin.java
new file mode 100644
index 0000000..90d9d0d
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedPlugin.java
@@ -0,0 +1,65 @@
+/*
+ * 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.tomee.gradle.embedded;
+
+import org.gradle.api.Action;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.DependencySet;
+import org.gradle.api.artifacts.ResolvableDependencies;
+import org.gradle.api.artifacts.dsl.DependencyHandler;
+
+import java.util.HashMap;
+
+/**
+ * Custom dependencies can be added using the scope "tomee-embedded".
+ */
+public class TomEEEmbeddedPlugin implements Plugin<Project> {
+    @Override
+    public void apply(final Project project) {
+        project.getExtensions().create(TomEEEmbeddedExtension.NAME, TomEEEmbeddedExtension.class);
+
+        project.afterEvaluate(new Action<Project>() {
+            @Override
+            public void execute(final Project actionProject) {
+                final TomEEEmbeddedExtension extension = actionProject.getExtensions().findByType(TomEEEmbeddedExtension.class);
+                if (!extension.isSkipDefaultRepository()) {
+                    actionProject.getRepositories().mavenCentral();
+                }
+            }
+        });
+
+        final Configuration configuration = project.getConfigurations().maybeCreate(TomEEEmbeddedExtension.NAME);
+        configuration.getIncoming().beforeResolve(new Action<ResolvableDependencies>() {
+            @Override
+            public void execute(final ResolvableDependencies resolvableDependencies) {
+                final DependencyHandler dependencyHandler = project.getDependencies();
+                final DependencySet dependencies = configuration.getDependencies();
+                dependencies.add(dependencyHandler.create("org.apache.tomee:tomee-embedded:" +
+                        project.getExtensions().findByType(TomEEEmbeddedExtension.class).getTomeeVersion()));
+            }
+        });
+
+        project.task(new HashMap<String, Object>() {{
+            put("type", TomEEEmbeddedTask.class);
+            put("group", "Embedded Application Server");
+            put("description", "Start an embedded Apache TomEE server deploying application classpath");
+        }}, TomEEEmbeddedExtension.NAME);
+        TomEEEmbeddedTask.class.cast(project.getTasks().findByName(TomEEEmbeddedExtension.NAME)).setClasspath(configuration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedTask.java
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedTask.java b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedTask.java
new file mode 100644
index 0000000..bfeb868
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/TomEEEmbeddedTask.java
@@ -0,0 +1,698 @@
+/*
+ * 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.tomee.gradle.embedded;
+
+import org.apache.tomee.gradle.embedded.classloader.FilterGradleClassLoader;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.GradleException;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.logging.LogLevel;
+import org.gradle.api.logging.LoggingManager;
+import org.gradle.api.tasks.Input;
+import org.gradle.api.tasks.Optional;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.util.GFileUtils;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+
+public class TomEEEmbeddedTask extends DefaultTask {
+    @Optional
+    @Input
+    private int httpPort = 8080;
+
+    @Optional
+    @Input
+    private int httpsPort = 8443;
+
+    @Optional
+    @Input
+    private int ajpPort = 8009;
+
+    @Optional
+    @Input
+    private int stopPort = 8005;
+
+    @Optional
+    @Input
+    private String host = "localhost";
+
+    @Optional
+    @Input
+    private String keystoreFile;
+
+    @Optional
+    @Input
+    private String keystorePass;
+
+    @Optional
+    @Input
+    private String keystoreType = "JKS";
+
+    @Optional
+    @Input
+    private String clientAuth;
+
+    @Optional
+    @Input
+    private String keyAlias;
+
+    @Optional
+    @Input
+    private String sslProtocol;
+
+    @Optional
+    @Input
+    private File serverXml;
+
+    @Optional
+    @Input
+    private boolean ssl = false;
+
+    @Optional
+    @Input
+    private boolean withEjbRemote = false;
+
+    @Optional
+    @Input
+    private boolean quickSession = true;
+
+    @Optional
+    @Input
+    private boolean skipHttp = false;
+
+    @Optional
+    @Input
+    private Collection<String> applicationScopes = new HashSet<>(asList("compile", "runtime"));
+
+    @Optional
+    @Input
+    private boolean webResourceCached = true;
+
+    @Optional
+    @Input
+    private String context = null;
+
+    @Optional
+    @Input
+    private Map<String, String> containerProperties;
+
+    @Optional
+    @Input
+    private boolean keepServerXmlAsThis = false;
+
+    @Optional
+    @Input
+    private Map<String, String> users;
+
+    @Optional
+    @Input
+    private Map<String, String> roles;
+
+    @Optional
+    @Input
+    private boolean forceJspDevelopment = true;
+
+    @Optional
+    @Input
+    private String inlinedServerXml;
+
+    @Optional
+    @Input
+    private String inlinedTomEEXml;
+
+    @Optional
+    @Input
+    private File workDir;
+
+    @Optional
+    @Input
+    private List<File> modules;
+
+    @Optional
+    @Input
+    private File docBase;
+
+    @Optional
+    @Input
+    private String dir;
+
+    @Optional
+    @Input
+    private LogLevel logLevel = LogLevel.INFO;
+
+    /* TODO if needed
+    @Parameter //a dvanced config but a simple boolean will be used for defaults (withLiveReload)
+    private LiveReload liveReload;
+
+    @Parameter(property = "tomee-plugin.liveReload", defaultValue = "false")
+    private boolean withLiveReload;
+     */
+
+    private Configuration classpath;
+
+    @TaskAction
+    public void runTomEEEmbedded() {
+        fixConfig();
+
+        final Thread thread = Thread.currentThread();
+        final ClassLoader tccl = thread.getContextClassLoader();
+        final LoggingManager logging = getProject().getLogging();
+        final LogSetup logSetup = new LogSetup(logging, logging.getStandardOutputCaptureLevel(), logging.getStandardErrorCaptureLevel(), logLevel).init();
+        logging.setLevel(logLevel);
+        thread.setContextClassLoader(createLoader(tccl));
+        try {
+            doRun();
+        } finally {
+            thread.setContextClassLoader(tccl);
+            logSetup.reset();
+        }
+    }
+
+    private void fixConfig() {
+        final Project project = getProject();
+
+        // final TomEEEmbeddedExtension extension = TomEEEmbeddedExtension.class.cast(project.findProject(TomEEEmbeddedExtension.NAME));
+
+        if (classpath == null) {
+            classpath = project.getConfigurations().getByName(TomEEEmbeddedExtension.NAME);
+        }
+
+        if (docBase == null) {
+            docBase = new File(project.getProjectDir(), "src/main/webapp");
+        }
+        if (workDir == null) {
+            workDir = new File(project.getBuildDir(), "tomee-embedded/work");
+        }
+        if (dir == null) {
+            dir = new File(project.getBuildDir(), "tomee-embedded/run").getAbsolutePath();
+        }
+        if (modules == null || modules.isEmpty()) {
+            final File main = new File(project.getBuildDir(), "classes/main");
+            if (main.isDirectory()) {
+                modules = new ArrayList<>(singletonList(main));
+            }
+        }
+    }
+
+    private void doRun() {
+        final Properties originalSystProp = new Properties();
+        originalSystProp.putAll(System.getProperties());
+
+        final Thread thread = Thread.currentThread();
+        final ClassLoader loader = thread.getContextClassLoader();
+
+        if (inlinedServerXml != null && !inlinedServerXml.trim().isEmpty()) {
+            if (serverXml != null && serverXml.exists()) {
+                throw new GradleException("you can't define a server.xml and an inlinedServerXml");
+            }
+            try {
+                GFileUtils.mkdirs(workDir);
+                serverXml = new File(workDir, "server.xml_dump");
+                GFileUtils.writeFile(inlinedServerXml, serverXml);
+            } catch (final Exception e) {
+                throw new GradleException(e.getMessage(), e);
+            }
+        }
+
+        final AtomicBoolean running = new AtomicBoolean();
+        AutoCloseable container;
+        Thread hook;
+        try {
+            final Class<?> containerClass = loader.loadClass("org.apache.tomee.embedded.Container");
+            final Class<?> configClass = loader.loadClass("org.apache.tomee.embedded.Configuration");
+            final Class<?> parentLoaderFinderClass = loader.loadClass("org.apache.openejb.core.ParentClassLoaderFinder");
+            final Class<?> loaderFinderClass = loader.loadClass("org.apache.openejb.core.ProvidedClassLoaderFinder");
+            final Class<?> systemInstanceClass = loader.loadClass("org.apache.openejb.loader.SystemInstance");
+
+            container = AutoCloseable.class.cast(containerClass.newInstance());
+            final Object config = getConfig(configClass);
+
+            containerClass.getMethod("setup", configClass).invoke(container, config);
+
+            if (inlinedTomEEXml != null && inlinedTomEEXml.trim().isEmpty()) {
+                try {
+                    final File conf = new File(dir, "conf");
+                    GFileUtils.mkdirs(conf);
+                    GFileUtils.writeFile(inlinedTomEEXml, new File(conf, "tomee.xml"));
+                } catch (final Exception e) {
+                    throw new GradleException(e.getMessage(), e);
+                }
+            }
+
+            final AutoCloseable finalContainer = container;
+            hook = new Thread() {
+                @Override
+                public void run() {
+                    if (running.compareAndSet(true, false)) {
+                        final Thread thread = Thread.currentThread();
+                        final ClassLoader old = thread.getContextClassLoader();
+                        thread.setContextClassLoader(loader);
+                        try {
+                            finalContainer.close();
+                        } catch (final NoClassDefFoundError noClassDefFoundError) {
+                            // debug cause it is too late to shutdown properly so don't pollute logs
+                            getLogger().debug("can't stop TomEE", noClassDefFoundError);
+                        } catch (final Exception e) {
+                            getLogger().error("can't stop TomEE", e);
+                        } finally {
+                            thread.setContextClassLoader(old);
+                        }
+                    }
+                }
+            };
+            hook.setName("TomEE-Embedded-ShutdownHook");
+
+            running.set(true); // yes should be done after but we can't help much if we don't do it there for auto shutdown
+            containerClass.getMethod("start").invoke(container);
+
+            // SystemInstance.get().setComponent(ParentClassLoaderFinder.class, new ProvidedClassLoaderFinder(loader));
+            final Object providedLoaderFinder = loaderFinderClass.getConstructor(ClassLoader.class).newInstance(loader);
+            final Object systemInstance = systemInstanceClass.getMethod("get").invoke(null);
+            systemInstanceClass.getMethod("setComponent", Class.class, Object.class)
+                    .invoke(systemInstance, parentLoaderFinderClass, providedLoaderFinder);
+
+            Runtime.getRuntime().addShutdownHook(hook);
+
+            containerClass.getMethod("deployClasspathAsWebApp", String.class, File.class, String[].class).invoke(container, context, docBase, new String[0]);
+
+            getLogger().info("TomEE embedded started on " + configClass.getMethod("getHost").invoke(config) + ":" + configClass.getMethod("getHttpPort").invoke(config));
+        } catch (final Exception e) {
+            throw new GradleException(e.getMessage(), e);
+        }
+
+
+        // installLiveReloadEndpointIfNeeded();
+
+        try {
+            String line;
+            final Scanner scanner = new Scanner(System.in);
+            while ((line = scanner.nextLine()) != null) {
+                switch (line.trim()) {
+                    case "exit":
+                    case "quit":
+                        running.set(false);
+                        Runtime.getRuntime().removeShutdownHook(hook);
+                        container.close();
+                        return;
+                }
+            }
+        } catch (final Exception e) {
+            Thread.interrupted();
+        } finally {
+            thread.setContextClassLoader(loader);
+            System.setProperties(originalSystProp);
+        }
+    }
+
+    private Object getConfig(final Class<?> configClass) throws Exception {
+        final Object config = configClass.newInstance();
+        for (final Field field : getClass().getDeclaredFields()) {
+            try {
+                final Field configField = Configuration.class.getDeclaredField(field.getName());
+                field.setAccessible(true);
+                configField.setAccessible(true);
+
+                final Object value = field.get(this);
+                if (value != null) {
+                    configField.set(config, value);
+                    getLogger().debug("using " + field.getName() + " = " + value);
+                }
+            } catch (final NoSuchFieldException nsfe) {
+                // ignored
+            } catch (final Exception e) {
+                getLogger().warn("can't initialize attribute " + field.getName());
+            }
+        }
+        if (containerProperties == null) {
+            containerProperties = new HashMap<>();
+        }
+        if (forceJspDevelopment) {
+            containerProperties.put("tomee.jsp-development", "true");
+        }
+
+        containerProperties.put("openejb.log.factory", "slf4j"); // like gradle
+
+        { // ensure we don't scan gradle
+            final String original = containerProperties.get("openejb.additional.exclude");
+            final String additional =
+                    "gradle,ant,jna,native-platform,reflectasm,bsh,jetty,rhino," +
+                            "aws,core-3,bcpg,jsch,pmaven,sonar,bndlib,jatl,simple-,snakeyaml,jcl-over-slf4j,ivy," +
+                            "jarjar,jul-to-slf4j,jaxen,minlog,jcip-annotations,kryo,objenesis";
+            if (original == null) {
+                containerProperties.put("openejb.additional.exclude", additional);
+            } else {
+                containerProperties.put("openejb.additional.exclude", original + ',' + additional);
+            }
+        }
+        if (containerProperties != null) {
+            final Properties props = new Properties();
+            props.putAll(containerProperties);
+            configClass.getMethod("setProperties", Properties.class)
+                    .invoke(config, props);
+        }
+        return config;
+    }
+
+    private ClassLoader createLoader(final ClassLoader parent) {
+        getLogger().info("Resolving tomee-embedded classpath...");
+
+        final Collection<URL> urls = new LinkedHashSet<>(64);
+
+        addFiles(modules, urls);
+
+        for (final Configuration cc : getProject().getConfigurations()) {
+            if (applicationScopes.contains(cc.getName())) {
+                addFiles(cc.getFiles(), urls);
+            }
+        }
+
+        addFiles(classpath.getFiles(), urls);
+
+        // use JVM loader to avoid the noise of gradle and its plugins
+        return new URLClassLoader(urls.toArray(new URL[urls.size()]), new FilterGradleClassLoader(parent));
+    }
+
+    private void addFiles(final Collection<File> files, final Collection<URL> urls) {
+        if (files == null || files.isEmpty()) {
+            return;
+        }
+        for (final File f : files) {
+            final String name = f.getName();
+            if (name.startsWith("slf4j-api") || name.startsWith("slf4j-jdk14")) {
+                continue; // use gradle
+            }
+            try {
+                urls.add(f.toURI().toURL());
+            } catch (final MalformedURLException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+    }
+
+    public int getHttpPort() {
+        return httpPort;
+    }
+
+    public void setHttpPort(final int httpPort) {
+        this.httpPort = httpPort;
+    }
+
+    public int getHttpsPort() {
+        return httpsPort;
+    }
+
+    public void setHttpsPort(final int httpsPort) {
+        this.httpsPort = httpsPort;
+    }
+
+    public int getAjpPort() {
+        return ajpPort;
+    }
+
+    public void setAjpPort(final int ajpPort) {
+        this.ajpPort = ajpPort;
+    }
+
+    public int getStopPort() {
+        return stopPort;
+    }
+
+    public void setStopPort(final int stopPort) {
+        this.stopPort = stopPort;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(final String host) {
+        this.host = host;
+    }
+
+    public String getKeystoreFile() {
+        return keystoreFile;
+    }
+
+    public void setKeystoreFile(final String keystoreFile) {
+        this.keystoreFile = keystoreFile;
+    }
+
+    public String getKeystorePass() {
+        return keystorePass;
+    }
+
+    public void setKeystorePass(final String keystorePass) {
+        this.keystorePass = keystorePass;
+    }
+
+    public String getKeystoreType() {
+        return keystoreType;
+    }
+
+    public void setKeystoreType(final String keystoreType) {
+        this.keystoreType = keystoreType;
+    }
+
+    public String getClientAuth() {
+        return clientAuth;
+    }
+
+    public void setClientAuth(final String clientAuth) {
+        this.clientAuth = clientAuth;
+    }
+
+    public String getKeyAlias() {
+        return keyAlias;
+    }
+
+    public void setKeyAlias(final String keyAlias) {
+        this.keyAlias = keyAlias;
+    }
+
+    public String getSslProtocol() {
+        return sslProtocol;
+    }
+
+    public void setSslProtocol(final String sslProtocol) {
+        this.sslProtocol = sslProtocol;
+    }
+
+    public File getServerXml() {
+        return serverXml;
+    }
+
+    public void setServerXml(final File serverXml) {
+        this.serverXml = serverXml;
+    }
+
+    public boolean isSsl() {
+        return ssl;
+    }
+
+    public void setSsl(final boolean ssl) {
+        this.ssl = ssl;
+    }
+
+    public boolean isWithEjbRemote() {
+        return withEjbRemote;
+    }
+
+    public void setWithEjbRemote(final boolean withEjbRemote) {
+        this.withEjbRemote = withEjbRemote;
+    }
+
+    public boolean isQuickSession() {
+        return quickSession;
+    }
+
+    public void setQuickSession(final boolean quickSession) {
+        this.quickSession = quickSession;
+    }
+
+    public boolean isSkipHttp() {
+        return skipHttp;
+    }
+
+    public void setSkipHttp(final boolean skipHttp) {
+        this.skipHttp = skipHttp;
+    }
+
+    public Collection<String> getApplicationScopes() {
+        return applicationScopes;
+    }
+
+    public void setApplicationScopes(final Collection<String> applicationScopes) {
+        this.applicationScopes = applicationScopes;
+    }
+
+    public boolean isWebResourceCached() {
+        return webResourceCached;
+    }
+
+    public void setWebResourceCached(final boolean webResourceCached) {
+        this.webResourceCached = webResourceCached;
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    public void setContext(final String context) {
+        this.context = context;
+    }
+
+    public Map<String, String> getContainerProperties() {
+        return containerProperties;
+    }
+
+    public void setContainerProperties(final Map<String, String> containerProperties) {
+        this.containerProperties = containerProperties;
+    }
+
+    public boolean isKeepServerXmlAsThis() {
+        return keepServerXmlAsThis;
+    }
+
+    public void setKeepServerXmlAsThis(final boolean keepServerXmlAsThis) {
+        this.keepServerXmlAsThis = keepServerXmlAsThis;
+    }
+
+    public Map<String, String> getUsers() {
+        return users;
+    }
+
+    public void setUsers(final Map<String, String> users) {
+        this.users = users;
+    }
+
+    public Map<String, String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(final Map<String, String> roles) {
+        this.roles = roles;
+    }
+
+    public boolean isForceJspDevelopment() {
+        return forceJspDevelopment;
+    }
+
+    public void setForceJspDevelopment(final boolean forceJspDevelopment) {
+        this.forceJspDevelopment = forceJspDevelopment;
+    }
+
+    public String getInlinedServerXml() {
+        return inlinedServerXml;
+    }
+
+    public void setInlinedServerXml(final String inlinedServerXml) {
+        this.inlinedServerXml = inlinedServerXml;
+    }
+
+    public String getInlinedTomEEXml() {
+        return inlinedTomEEXml;
+    }
+
+    public void setInlinedTomEEXml(final String inlinedTomEEXml) {
+        this.inlinedTomEEXml = inlinedTomEEXml;
+    }
+
+    public File getWorkDir() {
+        return workDir;
+    }
+
+    public void setWorkDir(final File workDir) {
+        this.workDir = workDir;
+    }
+
+    public List<File> getModules() {
+        return modules;
+    }
+
+    public void setModules(final List<File> modules) {
+        this.modules = modules;
+    }
+
+    public File getDocBase() {
+        return docBase;
+    }
+
+    public void setDocBase(final File docBase) {
+        this.docBase = docBase;
+    }
+
+    public String getDir() {
+        return dir;
+    }
+
+    public void setDir(final String dir) {
+        this.dir = dir;
+    }
+
+    public Configuration getClasspath() {
+        return classpath;
+    }
+
+    public void setClasspath(final Configuration classpath) {
+        this.classpath = classpath;
+    }
+
+    private static final class LogSetup {
+        private final LoggingManager logging;
+        private final LogLevel stdOutLvl;
+        private final LogLevel stdErrLvl;
+        private final LogLevel requiredLvl;
+
+        private LogSetup(final LoggingManager logging, final LogLevel stdOutLvl, final LogLevel stdErrLvl,
+                         final LogLevel requiredLvl) {
+            this.logging = logging;
+            this.stdOutLvl = stdOutLvl;
+            this.stdErrLvl = stdErrLvl;
+            this.requiredLvl = requiredLvl;
+        }
+
+
+        public LogSetup init() {
+            logging.captureStandardError(requiredLvl);
+            logging.captureStandardOutput(requiredLvl);
+            return this;
+        }
+
+        public void reset() {
+            logging.captureStandardError(stdErrLvl);
+            logging.captureStandardOutput(stdOutLvl);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/classloader/FilterGradleClassLoader.java
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/classloader/FilterGradleClassLoader.java b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/classloader/FilterGradleClassLoader.java
new file mode 100644
index 0000000..00fb440
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/src/main/java/org/apache/tomee/gradle/embedded/classloader/FilterGradleClassLoader.java
@@ -0,0 +1,124 @@
+/*
+ * 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.tomee.gradle.embedded.classloader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+import static java.util.Collections.emptyEnumeration;
+
+public class FilterGradleClassLoader extends ClassLoader { // TODO: make configurable
+    private final ClassLoader delegate;
+
+    public FilterGradleClassLoader(final ClassLoader gradle) {
+        super(gradle.getParent());
+        delegate = gradle;
+    }
+
+    @Override
+    public Class<?> loadClass(final String name) throws ClassNotFoundException {
+        checkClass(name);
+        return delegate.loadClass(name);
+    }
+
+    @Override
+    public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
+        return loadClass(name);
+    }
+
+    @Override
+    public URL getResource(final String name) {
+        if (!checkResource(name)) {
+            return null;
+        }
+        return delegate.getResource(name);
+    }
+
+    @Override
+    public Enumeration<URL> getResources(final String name) throws IOException {
+        final Enumeration<URL> resources = delegate.getResources(name);
+        if (!checkResource(name)) {
+            return emptyEnumeration();
+        }
+        return resources;
+    }
+
+    @Override
+    public InputStream getResourceAsStream(final String name) {
+        if (!checkResource(name)) {
+            return null;
+        }
+        return delegate.getResourceAsStream(name);
+    }
+
+    private void checkClass(final String name) throws ClassNotFoundException { // let slf4j+gradle go to reuse it
+        if (name != null && (
+                name.startsWith("aQute") ||
+                        name.startsWith("bsh") ||
+                        name.startsWith("com.amazon") ||
+                        name.startsWith("com.beust") ||
+                        name.startsWith("com.esot") ||
+                        name.startsWith("com.google") ||
+                        name.startsWith("com.jackson") ||
+                        name.startsWith("com.jcraft") ||
+                        name.startsWith("com.tonixsystems") ||
+                        name.startsWith("javax.el") ||
+                        name.startsWith("javax.inject") ||
+                        name.startsWith("javax.servlet") ||
+                        name.startsWith("jcifs.") ||
+                        name.startsWith("junit.") ||
+                        name.startsWith("groovy") ||
+                        name.startsWith("mozilla.") ||
+                        name.startsWith("net.jcip.") ||
+                        name.startsWith("net.ruby") ||
+                        name.startsWith("org.apache.") ||
+                        name.startsWith("org.bouncycastle.") ||
+                        name.startsWith("org.codehaus.") ||
+                        name.startsWith("org.cyber") ||
+                        name.startsWith("org.dom4j.") ||
+                        name.startsWith("org.eclipse.") ||
+                        name.startsWith("org.fusesource.") ||
+                        name.startsWith("org.hamcrest.") ||
+                        name.startsWith("org.jaxen.") ||
+                        name.startsWith("org.mortbay.") ||
+                        name.startsWith("org.mozilla.") ||
+                        name.startsWith("org.objectweb.") ||
+                        name.startsWith("org.objenesis.") ||
+                        name.startsWith("org.osgi.") ||
+                        name.startsWith("org.simpleframework.") ||
+                        name.startsWith("org.sonar.") ||
+                        name.startsWith("org.sonatype.") ||
+                        name.startsWith("org.testng.") ||
+                        name.startsWith("org.yaml.") ||
+                        isForbiddenGradleClass(name)
+        )) {
+            throw new ClassNotFoundException();
+        }
+    }
+
+    private boolean isForbiddenGradleClass(final String name) { // we need logging classes but we don't want to scan gradle
+        return name.startsWith("org.gradle.initialization") || name.startsWith("org.gradle.launcher")
+                || name.startsWith("org.gradle.execution") || name.startsWith("org.gradle.internal")
+                || name.startsWith("org.gradle.tooling") || name.startsWith("org.gradle.api.internal.tasks");
+    }
+
+    private boolean checkResource(final String name) {
+        return name != null && !name.startsWith("META-INF/services/com.fasterxml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/gradle-tomee-embedded/src/main/resources/META-INF/gradle-plugins/org.apache.tomee.tomee-embedded.properties
----------------------------------------------------------------------
diff --git a/gradle/gradle-tomee-embedded/src/main/resources/META-INF/gradle-plugins/org.apache.tomee.tomee-embedded.properties b/gradle/gradle-tomee-embedded/src/main/resources/META-INF/gradle-plugins/org.apache.tomee.tomee-embedded.properties
new file mode 100644
index 0000000..4dad1fe
--- /dev/null
+++ b/gradle/gradle-tomee-embedded/src/main/resources/META-INF/gradle-plugins/org.apache.tomee.tomee-embedded.properties
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+implementation-class=org.apache.tomee.gradle.embedded.TomEEEmbeddedPlugin

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/gradle/pom.xml
----------------------------------------------------------------------
diff --git a/gradle/pom.xml b/gradle/pom.xml
new file mode 100644
index 0000000..90164d1
--- /dev/null
+++ b/gradle/pom.xml
@@ -0,0 +1,60 @@
+<?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>tomee-project</artifactId>
+    <groupId>org.apache.tomee</groupId>
+    <version>7.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.tomee.gradle</groupId>
+  <artifactId>gradle</artifactId>
+  <name>OpenEJB :: Gradle Plugins</name>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>gradle-tomee-embedded</module>
+  </modules>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.gradle</groupId>
+      <artifactId>gradle-core</artifactId>
+      <version>2.12</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy-all</artifactId>
+      <version>${version.groovy}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <repositories>
+    <repository>
+      <id>gradle-libs-releases-local</id>
+      <url>http://repo.gradle.org/gradle/libs-releases-local/</url>
+    </repository>
+  </repositories>
+</project>

http://git-wip-us.apache.org/repos/asf/tomee/blob/24900b1e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 64748f1..ef1fa0e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,6 +22,9 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
+  <modules>
+    <module>gradle</module>
+  </modules>
 
   <parent>
     <groupId>org.apache</groupId>
@@ -172,7 +175,7 @@
     <geronimo-javamail_1.4_spec.version>1.9.0-alpha-2</geronimo-javamail_1.4_spec.version>
     <myfaces.version>2.2.10</myfaces.version>
     <mojarra.version>2.2.12</mojarra.version>
-    <slf4j.version>1.7.10</slf4j.version>
+    <slf4j.version>1.7.21</slf4j.version>
     <log4j.version>1.2.17</log4j.version>
     <log4j2.version>2.0.1</log4j2.version>
     <osgi.framework.version>4.2.0</osgi.framework.version>