@Override
 protected void doClose() throws ElasticsearchException {
   try {
     tomcat.destroy();
     tomcat = null;
   } catch (final LifecycleException e) {
     throw new ElasticsearchException("Unable to destroy Tomcat", e);
   }
 }
  @Override
  protected void doStop() throws ElasticsearchException {

    try {
      if (tomcat != null) {
        tomcat.stop();
      }

    } catch (final Exception e) {
      throw new ElasticsearchException("Unable to stop Tomcat", e);
    }
  }
  @Override
  protected void doStart() throws ElasticsearchException {
    try {

      final String currentDir = new File(".").getCanonicalPath();
      final String tomcatDir = currentDir + File.separatorChar + "tomcat";

      logger.debug("cur dir " + currentDir);

      if (tomcat != null) {
        try {
          tomcat.stop();
          tomcat.destroy();
        } catch (final Exception e) {

        }
      }

      tomcat = new ExtendedTomcat();
      tomcat.enableNaming();
      tomcat.getServer().setPort(-1); // shutdown disabled
      tomcat.getServer().setAddress("localhost");

      final String httpProtocolImpl =
          blockingServer
              ? "org.apache.coyote.http11.Http11Protocol"
              : "org.apache.coyote.http11.Http11NioProtocol";

      final Connector httpConnector = new Connector(httpProtocolImpl);
      tomcat.setConnector(httpConnector);
      tomcat.getService().addConnector(httpConnector);

      // TODO report tomcat bug with setProtocol

      if (maxContentLength != null) {
        httpConnector.setMaxPostSize(maxContentLength.bytesAsInt());
      }

      if (maxHeaderSize != null) {
        httpConnector.setAttribute("maxHttpHeaderSize", maxHeaderSize.bytesAsInt());
      }

      if (tcpNoDelay != null) {
        httpConnector.setAttribute("tcpNoDelay", tcpNoDelay.booleanValue());
      }

      if (reuseAddress != null) {
        httpConnector.setAttribute("socket.soReuseAddress", reuseAddress.booleanValue());
      }

      if (tcpKeepAlive != null) {
        httpConnector.setAttribute("socket.soKeepAlive", tcpKeepAlive.booleanValue());
        httpConnector.setAttribute(
            "maxKeepAliveRequests", tcpKeepAlive.booleanValue() ? "100" : "1");
      }

      if (tcpReceiveBufferSize != null) {
        httpConnector.setAttribute("socket.rxBufSize", tcpReceiveBufferSize.bytesAsInt());
      }

      if (tcpSendBufferSize != null) {
        httpConnector.setAttribute("socket.txBufSize", tcpSendBufferSize.bytesAsInt());
      }

      httpConnector.setAttribute(
          "compression", compression ? String.valueOf(compressionLevel) : "off");

      if (maxChunkSize != null) {
        httpConnector.setAttribute("maxExtensionSize", maxChunkSize.bytesAsInt());
      }

      httpConnector.setPort(Integer.parseInt(port));

      tomcat.setBaseDir(tomcatDir);

      final TomcatHttpTransportHandlerServlet servlet = new TomcatHttpTransportHandlerServlet();
      servlet.setTransport(this);

      final Context ctx = tomcat.addContext("", currentDir);

      logger.debug("currentDir " + currentDir);

      Tomcat.addServlet(ctx, "ES Servlet", servlet);

      ctx.addServletMapping("/*", "ES Servlet");

      if (useSSL) {
        logger.info("Using SSL");

        // System.setProperty("javax.net.debug", "ssl");
        httpConnector.setAttribute("SSLEnabled", "true");
        httpConnector.setSecure(true);
        httpConnector.setScheme("https");

        httpConnector.setAttribute("sslProtocol", "TLS");

        httpConnector.setAttribute(
            "keystoreFile", settings.get("security.ssl.keystorefile", "keystore"));
        httpConnector.setAttribute(
            "keystorePass", settings.get("security.ssl.keystorepass", "changeit"));
        httpConnector.setAttribute(
            "keystoreType", settings.get("security.ssl.keystoretype", "JKS"));

        final String keyalias = settings.get("security.ssl.keyalias", null);

        if (keyalias != null) {
          httpConnector.setAttribute("keyAlias", keyalias);
        }

        if (useClientAuth) {

          logger.info(
              "Using SSL Client Auth (PKI), so user/roles will be retrieved from client certificate.");

          httpConnector.setAttribute("clientAuth", "true");

          httpConnector.setAttribute(
              "truststoreFile",
              settings.get("security.ssl.clientauth.truststorefile", "truststore"));
          httpConnector.setAttribute(
              "truststorePass", settings.get("security.ssl.clientauth.truststorepass", "changeit"));
          httpConnector.setAttribute(
              "truststoreType", settings.get("security.ssl.clientauth.truststoretype", "JKS"));

          /*final String loginconf = this.settings
          		.get("security.kerberos.login.conf.path");
          final String krbconf = this.settings
          		.get("security.kerberos.krb5.conf.path");

          SecurityUtil.setSystemPropertyToAbsoluteFile(
          		"java.security.auth.login.config", loginconf);
          SecurityUtil.setSystemPropertyToAbsoluteFile(
          		"java.security.krb5.conf", krbconf);*/

          // httpConnector.setAttribute("allowUnsafeLegacyRenegotiation", "true");

          final SecurityConstraint constraint = new SecurityConstraint();
          constraint.addAuthRole("*");
          constraint.setAuthConstraint(true);
          constraint.setUserConstraint("CONFIDENTIAL");

          final SecurityCollection col = new SecurityCollection();
          col.addPattern("/*");

          constraint.addCollection(col);
          ctx.addConstraint(constraint);

          final LoginConfig lc = new LoginConfig();
          lc.setAuthMethod("CLIENT-CERT");
          lc.setRealmName("clientcretificate");
          ctx.setLoginConfig(lc);

          configureJndiRealm(ctx);

          ctx.getPipeline().addValve(new SSLAuthenticator());
          logger.info("Auth Method is CLIENT-CERT");

          // http://pki-tutorial.readthedocs.org/en/latest/simple/

        }

      } else {
        if (useClientAuth) {
          logger.error("Client Auth only available with SSL");
          throw new RuntimeException("Client Auth only available with SSL");
        }

        // useClientAuth = false;
      }

      if (!useClientAuth) {
        if ("waffle".equalsIgnoreCase(kerberosMode)) {

          final Boolean testMode = settings.getAsBoolean("security.waffle.testmode", false);

          final FilterDef fd = new FilterDef();
          fd.setFilterClass("waffle.servlet.NegotiateSecurityFilter");
          fd.setFilterName("Waffle");

          if (testMode != null && testMode.booleanValue()) {

            fd.addInitParameter("principalFormat", "fqn");
            fd.addInitParameter("roleFormat", "both");
            fd.addInitParameter("allowGuestLogin", "true");
            fd.addInitParameter(
                "securityFilterProviders",
                "org.elasticsearch.plugins.security.waffle.TestProvider");

            logger.info(
                "Kerberos implementaton is WAFFLE in testmode (only work on Windows Operations system)");
          } else {
            final Map<String, String> waffleSettings =
                settings.getByPrefix("security.waffle").getAsMap();

            for (final String waffleKey : waffleSettings.keySet()) {

              fd.addInitParameter(waffleKey.substring(1), waffleSettings.get(waffleKey));

              logger.debug(waffleKey.substring(1) + "=" + waffleSettings.get(waffleKey));
            }

            fd.addInitParameter("principalFormat", "fqn");
            fd.addInitParameter("roleFormat", "both");
            fd.addInitParameter("allowGuestLogin", "false");

            logger.info(
                "Kerberos implementaton is WAFFLE (only work on Windows Operations system)");
          }

          ctx.addFilterDef(fd);
          final FilterMap fm = new FilterMap();
          fm.setFilterName("Waffle");
          fm.addURLPattern("/*");
          ctx.addFilterMap(fm);

        } else if ("spnegoad".equalsIgnoreCase(kerberosMode)) {

          // System.setProperty("sun.security.krb5.debug", "true"); // TODO
          // switch
          // off

          System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

          final SecurityConstraint constraint = new SecurityConstraint();
          constraint.addAuthRole("*");
          constraint.setAuthConstraint(true);
          constraint.setDisplayName("spnego_sc_all");
          final SecurityCollection col = new SecurityCollection();
          col.addPattern("/*");

          constraint.addCollection(col);
          ctx.addConstraint(constraint);

          final LoginConfig lc = new LoginConfig();
          lc.setAuthMethod("SPNEGO");
          lc.setRealmName("SPNEGO");
          ctx.setLoginConfig(lc);

          logger.info("Kerberos implementaton is SPNEGOAD");

          configureJndiRealm(ctx);

          final ExtendedSpnegoAuthenticator spnegoValve = new ExtendedSpnegoAuthenticator();
          // spnegoValve.setLoginConfigName("es-login");
          spnegoValve.setStoreDelegatedCredential(true);
          ctx.getPipeline().addValve(spnegoValve);

          // final SpnegoAuthenticator spnegoValve = new SpnegoAuthenticator();
          // spnegoValve.setLoginEntryName("es-login");
          // ctx.getPipeline().addValve(spnegoValve);

        } else if ("none".equalsIgnoreCase(kerberosMode)) {

          logger.warn(
              "Kerberos is not configured so user/roles are unavailable. Host based security, in contrast, is woking. ");

        } else {
          logger.error(
              "No Kerberos implementaion '"
                  + kerberosMode
                  + "' found. Kerberos is therefore not configured so user/roles are unavailable. Host based security, in contrast, is woking. ");
        }
      }

      tomcat.start();

      logger.info("Tomcat started");

      InetSocketAddress bindAddress;
      try {
        bindAddress =
            new InetSocketAddress(
                networkService.resolveBindHostAddress(bindHost),
                tomcat.getConnector().getLocalPort());
      } catch (final Exception e) {
        throw new BindTransportException("Failed to resolve bind address", e);
      }

      InetSocketAddress publishAddress;
      try {
        publishAddress =
            new InetSocketAddress(
                networkService.resolvePublishHostAddress(publishHost), bindAddress.getPort());
      } catch (final Exception e) {
        throw new BindTransportException("Failed to resolve publish address", e);
      }

      logger.debug("bindAddress " + bindAddress);
      logger.debug("publishAddress " + publishAddress);

      boundAddress =
          new BoundTransportAddress(
              new InetSocketTransportAddress(bindAddress),
              new InetSocketTransportAddress(publishAddress));

    } catch (final Exception e) {
      throw new ElasticsearchException("Unable to start Tomcat", e);
    }
  }