/*
 * 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.ranger.server.tomcat;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.hadoop.security.SecureClientLogin;

import javax.security.auth.Subject;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class EmbeddedServer {
	
	private static final Logger LOG = Logger.getLogger(EmbeddedServer.class
			.getName());
	private static final String DEFAULT_NAME_RULE = "DEFAULT";
	
	private static final String DEFAULT_CONFIG_FILENAME = "ranger-admin-site.xml";
	private static final String CORE_SITE_CONFIG_FILENAME = "core-site.xml";
	
	private static final String DEFAULT_WEBAPPS_ROOT_FOLDER = "webapps";
	
	private static String configFile = DEFAULT_CONFIG_FILENAME;
	
	private static final String AUTH_TYPE_KERBEROS = "kerberos";
    private static final String AUTHENTICATION_TYPE = "hadoop.security.authentication";
    private static final String ADMIN_USER_PRINCIPAL = "ranger.admin.kerberos.principal";
    private static final String ADMIN_USER_KEYTAB = "ranger.admin.kerberos.keytab";

	private static final String ADMIN_NAME_RULES = "hadoop.security.auth_to_local";
	private static final String ADMIN_SERVER_NAME = "rangeradmin";
	
	private Properties serverConfigProperties = new Properties();

	public static void main(String[] args) {
		new EmbeddedServer(args).start();
	}
	
	public EmbeddedServer(String[] args) {
		if (args.length > 0) {
			configFile = args[0];
		}
		loadConfig(CORE_SITE_CONFIG_FILENAME);
		loadConfig(configFile);		
	}
	
	public static int DEFAULT_SHUTDOWN_PORT = 6185;
	public static String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
	
	public void start() {
		final Tomcat server = new Tomcat();

		String logDir =  null;
		logDir = getConfig("logdir");
		if (logDir == null) {
			logDir = getConfig("kms.log.dir");
		}
		String servername = getConfig("servername");
		String hostName = getConfig("ranger.service.host");
		int serverPort = getIntConfig("ranger.service.http.port", 6181);
		int sslPort = getIntConfig("ranger.service.https.port", -1);
		int shutdownPort = getIntConfig("ranger.service.shutdown.port",DEFAULT_SHUTDOWN_PORT);
		String shutdownCommand = getConfig("ranger.service.shutdown.command",DEFAULT_SHUTDOWN_COMMAND);

		server.setHostname(hostName);
		server.setPort(serverPort);
		server.getServer().setPort(shutdownPort);
		server.getServer().setShutdown(shutdownCommand);

		boolean isHttpsEnabled = Boolean.valueOf(getConfig("ranger.service.https.attrib.ssl.enabled", "false"));
		boolean ajpEnabled = Boolean.valueOf(getConfig("ajp.enabled", "false"));

		if (ajpEnabled) {

			Connector ajpConnector = new Connector(
					"org.apache.coyote.ajp.AjpNioProtocol");
			ajpConnector.setPort(serverPort);
			ajpConnector.setProperty("protocol", "AJP/1.3");

			server.getService().addConnector(ajpConnector);

			// Making this as a default connector
			server.setConnector(ajpConnector);
			LOG.info("Created AJP Connector");
		} else if ((sslPort > 0) && isHttpsEnabled) {
			Connector ssl = new Connector();
			ssl.setPort(sslPort);
			ssl.setSecure(true);
			ssl.setScheme("https");
			ssl.setAttribute("SSLEnabled", "true");
			ssl.setAttribute("sslProtocol", getConfig("ranger.service.https.attrib.ssl.protocol", "TLS"));
			ssl.setAttribute("clientAuth", getConfig("ranger.service.https.attrib.clientAuth", "false"));
			ssl.setAttribute("keyAlias", getConfig("ranger.service.https.attrib.keystore.keyalias"));
			ssl.setAttribute("keystorePass", getConfig("ranger.service.https.attrib.keystore.pass"));
			ssl.setAttribute("keystoreFile", getKeystoreFile());
			
			String enabledProtocols = "SSLv2Hello, TLSv1, TLSv1.1, TLSv1.2";
			ssl.setAttribute("sslEnabledProtocols", enabledProtocols);
			
			server.getService().addConnector(ssl);

			//
			// Making this as a default connector
			//
			server.setConnector(ssl);
			
		}
		updateHttpConnectorAttribConfig(server);
		
		File logDirectory = new File(logDir);
		if (!logDirectory.exists()) {
			logDirectory.mkdirs();
		}
		
		AccessLogValve valve = new AccessLogValve();
		valve.setRotatable(true);
		valve.setAsyncSupported(true);
		valve.setBuffered(false);
		valve.setEnabled(true);
		valve.setFileDateFormat(getConfig("ranger.accesslog.dateformat", "yyyy-MM-dd.HH"));
		valve.setDirectory(logDirectory.getAbsolutePath());
		valve.setSuffix(".log");
		
		String logPattern = getConfig("ranger.accesslog.pattern", "%h %l %u %t \"%r\" %s %b");
		valve.setPattern(logPattern);	
				
		server.getHost().getPipeline().addValve(valve);
		
		try {
			String webapp_dir = getConfig("xa.webapp.dir");
			if (webapp_dir == null || webapp_dir.trim().isEmpty()) {
				// If webapp location property is not set, then let's derive
				// from catalina_base
				String catalina_base = getConfig("catalina.base");
				if (catalina_base == null || catalina_base.trim().isEmpty()) {
					LOG.severe("Tomcat Server failed to start: catalina.base and/or xa.webapp.dir is not set");
					System.exit(1);
				}
				webapp_dir = catalina_base + File.separator + "webapp";
				LOG.info("Deriving webapp folder from catalina.base property. folder="
						+ webapp_dir);
			}
			
			//String webContextName = getConfig("xa.webapp.contextName", "/");
			String webContextName = getConfig("ranger.contextName", "/");
			if (webContextName == null) {
				webContextName = "/";
			} else if (!webContextName.startsWith("/")) {
				LOG.info("Context Name [" + webContextName
						+ "] is being loaded as [ /" + webContextName + "]");
				webContextName = "/" + webContextName;
			}
			
			File wad = new File(webapp_dir);
			if (wad.isDirectory()) {
				LOG.info("Webapp file =" + webapp_dir + ", webAppName = "
						+ webContextName);
			} else if (wad.isFile()) {
				File webAppDir = new File(DEFAULT_WEBAPPS_ROOT_FOLDER);
				if (!webAppDir.exists()) {
					webAppDir.mkdirs();
				}
				LOG.info("Webapp file =" + webapp_dir + ", webAppName = "
						+ webContextName);
			}
			LOG.info("Adding webapp [" + webContextName + "] = path ["
					+ webapp_dir + "] .....");
			Context webappCtx = server.addWebapp(webContextName, new File(
					webapp_dir).getAbsolutePath());
			webappCtx.init();
			LOG.info("Finished init of webapp [" + webContextName
					+ "] = path [" + webapp_dir + "].");
		} catch (ServletException e1) {
			LOG.severe("Tomcat Server failed to add webapp:" + e1.toString());
			e1.printStackTrace();
		} catch (LifecycleException lce) {
			LOG.severe("Tomcat Server failed to start webapp:" + lce.toString());
			lce.printStackTrace();
		}
		
		if (servername.equalsIgnoreCase(ADMIN_SERVER_NAME)) {
			String keytab = getConfig(ADMIN_USER_KEYTAB);
			String principal = null;
			try {
				principal = SecureClientLogin.getPrincipal(getConfig(ADMIN_USER_PRINCIPAL), hostName);
			} catch (IOException ignored) {
				LOG.warning("Failed to get ranger.admin.kerberos.principal. Reason: " + ignored.toString());
			}
			String nameRules = getConfig(ADMIN_NAME_RULES);
			if (nameRules == null || nameRules.length() == 0) {
				LOG.info("Name is empty. Setting Name Rule as 'DEFAULT'");
				nameRules = DEFAULT_NAME_RULE;
			}
			if (getConfig(AUTHENTICATION_TYPE) != null
					&& getConfig(AUTHENTICATION_TYPE).trim().equalsIgnoreCase(AUTH_TYPE_KERBEROS)
					&& SecureClientLogin.isKerberosCredentialExists(principal,keytab)) {
				try{
					LOG.info("Provided Kerberos Credential : Principal = "
							+ principal + " and Keytab = " + keytab);
					Subject sub = SecureClientLogin.loginUserFromKeytab(principal, keytab, nameRules);
					Subject.doAs(sub, new PrivilegedAction<Void>() {
						@Override
						public Void run() {
							LOG.info("Starting Server using kerberos credential");
							startServer(server);
							return null;
						}
					});
				} catch (Exception e) {
					LOG.severe("Tomcat Server failed to start:" + e.toString());
					e.printStackTrace();
				}
			} else {
				startServer(server);
			}
		} else {
			startServer(server);
		}
	}

	private void startServer(final Tomcat server) {
		try {
			server.start();
			server.getServer().await();
			shutdownServer();
		} catch (LifecycleException e) {
			LOG.severe("Tomcat Server failed to start:" + e.toString());
			e.printStackTrace();
		} catch (Exception e) {
			LOG.severe("Tomcat Server failed to start:" + e.toString());
			e.printStackTrace();
		}
	}

	private String getKeystoreFile() {
		String keystoreFile=getConfig("ranger.service.https.attrib.keystore.file");
		if (keystoreFile == null || keystoreFile.trim().isEmpty()) {
			// new property not configured, lets use the old property
			keystoreFile = getConfig("ranger.https.attrib.keystore.file");
		}
		return keystoreFile;
	}

	protected String getConfig(String key) {
		String value = serverConfigProperties.getProperty(key);
		if (value == null || value.trim().isEmpty()) {
			// Value not found in properties file, let's try to get from
			// System's property
			value = System.getProperty(key);
		}
		return value;
	}
	
	protected String getConfig(String key, String defaultValue) {
		String ret = getConfig(key);
		if (ret == null) {
			ret = defaultValue;
		}
		return ret;
	}
	
	protected int getIntConfig(String key, int defaultValue) {
		int ret = defaultValue;
		String retStr = getConfig(key);
		try {
			if (retStr != null) {
				ret = Integer.parseInt(retStr);
			}
		} catch (Exception err) {
			LOG.warning(retStr + " can't be parsed to int. Reason: " + err.toString());
		}
		return ret;
	}
	
	private String getResourceFileName(String aResourceName) {
		
		String ret = aResourceName;
		
		ClassLoader cl = getClass().getClassLoader();
		
		for (String path : new String[] { aResourceName, "/" + aResourceName }) {
			
			try {
				URL lurl = cl.getResource(path);
		
				if (lurl != null) {
					ret = lurl.getFile();
				}
			} catch (Throwable t) {
				ret = null;
			}
			if (ret != null) {
				break;
			}

		}
		
		if (ret == null) {
			ret = aResourceName;
		}
		
		return ret;
		
	}
	
	public void shutdownServer() {
		int timeWaitForShutdownInSeconds = getIntConfig(
				"service.waitTimeForForceShutdownInSeconds", 0);
		if (timeWaitForShutdownInSeconds > 0) {
			long endTime = System.currentTimeMillis()
					+ (timeWaitForShutdownInSeconds * 1000L);
			LOG.info("Will wait for all threads to shutdown gracefully. Final shutdown Time: "
					+ new Date(endTime));
			while (System.currentTimeMillis() < endTime) {
				int activeCount = Thread.activeCount();
				if (activeCount == 0) {
				    LOG.info("Number of active threads = " + activeCount + ".");
					break;
				} else {
					LOG.info("Number of active threads = " + activeCount
							+ ". Waiting for all threads to shutdown ...");
					try {
						Thread.sleep(5000L);
					} catch (InterruptedException e) {
						LOG.warning("shutdownServer process is interrupted with exception: "
								+ e);
						break;
					}
				}
			}
		}
		LOG.info("Shuting down the Server.");
		System.exit(0);
	}


	public void loadConfig(String configFileName) {
		String path = getResourceFileName(configFileName);
		try {
			DocumentBuilderFactory xmlDocumentBuilderFactory = DocumentBuilderFactory
					.newInstance();
			xmlDocumentBuilderFactory.setIgnoringComments(true);
			xmlDocumentBuilderFactory.setNamespaceAware(true);
			DocumentBuilder xmlDocumentBuilder = xmlDocumentBuilderFactory
					.newDocumentBuilder();
			Document xmlDocument = xmlDocumentBuilder.parse(new File(path));
			xmlDocument.getDocumentElement().normalize();

			NodeList nList = xmlDocument.getElementsByTagName("property");

			for (int temp = 0; temp < nList.getLength(); temp++) {

				Node nNode = nList.item(temp);

				if (nNode.getNodeType() == Node.ELEMENT_NODE) {

					Element eElement = (Element) nNode;

					String propertyName = "";
					String propertyValue = "";
					if (eElement.getElementsByTagName("name").item(0) != null) {
						propertyName = eElement.getElementsByTagName("name")
								.item(0).getTextContent().trim();
					}
					if (eElement.getElementsByTagName("value").item(0) != null) {
						propertyValue = eElement.getElementsByTagName("value")
								.item(0).getTextContent().trim();
					}

					serverConfigProperties.put(propertyName, propertyValue);

				}
			}

		} catch (Exception e) {
			LOG.severe("Load configuration fail. Reason: " + e.toString());
		}

	}
	protected long getLongConfig(String key, long defaultValue) {
		long ret = defaultValue;
		String retStr = getConfig(key);
		try{
			if (retStr != null) {
		        ret = Long.parseLong(retStr);
			}
		}catch(Exception err){
			LOG.warning(retStr + " can't be parsed to long. Reason: " + err.toString());
		}
		return ret;
	}
	public void updateHttpConnectorAttribConfig(Tomcat server) {
		server.getConnector().setAllowTrace(Boolean.valueOf(getConfig("ranger.service.http.connector.attrib.allowTrace","false")));
		server.getConnector().setAsyncTimeout(getLongConfig("ranger.service.http.connector.attrib.asyncTimeout", 10000));
		server.getConnector().setEnableLookups(Boolean.valueOf(getConfig("ranger.service.http.connector.attrib.enableLookups","false")));
		server.getConnector().setMaxHeaderCount(getIntConfig("ranger.service.http.connector.attrib.maxHeaderCount", 100));
		server.getConnector().setMaxParameterCount(getIntConfig("ranger.service.http.connector.attrib.maxParameterCount", 10000));
		server.getConnector().setMaxPostSize(getIntConfig("ranger.service.http.connector.attrib.maxPostSize", 2097152));
		server.getConnector().setMaxSavePostSize(getIntConfig("ranger.service.http.connector.attrib.maxSavePostSize", 4096));
		server.getConnector().setParseBodyMethods(getConfig("ranger.service.http.connector.attrib.methods", "POST"));
		server.getConnector().setURIEncoding(getConfig("ranger.service.http.connector.attrib.URIEncoding", "UTF-8"));
		Iterator<Object> iterator = serverConfigProperties.keySet().iterator();
		String key = null;
		String property = null;
		while (iterator.hasNext()){
			key = iterator.next().toString();
			if(key != null && key.startsWith("ranger.service.http.connector.property.")){
				property = key.replace("ranger.service.http.connector.property.","");
				server.getConnector().setProperty(property,getConfig(key));
				LOG.info(property + ":" + server.getConnector().getProperty(property));
			}
		}
	}
}
