You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2018/12/06 11:51:38 UTC

svn commit: r1848295 - in /openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache: catalina/ meecrowave/Meecrowave.java meecrowave/tomcat/MeecrowaveContextConfig.java

Author: rmannibucau
Date: Thu Dec  6 11:51:38 2018
New Revision: 1848295

URL: http://svn.apache.org/viewvc?rev=1848295&view=rev
Log:
MEECROWAVE-164 drop catalina package from our codebase

Added:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java
Removed:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/catalina/
Modified:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java?rev=1848295&r1=1848294&r2=1848295&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java Thu Dec  6 11:51:38 2018
@@ -97,7 +97,7 @@ import org.apache.catalina.core.Standard
 import org.apache.catalina.session.ManagerBase;
 import org.apache.catalina.session.StandardManager;
 import org.apache.catalina.startup.Catalina;
-import org.apache.catalina.startup.MeecrowaveContextConfig;
+import org.apache.meecrowave.tomcat.MeecrowaveContextConfig;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.coyote.http2.Http2Protocol;
 import org.apache.meecrowave.api.StartListening;

Added: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java?rev=1848295&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java Thu Dec  6 11:51:38 2018
@@ -0,0 +1,314 @@
+/*
+ * 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.meecrowave.tomcat;
+
+import static java.util.Collections.emptySet;
+import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toSet;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.annotation.HandlesTypes;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.annotation.WebListener;
+import javax.servlet.annotation.WebServlet;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.startup.ContextConfig;
+import org.apache.catalina.startup.WebappServiceLoader;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.logging.tomcat.LogFacade;
+import org.apache.meecrowave.openwebbeans.OWBTomcatWebScannerService;
+import org.apache.meecrowave.watching.ReloadOnChangeController;
+import org.apache.tomcat.JarScanner;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.descriptor.web.WebXml;
+import org.apache.tomcat.util.descriptor.web.WebXmlParser;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.corespi.scanner.xbean.CdiArchive;
+import org.apache.webbeans.corespi.scanner.xbean.OwbAnnotationFinder;
+import org.xml.sax.InputSource;
+
+public class MeecrowaveContextConfig extends ContextConfig {
+    private static final Log LOG = LogFactory.getLog(ContextConfig.class);
+
+    private static final byte[] DEFAULT_WEB_XML = "<web-app version=\"3.1\" />".getBytes(StandardCharsets.UTF_8);
+
+    private final Meecrowave.Builder configuration;
+    private final Map<String, Collection<Class<?>>> webClasses = new HashMap<>();
+    private final boolean fixDocBase;
+    private final ServletContainerInitializer intializer;
+    private OwbAnnotationFinder finder;
+    private ReloadOnChangeController watcher;
+
+    public MeecrowaveContextConfig(final Meecrowave.Builder configuration, final boolean fixDocBase, final ServletContainerInitializer intializer) {
+        this.configuration = configuration;
+        this.fixDocBase = fixDocBase;
+        this.intializer= intializer;
+    }
+
+    @Override
+    protected void fixDocBase() throws IOException {
+        if (!fixDocBase) {
+            return;
+        }
+        super.fixDocBase();
+    }
+
+    @Override
+    protected void webConfig() {
+        if (context.getServletContext().getAttribute("meecrowave.configuration") == null) { // redeploy
+            context.getServletContext().setAttribute("meecrowave.configuration", configuration);
+            context.addServletContainerInitializer(intializer, emptySet());
+        }
+
+        if (!configuration.isTomcatScanning()) {
+            doWebConfig();
+            return;
+        }
+
+        // eagerly start CDI to scan only once and not twice (tomcat+CDI)
+        final ClassLoader loader = context.getLoader().getClassLoader(); // should already be started at that point
+        final Thread thread = Thread.currentThread();
+        final ClassLoader old = thread.getContextClassLoader();
+        thread.setContextClassLoader(loader);
+        try {
+            final OWBTomcatWebScannerService scannerService = OWBTomcatWebScannerService.class.cast(WebBeansContext.getInstance().getScannerService());
+            scannerService.setFilter(ofNullable(context.getJarScanner()).map(JarScanner::getJarScanFilter).orElse(null), context.getServletContext());
+            scannerService.setDocBase(context.getDocBase());
+            scannerService.setShared(configuration.getSharedLibraries());
+            if (configuration.getWatcherBouncing() > 0) { // note that caching should be disabled with this config in most of the times
+                watcher = new ReloadOnChangeController(context, configuration.getWatcherBouncing());
+                scannerService.setFileVisitor(f -> watcher.register(f));
+            }
+            scannerService.scan();
+            finder = scannerService.getFinder();
+            finder.link();
+            final CdiArchive archive = CdiArchive.class.cast(finder.getArchive());
+            Stream.of(WebServlet.class, WebFilter.class, WebListener.class)
+                    .forEach(marker -> finder.findAnnotatedClasses(marker).stream()
+                            .filter(c -> !Modifier.isAbstract(c.getModifiers()) && Modifier.isPublic(c.getModifiers()))
+                            .forEach(webComponent -> webClasses.computeIfAbsent(
+                                    archive.classesByUrl().entrySet().stream()
+                                            .filter(e -> e.getValue().getClassNames().contains(webComponent.getName()))
+                                            .findFirst().get().getKey(), k -> new HashSet<>())
+                                    .add(webComponent)));
+        } finally {
+            thread.setContextClassLoader(old);
+        }
+        try {
+            doWebConfig();
+        } finally {
+            webClasses.clear();
+            finder = null;
+        }
+    }
+
+    // webConfig of the parent
+    private void doWebConfig() {
+        final WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),
+                context.getXmlValidation(), context.getXmlBlockExternal());
+
+        final Set<WebXml> defaults = new HashSet<>();
+        defaults.add(WebXml.class.cast(invokePrivate("getDefaultWebXmlFragment", WebXmlParser.class, webXmlParser)));
+
+        final Set<WebXml> tomcatWebXml = new HashSet<>();
+        tomcatWebXml.add(WebXml.class.cast(invokePrivate("getTomcatWebXmlFragment", WebXmlParser.class, webXmlParser)));
+
+        final WebXml webXml = createWebXml();
+        final InputSource contextWebXml = getContextWebXmlSource();
+        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
+            ok = false;
+        }
+
+        final ServletContext sContext = context.getServletContext();
+        final Map<String,WebXml> fragments = processJarsForWebFragments(webXml, webXmlParser);
+        final Set<WebXml> orderedFragments = WebXml.orderWebFragments(webXml, fragments, sContext);
+        if (ok) {
+            processServletContainerInitializers();
+        }
+
+        if  (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
+            final ClassLoader loader = context.getLoader().getClassLoader();
+            webClasses.forEach((k, v) -> {
+                final WebXml xml = fragments.get(k);
+                if (xml == null) {
+                    return;
+                }
+                v.forEach(clazz -> {
+                    try (final InputStream stream = loader.getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) {
+                        final ClassParser parser = new ClassParser(stream);
+                        final JavaClass parsed = parser.parse();
+                        final AnnotationEntry[] annotationsEntries = parsed.getAnnotationEntries();
+                        if (annotationsEntries != null) {
+                            final String className = parsed.getClassName();
+                            for (final AnnotationEntry ae : annotationsEntries) {
+                                final String type = ae.getAnnotationType();
+                                if ("Ljavax/servlet/annotation/WebServlet;".equals(type)) {
+                                    processAnnotationWebServlet(className, ae, xml);
+                                }else if ("Ljavax/servlet/annotation/WebFilter;".equals(type)) {
+                                    processAnnotationWebFilter(className, ae, xml);
+                                }else if ("Ljavax/servlet/annotation/WebListener;".equals(type)) {
+                                    xml.addListener(className);
+                                }
+                            }
+                        }
+                    } catch (final IOException e) {
+                        new LogFacade(MeecrowaveContextConfig.class.getName()).error("Can't parse " + clazz);
+                    }
+                });
+            });
+        }
+
+        if (!webXml.isMetadataComplete()) {
+            if (ok) {
+                ok = webXml.merge(orderedFragments);
+            }
+            webXml.merge(tomcatWebXml);
+            webXml.merge(defaults);
+            if (ok) {
+                invokePrivate("convertJsps", WebXml.class, webXml);
+            }
+            if (ok) {
+                invokePrivate("configureContext", WebXml.class, webXml);
+            }
+        } else {
+            webXml.merge(tomcatWebXml);
+            webXml.merge(defaults);
+            invokePrivate("convertJsps", WebXml.class, webXml);
+            invokePrivate("configureContext", WebXml.class, webXml);
+        }
+
+        if (context.getLogEffectiveWebXml()) {
+            LOG.info("web.xml:\n" + webXml.toXml());
+        }
+
+        if (ok) {
+            processResourceJARs(Stream.concat(orderedFragments.stream(), fragments.values().stream()).collect(toSet()));
+        }
+
+        if (ok) {
+            initializerClassMap.forEach((key, value) -> {
+                if (value.isEmpty()) {
+                    context.addServletContainerInitializer(key, null);
+                } else {
+                    context.addServletContainerInitializer(key, value);
+                }
+            });
+        }
+    }
+
+    @Override
+    public void lifecycleEvent(final LifecycleEvent event) {
+        super.lifecycleEvent(event);
+        if (watcher != null && watcher.shouldRun() && Context.class.cast(event.getLifecycle()) == context) {
+            if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+                watcher.start();
+            } else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
+                watcher.close();
+            }
+        }
+    }
+
+    @Override  // just to avoid an info log pretty useless for us
+    protected InputSource getGlobalWebXmlSource() {
+        return ofNullable(super.getGlobalWebXmlSource()).orElse(new InputSource(new ByteArrayInputStream(DEFAULT_WEB_XML)));
+    }
+
+    @Override
+    protected void processServletContainerInitializers() { // use our finder
+        if (!configuration.isTomcatScanning()) {
+            return;
+        }
+
+        try {
+            new WebappServiceLoader<ServletContainerInitializer>(context).load(ServletContainerInitializer.class).forEach(sci -> {
+                final Set<Class<?>> classes = new HashSet<>();
+                initializerClassMap.put(sci, classes);
+
+                final HandlesTypes ht;
+                try {
+                    ht = sci.getClass().getAnnotation(HandlesTypes.class);
+                } catch (final Exception | NoClassDefFoundError e) {
+                    return;
+                }
+                if (ht == null) {
+                    return;
+                }
+                Stream.of(ht.value()).forEach(t -> {
+                    if (t.isAnnotation()) {
+                        final Class<? extends Annotation> annotation = Class.class.cast(t);
+                        classes.addAll(finder.findAnnotatedClasses(annotation));
+                    } else if (t.isInterface()) {
+                        classes.addAll(finder.findImplementations(t));
+                    } else {
+                        classes.addAll(finder.findSubclasses(t));
+                    }
+                });
+            });
+        } catch (final IOException e) {
+            ok = false;
+        }
+    }
+
+    private Object invokePrivate(final String mtdName, final Class<?> paramType, final Object param) {
+        try {
+            final Method declaredMethod = ContextConfig.class.getDeclaredMethod(mtdName, paramType);
+            if (!declaredMethod.isAccessible()) {
+                declaredMethod.setAccessible(true);
+            }
+            return declaredMethod.invoke(this, param);
+        } catch (final InvocationTargetException ite) {
+            return rethrow(ite.getTargetException());
+        } catch (final Exception ex) {
+            return rethrow(ex);
+        }
+    }
+
+    private Object rethrow(final Throwable ex) {
+        if (RuntimeException.class.isInstance(ex)) {
+            throw RuntimeException.class.cast(ex);
+        }
+        if (Error.class.isInstance(ex)) {
+            throw Error.class.cast(ex);
+        }
+        throw new IllegalStateException(ex);
+    }
+}