Package com.brienwheeler.apps.tomcat

Source Code of com.brienwheeler.apps.tomcat.TomcatBean

/*
* The MIT License (MIT)
*
* Copyright (c) 2013 Brien L. Wheeler (brienwheeler@yahoo.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.brienwheeler.apps.tomcat;

import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfoBuilder;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;

public class TomcatBean implements InitializingBean, DisposableBean
{
  private static final Log log = LogFactory.getLog(TomcatBean.class);

    private static final Pattern KEY_PATTERN = Pattern.compile(
            "-+BEGIN (.*)PRIVATE KEY-+([^-]*)-+END .*PRIVATE KEY-+");
    private static final Pattern CERT_PATTERN = Pattern.compile(
            "-+BEGIN CERTIFICATE-+([^-]*)-+END CERTIFICATE-+");

    private static final String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  private int port;
    private int sslPort;
    private File sslKeyFile;
    private File sslCertFile;
  private String baseDirectory;
  private String webAppBase = null;
  private String contextRoot = null;
  private final Tomcat tomcat;
 
  public TomcatBean()
  {
    tomcat = new Tomcat();
  }

  @Override
  public void afterPropertiesSet() throws Exception
  {
    tomcat.setBaseDir(baseDirectory);
    tomcat.getHost().setAppBase(baseDirectory);
        configureNetwork();
    extractWarFile();
    tomcat.start();
  }

  @Override
  public void destroy() throws Exception
  {
    tomcat.stop();
    tomcat.getServer().await();
  }

  @Required
  public void setBaseDirectory(String baseDirectory)
  {
    this.baseDirectory = baseDirectory;
  }

  @Required
  public void setWebAppBase(String webAppBase)
  {
    this.webAppBase = webAppBase;
  }

  public void setContextRoot(String contextRoot)
  {
    this.contextRoot = contextRoot;
  }
 
  @Required
  public void setPort(int port)
  {
    this.port = port;
  }

    @Required
    public void setSslPort(int sslPort)
    {
        this.sslPort = sslPort;
    }

    @Required
    public void setSslKeyFile(File sslKeyFile)
    {
        this.sslKeyFile = sslKeyFile;
    }

    @Required
    public void setSslCertFile(File sslCertFile)
    {
        this.sslCertFile = sslCertFile;
    }

    private void configureNetwork() throws Exception
    {
        if (port > 0) {
            tomcat.setPort(port);
        }
        else {
            tomcat.getService().removeConnector(tomcat.getConnector());
        }

        if (sslPort > 0) {
            StringBuffer randomPass = new StringBuffer();
            for (int i=0; i<10; i++)
                randomPass.append(characters.charAt((int) (characters.length() * Math.random())));
            String keystorePass = randomPass.toString();

            RSAPrivateKey privateKey = readKeyFile();
            log.info("successfully read SSL private key from " + sslKeyFile.getAbsolutePath());
            X509Certificate certificate = readCertFile();
            log.info("successfully read SSL certificate from " + sslCertFile.getAbsolutePath());

            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(null);
            keyStore.setCertificateEntry("cert-alias", certificate);
            keyStore.setKeyEntry("key-alias", privateKey, keystorePass.toCharArray(), new Certificate[]{certificate});
            File keyStoreFile = new File("tcks");
            keyStore.store(new FileOutputStream(keyStoreFile), keystorePass.toCharArray());

            Connector sslConnector = new Connector();
            sslConnector.setPort(sslPort);
            sslConnector.setSecure(true);
            sslConnector.setScheme("https");
            sslConnector.setAttribute("keystoreFile", keyStoreFile.getAbsolutePath());
            sslConnector.setAttribute("keystorePass", keystorePass);
            sslConnector.setAttribute("clientAuth", "false");
            sslConnector.setAttribute("sslProtocol", "TLS");
            sslConnector.setAttribute("SSLEnabled", true);
            tomcat.getService().addConnector(sslConnector);
        }
    }

    private void extractWarFile()
  {
    if (webAppBase != null && webAppBase.length() > 0) {
      ProtectionDomain protectionDomain = this.getClass().getProtectionDomain();
      URL location = protectionDomain.getCodeSource().getLocation();
      log.info("detected run JAR at " + location);
     
      if (!location.toExternalForm().startsWith("file:") ||
          !location.toExternalForm().endsWith(".jar"))
        throw new IllegalArgumentException("invalid code location: " + location);
 
      try {
        ZipFile zipFile = new ZipFile(new File(location.toURI()));

        Enumeration<? extends ZipEntry> entryEnum = zipFile.entries();
        ZipEntry warEntry = null;
        while (entryEnum.hasMoreElements()) {
          ZipEntry entry = entryEnum.nextElement();
          String entryName = entry.getName();
          if (entryName.startsWith(webAppBase) && entryName.endsWith(".war")) {
            warEntry = entry;
            break;
          }
        }
       
        if (warEntry == null)
          throw new RuntimeException("can't find JAR entry for " + webAppBase + "*.war");
       
        log.info("extracting WAR file " + warEntry.getName());
       
        // extract web app WAR to current directory
        InputStream inputStream = zipFile.getInputStream(warEntry);
        OutputStream outputStream = new FileOutputStream(new File(warEntry.getName()));
        byte buf[] = new byte[1024];
        int nread;
        while ((nread = inputStream.read(buf, 0, 1024)) > 0) {
          outputStream.write(buf, 0, nread);
        }
        outputStream.close();
        inputStream.close();
        zipFile.close();

        String launchContextRoot = contextRoot != null ? contextRoot : webAppBase;
        if (!launchContextRoot.startsWith("/"))
          launchContextRoot = "/" + launchContextRoot;
       
        log.info("launching WAR file " + warEntry.getName() + " at context root " + launchContextRoot);

        // add web app to Tomcat
        Context context = tomcat.addWebapp(launchContextRoot, warEntry.getName());
        if (context instanceof StandardContext)
          ((StandardContext) context).setUnpackWAR(false);
      }
      catch (Exception e) {
        throw new RuntimeException("error extracting WAR file", e);
      }
    }
  }

    private RSAPrivateKey readKeyFile() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        String parse[] = readPEMFile(sslKeyFile, KEY_PATTERN, 2);
        if (parse == null)
            throw new IllegalArgumentException("invalid key file contents");

        if (parse[0].length() == 0) { // BEGIN PRIVATE KEY
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(parse[1])));
        }

        if (parse[0].contains("RSA")) { // BEGIN RSA PRIVATE KEY
            Security.addProvider(new BouncyCastleProvider());

            PEMParser pemParser = new PEMParser(new FileReader(sslKeyFile));
            Object parsedObject = pemParser.readObject();
            if (!(parsedObject instanceof PEMKeyPair))
                throw new IllegalArgumentException("invalid key file contents");

            PEMKeyPair keyPair = (PEMKeyPair) parsedObject;
            RSAPrivateKey privateKey = (RSAPrivateKey) BouncyCastleProvider.getPrivateKey(keyPair.getPrivateKeyInfo());
            if (privateKey == null)
                throw new IllegalArgumentException("invalid key file contents");
            return privateKey;
        }

        throw new IllegalArgumentException("invalid key file contents");
    }

    private X509Certificate readCertFile() throws IOException, CertificateException {
        String parse[] = readPEMFile(sslCertFile, CERT_PATTERN, 1);
        if (parse == null)
            throw new IllegalArgumentException("invalid certificate file contents");
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(Base64.decode(parse[0])));
    }

    private String[] readPEMFile(File inFile, Pattern pattern, int groups) throws IOException {
        StringBuffer buffer = new StringBuffer();

        BufferedReader reader = new BufferedReader(new FileReader(inFile));
        for (String line=reader.readLine(); line!=null; line=reader.readLine())
            buffer.append(line);
        reader.close();

        Matcher matcher = pattern.matcher(buffer.toString());
        if (!matcher.matches())
            return null;

        String[] ret = new String[groups];
        for (int i=0; i<groups; i++)
            ret[i] = matcher.group(i + 1);
        return ret;
    }
}
TOP

Related Classes of com.brienwheeler.apps.tomcat.TomcatBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.