All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.winegrower.servlet.service.ServletHttpServiceDeployer Maven / Gradle / Ivy

/**
 * Licensed 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.winegrower.servlet.service; import org.apache.winegrower.Ripener; import org.apache.winegrower.api.LifecycleCallbacks; import org.apache.winegrower.scanner.manifest.ManifestContributor; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebListener; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingListener; import javax.servlet.http.HttpSessionIdListener; import javax.servlet.http.HttpSessionListener; import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.util.EventListener; import java.util.Hashtable; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collector; import java.util.stream.Stream; import static java.util.Arrays.asList; import static java.util.Optional.of; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; public class ServletHttpServiceDeployer implements ServletContainerInitializer { @Override public void onStartup(final Set> c, final ServletContext servletContext) { if (getClass() == ServletHttpServiceDeployer.class && is(servletContext, "winegrower.servlet.ripener.skip", false)) { return; } final Ripener.Configuration configuration = createConfiguration(servletContext); final Ripener.Impl ripener = new Ripener.Impl(configuration); onRipenerCreated(ripener); if (is(servletContext, "winegrower.servlet.services.http.register", true)) { final ServletHttpService service = new ServletHttpService(servletContext); ripener.registerBuiltInService(HttpService.class, service, new Hashtable<>()); final BundleContext rootBundle = ripener.getRegistry().getBundles().get(0L).getBundle().getBundleContext(); Stream.of(Servlet.class, HttpServlet.class).forEach(base -> registerServletTracker(service, rootBundle, base)); registerFilterTracker(service, rootBundle); Stream.of( ServletContextListener.class, ServletContextAttributeListener.class, HttpSessionListener.class, HttpSessionAttributeListener.class, HttpSessionActivationListener.class, HttpSessionBindingListener.class, HttpSessionIdListener.class, ServletRequestListener.class, ServletRequestAttributeListener.class) .forEach(base -> registerListenerTracker(service, rootBundle, base)); } servletContext.setAttribute(Ripener.class.getName(), ripener.start()); onRipenerStarted(ripener); servletContext.addListener(new ServletContextListener() { @Override public void contextDestroyed(final ServletContextEvent sce) { ofNullable(sce.getServletContext().getAttribute(Ripener.class.getName())) .map(Ripener.class::cast) .map(it -> { onRipenerWillStop(it); return it; }) .ifPresent(Ripener::stop); } }); } // enables subclasses to register built in services protected void onRipenerCreated(final Ripener ripener) { // no-op } protected void onRipenerWillStop(final Ripener ripener) { // no-op } // enables subclasses to wait for some start (OSGi-CDI typically) protected void onRipenerStarted(final Ripener ripener) { // no-op } private Boolean is(final ServletContext servletContext, final String name, final boolean def) { return ofNullable(servletContext.getInitParameter(name)).map(String::valueOf).map(Boolean::parseBoolean).orElse(def); } private void registerListenerTracker(final ServletHttpService service, final BundleContext bundleContext, final Class type) { new StartupOnlyTracker<>(bundleContext, type, (reference, listener) -> { final Hashtable props = Stream.of(reference.getPropertyKeys()).map(String::valueOf) .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> { a.putAll(b); return a; })); ofNullable(listener.getClass().getAnnotation(WebListener.class)) .ifPresent(annotConfig -> of(annotConfig.value()) .filter(it -> !it.isEmpty()) .ifPresent(value -> props.put("description", value))); service.registerListener(listener, props); }).open(); } private void registerFilterTracker(final ServletHttpService service, final BundleContext bundleContext) { new StartupOnlyTracker<>(bundleContext, Filter.class, (reference, filter) -> { final Hashtable props = Stream.of(reference.getPropertyKeys()).map(String::valueOf) .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> { a.putAll(b); return a; })); ofNullable(filter.getClass().getAnnotation(WebFilter.class)).ifPresent(annotConfig -> { of(annotConfig.asyncSupported()).filter(it -> it).ifPresent(value -> props.put("async-supported", value)); of(annotConfig.displayName()).filter(it -> !it.isEmpty()).ifPresent(value -> props.put("display-name", value)); }); findMapping(reference, filter, WebFilter.class, WebFilter::urlPatterns) .forEach(mapping -> service.registerFilter(mapping, filter, props)); }).open(); } private void registerServletTracker(final ServletHttpService service, final BundleContext bundleContext, final Class base) { new StartupOnlyTracker<>(bundleContext, base, (reference, servlet) -> { final Hashtable props = toProps(reference); ofNullable(servlet.getClass().getAnnotation(WebServlet.class)).ifPresent(annotConfig -> { props.put("servlet-name", of(annotConfig.name()).filter(it -> !it.isEmpty()).orElse(servlet.getClass().getName())); of(annotConfig.loadOnStartup()).filter(it -> it >= 0).ifPresent(value -> props.put("load-on-startup", value)); of(annotConfig.asyncSupported()).filter(it -> it).ifPresent(value -> props.put("async-supported", value)); of(annotConfig.displayName()).filter(it -> !it.isEmpty()).ifPresent(value -> props.put("display-name", value)); }); findMapping(reference, servlet, WebServlet.class, WebServlet::urlPatterns) .forEach(mapping -> service.registerServlet(mapping, servlet, props, null)); }).open(); } private Stream findMapping(final ServiceReference reference, final T servlet, final Class holder, final Function mappingExtractor) { return ofNullable(servlet.getClass().getAnnotation(holder)).map(mappingExtractor).filter(it -> it.length > 0) .map(Stream::of).orElseGet(() -> ofNullable(reference.getProperty("alias")).map(String::valueOf).map(Stream::of) .orElseGet(Stream::empty)); } private Hashtable toProps(final ServiceReference reference) { return Stream.of(reference.getPropertyKeys()).map(String::valueOf) .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> { a.putAll(b); return a; })); } private Ripener.Configuration createConfiguration(final ServletContext servletContext) { final Ripener.Configuration configuration = new Ripener.Configuration(); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.useLifecycleCallbacks")) .map(String::valueOf) .map(Boolean::parseBoolean) .ifPresent(configuration::setUseLifecycleCallbacks); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.workdir")).map(String::valueOf) .map(File::new).ifPresent(configuration::setWorkDir); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.prioritizedBundles")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))) .ifPresent(configuration::setPrioritizedBundles); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.ignoredBundles")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))) .ifPresent(configuration::setIgnoredBundles); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.scanningIncludes")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))) .ifPresent(configuration::setScanningIncludes); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.scanningExcludes")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))) .ifPresent(configuration::setScanningExcludes); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.manifestContributors")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))).ifPresent(contributors -> { configuration.setManifestContributors(contributors.stream().map(clazz -> { try { return Thread.currentThread().getContextClassLoader().loadClass(clazz).getConstructor().newInstance(); } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) { throw new IllegalArgumentException(e); } catch (final InvocationTargetException e) { throw new IllegalArgumentException(e.getTargetException()); } }).map(ManifestContributor.class::cast).collect(toList())); }); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.lifecycleCallbacks")) .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))).ifPresent(lifecycleCallbacks -> { configuration.setLifecycleCallbacks(lifecycleCallbacks.stream().map(clazz -> { try { return Thread.currentThread().getContextClassLoader().loadClass(clazz).getConstructor().newInstance(); } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) { throw new IllegalArgumentException(e); } catch (final InvocationTargetException e) { throw new IllegalArgumentException(e.getTargetException()); } }).map(LifecycleCallbacks.class::cast).collect(toList())); }); ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.jarFilter")).map(String::valueOf) .filter(it -> !it.isEmpty()).ifPresent(filter -> { try { configuration.setJarFilter((Predicate) Thread.currentThread().getContextClassLoader() .loadClass(filter).getConstructor().newInstance()); } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) { throw new IllegalArgumentException(e); } catch (final InvocationTargetException e) { throw new IllegalArgumentException(e.getTargetException()); } }); return configuration; } private static class StartupOnlyTracker extends ServiceTracker { private StartupOnlyTracker(final BundleContext context, final Class type, final BiConsumer, A> onService) { super(context, type, new ServiceTrackerCustomizer() { @Override public A addingService(final ServiceReference reference) { final A service = context.getService(reference); onService.accept(reference, service); return service; } @Override public void modifiedService(final ServiceReference reference, final A service) { // no-op } @Override public void removedService(final ServiceReference reference, final A service) { // no-op } }); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy