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

org.smallmind.web.grizzly.GrizzlyInitializingBean Maven / Gradle / Ivy

/*
 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 David Berkman
 * 
 * This file is part of the SmallMind Code Project.
 * 
 * The SmallMind Code Project is free software, you can redistribute
 * it and/or modify it under either, at your discretion...
 * 
 * 1) The terms of GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * ...or...
 * 
 * 2) The terms of the Apache License, Version 2.0.
 * 
 * The SmallMind Code Project is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License or Apache License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * and the Apache License along with the SmallMind Code Project. If not, see
 *  or .
 * 
 * Additional permission under the GNU Affero GPL version 3 section 7
 * ------------------------------------------------------------------
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 */
package org.smallmind.web.grizzly;

import java.io.File;
import java.io.IOException;
import java.net.BindException;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletRegistration;
import org.glassfish.grizzly.http.server.AddOn;
import org.glassfish.grizzly.http.server.CLStaticHttpHandler;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.StaticHttpHandler;
import org.glassfish.grizzly.jaxws.JaxwsHandler;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.grizzly.ssl.SSLContextConfigurator;
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
import org.glassfish.grizzly.websockets.WebSocketEngine;
import org.glassfish.jersey.servlet.ServletContainer;
import org.smallmind.nutsnbolts.lang.web.PerApplicationContextFilter;
import org.smallmind.nutsnbolts.resource.ResourceException;
import org.smallmind.web.jersey.jackson.JsonResourceConfig;
import org.smallmind.web.jersey.spring.ExposedApplicationContext;
import org.smallmind.web.jersey.spring.ResourceConfigExtension;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class GrizzlyInitializingBean implements DisposableBean, ApplicationContextAware, ApplicationListener, BeanPostProcessor {

  private HttpServer httpServer;
  private LinkedList serviceList = new LinkedList<>();
  private LinkedList filterInstallerList = new LinkedList<>();
  private LinkedList listenerInstallerList = new LinkedList<>();
  private LinkedList servletInstallerList = new LinkedList<>();
  private LinkedList webSocketApplicationInstallerList = new LinkedList<>();
  private ResourceConfigExtension[] resourceConfigExtensions;
  private AddOn[] addOns;
  private File[] documentRoots;
  private SSLInfo sslInfo;
  private String host;
  private String contextPath = "/context";
  private String documentPath = "/document";
  private String staticPath = "/static";
  private String restPath = "/rest";
  private String soapPath = "/soap";
  private String webSocketPath = "/websocket";
  private int port = 80;
  private boolean allowInsecure = true;
  private boolean debug = false;

  public void setHost (String host) {

    this.host = host;
  }

  public void setPort (int port) {

    this.port = port;
  }

  public void setSslInfo (SSLInfo sslInfo) {

    this.sslInfo = sslInfo;
  }

  public void setContextPath (String contextPath) {

    this.contextPath = contextPath;
  }

  public void setDocumentPath (String documentPath) {

    this.documentPath = documentPath;
  }

  public void setStaticPath (String staticPath) {

    this.staticPath = staticPath;
  }

  public void setRestPath (String restPath) {

    this.restPath = restPath;
  }

  public void setSoapPath (String soapPath) {

    this.soapPath = soapPath;
  }

  public void setWebSocketPath (String webSocketPath) {

    this.webSocketPath = webSocketPath;
  }

  public void setDocumentRoots (File[] documentRoots) {

    this.documentRoots = documentRoots;
  }

  public void setResourceConfigExtensions (ResourceConfigExtension[] resourceConfigExtensions) {

    this.resourceConfigExtensions = resourceConfigExtensions;
  }

  public void setAddOns (AddOn[] addOns) {

    this.addOns = addOns;
  }

  public void setAllowInsecure (boolean allowInsecure) {

    this.allowInsecure = allowInsecure;
  }

  public void setDebug (boolean debug) {

    this.debug = debug;
  }

  @Override
  public synchronized void onApplicationEvent (ApplicationEvent event) {

    NetworkListener secureNetworkListener = null;

    if (event instanceof ContextRefreshedEvent) {

      if (debug) {
        System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true");
      }

      httpServer = new HttpServer();

      if (allowInsecure) {
        httpServer.addListener(new NetworkListener("grizzly2", host, port));
      }

      if (sslInfo != null) {
        try {
          httpServer.addListener(secureNetworkListener = generateSecureNetworkListener(sslInfo));
        } catch (Exception exception) {
          throw new GrizzlyInitializationException(exception);
        }
      }

      if ((addOns != null) && (addOns.length > 0)) {
        for (AddOn addOn : addOns)
          for (NetworkListener networkListener : httpServer.getListeners()) {
            networkListener.registerAddOn(addOn);
          }
      }

      httpServer.getServerConfiguration().addHttpHandler(new CLStaticHttpHandler(GrizzlyInitializingBean.class.getClassLoader(), "/"), staticPath);

      if ((documentRoots != null) && (documentRoots.length > 0)) {

        String[] absolutePaths = new String[documentRoots.length];

        for (int index = 0; index < documentRoots.length; index++) {
          absolutePaths[index] = documentRoots[index].getAbsolutePath();
        }

        httpServer.getServerConfiguration().addHttpHandler(new StaticHttpHandler(absolutePaths), documentPath);
      }

      WebappContext webappContext = new WebappContext("Grizzly Application Context", contextPath);
      webappContext.addServlet("JAX-RS Application", new ServletContainer(new JsonResourceConfig(ExposedApplicationContext.getApplicationContext(), resourceConfigExtensions))).addMapping(restPath + "/*");
      webappContext.addFilter("per-application-data", new PerApplicationContextFilter()).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), restPath + "/*");
      webappContext.addListener("org.springframework.web.context.request.RequestContextListener");

      for (FilterInstaller filterInstaller : filterInstallerList) {
        try {

          FilterRegistration filterRegistration;
          Map initParameters;
          String urlPattern;

          filterRegistration = webappContext.addFilter(filterInstaller.getDisplayName(), filterInstaller.getFilter());
          filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), filterInstaller.isMatchAfter(), (urlPattern = filterInstaller.getUrlPattern()) == null ? "/" : urlPattern);
          if ((initParameters = filterInstaller.getInitParameters()) != null) {
            filterRegistration.setInitParameters(initParameters);
          }
        } catch (Exception exception) {
          throw new GrizzlyInitializationException(exception);
        }
      }
      for (ListenerInstaller listenerInstaller : listenerInstallerList) {
        try {
          webappContext.addListener(listenerInstaller.getListener());
          for (Map.Entry parameterEntry : listenerInstaller.getContextParameters().entrySet()) {
            webappContext.addContextInitParameter(parameterEntry.getKey(), parameterEntry.getValue());
          }
        } catch (Exception exception) {
          throw new GrizzlyInitializationException(exception);
        }
      }
      for (ServletInstaller servletInstaller : servletInstallerList) {
        try {

          ServletRegistration servletRegistration;
          Map initParameters;
          String urlPattern;

          servletRegistration = webappContext.addServlet(servletInstaller.getDisplayName(), servletInstaller.getServlet());
          servletRegistration.addMapping((urlPattern = servletInstaller.getUrlPattern()) == null ? "/" : urlPattern);
          if ((initParameters = servletInstaller.getInitParameters()) != null) {
            servletRegistration.setInitParameters(initParameters);
          }
        } catch (Exception exception) {
          throw new GrizzlyInitializationException(exception);
        }
      }
      for (WebSocketApplicationInstaller webSocketApplicationInstaller : webSocketApplicationInstallerList) {
        try {
          WebSocketEngine.getEngine().register(webSocketPath, webSocketApplicationInstaller.getUrlPattern(), webSocketApplicationInstaller.getWebSocketApplication());
        } catch (Exception exception) {
          throw new GrizzlyInitializationException(exception);
        }
      }

      webappContext.deploy(httpServer);

      for (WebService webService : serviceList) {

        HttpHandler httpHandler = new JaxwsHandler(webService.getService(), false);

        httpServer.getServerConfiguration().addHttpHandler(httpHandler, soapPath + webService.getPath());
      }

      try {
        httpServer.start();

        if (secureNetworkListener != null) {
          secureNetworkListener.getFilterChain().add(secureNetworkListener.getFilterChain().size() - 1, new ClientAuthProxyFilter(sslInfo.isProxyMode()));
        }
      } catch (IOException ioException) {
        if (!(ioException instanceof BindException)) {
          throw new GrizzlyInitializationException(ioException);
        }
      }
    }
  }

  @Override
  public void setApplicationContext (ApplicationContext applicationContext) {

    ExposedApplicationContext.register(applicationContext);
  }

  @Override
  public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException {

    return bean;
  }

  @Override
  public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException {

    ServicePath servicePath;

    if (bean instanceof FilterInstaller) {
      filterInstallerList.add((FilterInstaller)bean);
    } else if (bean instanceof ListenerInstaller) {
      listenerInstallerList.add((ListenerInstaller)bean);
    } else if (bean instanceof ServletInstaller) {
      servletInstallerList.add((ServletInstaller)bean);
    } else if (bean instanceof WebSocketApplicationInstaller) {
      webSocketApplicationInstallerList.add((WebSocketApplicationInstaller)bean);
    } else if ((servicePath = bean.getClass().getAnnotation(ServicePath.class)) != null) {
      serviceList.add(new WebService(servicePath.value(), bean));
    }

    return bean;
  }

  @Override
  public synchronized void destroy () {

    if (httpServer != null) {
      httpServer.shutdown();
    }
  }

  public NetworkListener generateSecureNetworkListener (SSLInfo sslInfo)
    throws IOException, ResourceException {

    NetworkListener secureListener = new NetworkListener("grizzly2Secure", host, sslInfo.getPort());
    SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();

    secureListener.setSecure(true);

    if (sslInfo.getKeySSLStore() != null) {
      sslContextConfigurator.setKeyStoreBytes(sslInfo.getKeySSLStore().getBytes());
      sslContextConfigurator.setKeyStorePass(sslInfo.getKeySSLStore().getPassword());
    }

    if (sslInfo.getTrustSSLStore() != null) {
      sslContextConfigurator.setTrustStoreBytes(sslInfo.getTrustSSLStore().getBytes());
      sslContextConfigurator.setTrustStorePass(sslInfo.getTrustSSLStore().getPassword());
    }

    if (!sslContextConfigurator.validateConfiguration(true)) {
      throw new GrizzlyInitializationException("Invalid ssl configuration");
    }

    /* Note: clientMode (2nd param) means server does not
    *  authenticate to client - which we never want
    */
    SSLEngineConfigurator sslEngineConfig = new SSLEngineConfigurator(sslContextConfigurator.createSSLContext(), false, sslInfo.isRequireClientAuth(), true);
    secureListener.setSSLEngineConfig(sslEngineConfig);

    return secureListener;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy