// 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 com.cloud.consoleproxy;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.xml.DOMConfigurator;

import com.cloud.consoleproxy.util.Logger;


//
//
// I switched to a simpler solution to monitor only unrecoverable exceptions, under these cases, console proxy process will exit
// itself and the shell script will re-launch console proxy
//
public class ConsoleProxyMonitor {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyMonitor.class);
	
	private String[] _argv;
	private Map<String, String> _argMap = new HashMap<String, String>();
	
	private volatile Process _process;
	private boolean _quit = false;
	
	public ConsoleProxyMonitor(String[] argv) {
		_argv = argv;
		
		for(String arg : _argv) {
			String[] tokens = arg.split("=");
			if(tokens.length == 2) {
				s_logger.info("Add argument " + tokens[0] + "=" + tokens[1] + " to the argument map");

				_argMap.put(tokens[0].trim(), tokens[1].trim());
			} else {
				s_logger.warn("unrecognized argument, skip adding it to argument map");
			}
		}
	}
	
	private void run() {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				_quit = true;
				onShutdown();
			}
		});
		
		while(!_quit) {
			String cmdLine = getLaunchCommandLine();
			
			s_logger.info("Launch console proxy process with command line: " + cmdLine);
			
			try {
				_process = Runtime.getRuntime().exec(cmdLine);
			} catch (IOException e) {
				s_logger.error("Unexpected exception ", e);
				System.exit(1);
			}
			
			boolean waitSucceeded = false;
			int exitCode = 0;
			while(!waitSucceeded) {
				try {
					exitCode = _process.waitFor();
					waitSucceeded = true;
					
					if(s_logger.isInfoEnabled())
						s_logger.info("Console proxy process exits with code: " + exitCode);
				} catch (InterruptedException e) {
					if(s_logger.isInfoEnabled())
						s_logger.info("InterruptedException while waiting for termination of console proxy, will retry");
				}
			}
		}
	}
	
	private String getLaunchCommandLine() {
		StringBuffer sb = new StringBuffer("java ");
		String jvmOptions = _argMap.get("jvmoptions");
		
		if(jvmOptions != null)
			sb.append(jvmOptions);
		
		for(Map.Entry<String, String> entry : _argMap.entrySet()) {
			if(!"jvmoptions".equalsIgnoreCase(entry.getKey()))
				sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue());
		}
		
		return sb.toString();
	}
	
	private void onShutdown() {
		if(_process != null) {
			if(s_logger.isInfoEnabled())
				s_logger.info("Console proxy monitor shuts dwon, terminate console proxy process");
			_process.destroy();
		}
	}

	private static void configLog4j() {
		URL configUrl = System.class.getResource("/conf/log4j-cloud.xml");
		if(configUrl == null)
			configUrl = ClassLoader.getSystemResource("log4j-cloud.xml");
		
		if(configUrl == null)
			configUrl = ClassLoader.getSystemResource("conf/log4j-cloud.xml");
			
		if(configUrl != null) {
			try {
				System.out.println("Configure log4j using " + configUrl.toURI().toString());
			} catch (URISyntaxException e1) {
				e1.printStackTrace();
			}

			try {
				File file = new File(configUrl.toURI());
				
				System.out.println("Log4j configuration from : " + file.getAbsolutePath());
				DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000);
			} catch (URISyntaxException e) {
				System.out.println("Unable to convert log4j configuration Url to URI");
			}
		} else {
			System.out.println("Configure log4j with default properties");
		}
	}
	
	public static void main(String[] argv) {
		configLog4j();
		(new ConsoleProxyMonitor(argv)).run();
	}
}
