/*
 * 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.oodt.commons;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.rmi.RMISecurityManager;
import java.util.*;
import javax.naming.Context;
import javax.naming.NamingException;
import org.apache.oodt.commons.io.Log;
import org.apache.oodt.commons.util.*;
import org.apache.xmlrpc.XmlRpcClientLite;
import org.apache.xmlrpc.XmlRpcServer;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.rmi.Remote;
import java.rmi.server.RemoteStub;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef;
import java.io.ObjectOutputStream;
import java.io.ByteArrayOutputStream;
import org.apache.oodt.commons.io.Base64EncodingOutputStream;

/** Server execution program.
 *
 * This is an executable class that starts a JPL EDA server.
 *
 * @author Kelly
 */
public class ExecServer {
	/** Start a server.
	 *
	 * The command-line should have two arguments:
	 *
	 * <ol>
	 *   <li>The fully-qualified class name of the server to execute.</li>
	 *   <li>The object name of the server to register with the naming service.</li>
	 * </ol>
	 *
	 * @param argv The command-line arguments
	 */
	public static void main(String[] argv) {
		if (argv.length < 2) {
			System.err.println("Usage: class-name-of-server object-name");
			System.exit(1);
		}

		String className = argv[0];
		String name = argv[1];

		// Enable support of our special URLs, like stdin:
		System.setProperty("java.protocol.handler.pkgs", "org.apache.oodt.commons.net.protocol");

		try {
			// Get the configuration.
			configuration = Configuration.getConfiguration();
			configuration.mergeProperties(System.getProperties());

			// Set up the logger.
			LogInit.init(System.getProperties(), name);

			// Run initializers
			try {
				runInitializers();
			} catch (EDAException ex) {
				ex.printStackTrace();
				System.exit(1);
			}

			// Create it.
			final ExecServer server = new ExecServer(name, className);

			// Print it.
			if (Boolean.getBoolean(PRINT_IOR_PROPERTY)) {
				if (server.getServant() instanceof RemoteObject) {
					RemoteObject remoteObject = (RemoteObject) server.getServant();
					RemoteStub remoteStub = (RemoteStub) RemoteObject.toStub(remoteObject);
					RemoteRef ref = remoteStub.getRef();
					System.out.print("RMI:");
					System.out.flush();
					ObjectOutputStream objOut
						= new ObjectOutputStream(new Base64EncodingOutputStream(System.out));
					objOut.writeObject(ref);
					objOut.flush();
					System.out.println();
				} else {
					org.omg.PortableServer.Servant servant=(org.omg.PortableServer.Servant)server.getServant();
					org.omg.CORBA.ORB orb = servant._orb();
					System.out.println(orb.object_to_string(servant._this_object(orb)));
				}
				System.out.flush();
			}

			// Bind it.
			if (!Boolean.getBoolean(DISABLE_BINDING)) {
				binder = new Binder(name, server);
				binder.start();
			}

			// Prepare for the inevitable
			Runtime.getRuntime().addShutdownHook(new Thread() {
				public void run() {
					server.shutdown0();
				}
			});

			// We're done here.
			for (;;) try {
				Thread.currentThread().join();
			} catch (InterruptedException ignore) {}
		} catch (IOException ex) {
			System.err.println("I/O error during initialization: " + ex.getMessage());
			ex.printStackTrace();
		} catch (SAXParseException ex) {
			System.err.println("Error in the configuration file at line " + ex.getLineNumber() + ", column "
				+ ex.getColumnNumber() + ": " + ex.getMessage());
		} catch (SAXException ex) {
			System.err.println("Error " + ex.getClass().getName() + " while attempting to parse the configuration"
				+ " file: " + ex.getMessage());
		} catch (javax.naming.NamingException ex) {
			System.err.println("Naming/directory error: " + ex.getClass().getName() + ": " + ex.getMessage());
		} catch (java.lang.reflect.InvocationTargetException ex) {
			Throwable target = ex.getTargetException();
			System.err.println("Constructor for \"" + className + "\" threw " + target.getClass().getName() + ": "
				+ ex.getMessage());
			target.printStackTrace();
		} catch (RuntimeException ex) {
			throw ex;
		} catch (Exception ex) {
			System.err.println("Exception " + ex.getClass().getName() + " initializing server \"" + name
				+ "\" with class \"" + className + "\": " + ex.getMessage());
			ex.printStackTrace();
		} 
		System.exit(1);
	}

	protected ExecServer(String name) {
		this.name = name;
	}

	/** Create a new executable server.
	 *
	 * @param name Name of the server
	 * @param className Name of class that implements the server.
	 * @throws ClassNotFoundException If the class for <var>className</var> can't be found.
	 * @throws NoSuchMethodException If the constructor for <var>className</var> taking a single <code>ExecServer</code>
	 *         can't be found.
	 * @throws InstantiationException If the class for <var>className</var> is abstract or is an interface.
	 * @throws IllegalAccessException If the class for <var>className</var> isn't public.
	 * @throws InvocationTargetException If an exception occurs in the constructor for <var>className</var>.
	 * @throws DOMException If the server's status document can't be created.
	 * @throws UnknownHostException If the local host name can't be determined.
	 */
	public ExecServer(String name, String className) throws ClassNotFoundException, NoSuchMethodException,
		InstantiationException, IllegalAccessException, InvocationTargetException, DOMException, UnknownHostException {
		this.name = name;

		// Find the class and the required constructor.
		Class clazz = Class.forName(className);
		Constructor ctor = clazz.getConstructor(new Class[]{ExecServer.class});

		// Invoke the constructor to create the servant.
		servant = ctor.newInstance(new Object[]{this});
		Date startDate = new Date();

		// Create the XML-RPC interface to this server.
		xmlrpcServer = new XmlRpcServer();
		xmlrpcServer.addHandler("server", this);

		// Create the server status document.
		DocumentType docType = XML.getDOMImplementation().createDocumentType("server", STATUS_FPI, STATUS_URL);
		statusDocument = XML.getDOMImplementation().createDocument(/*namespaceURI*/null, "server", docType);
		Element serverElement = statusDocument.getDocumentElement();
		XML.add(serverElement, "name", name);
		XML.add(serverElement, "class", className);
		XML.add(serverElement, "state", "up");
		Element startElement = statusDocument.createElement("start");
		serverElement.appendChild(startElement);
		Element userElement = statusDocument.createElement("user");
		startElement.appendChild(userElement);
		XML.add(userElement, "name", System.getProperty("user.name", "UNKNOWN"));
		XML.add(userElement, "cwd", System.getProperty("user.dir", "UNKNOWN"));
		XML.add(userElement, "home", System.getProperty("user.home", "UNKNOWN"));
		Element dateElement = statusDocument.createElement("date");
		startElement.appendChild(dateElement);
		dateElement.setAttribute("ms", String.valueOf(startDate.getTime()));
		dateElement.appendChild(statusDocument.createTextNode(startDate.toString()));
		XML.add(startElement, "config", System.getProperty("org.apache.oodt.commons.Configuration.url", "UNKNOWN"));
		Element hostElement = statusDocument.createElement("host");
		serverElement.appendChild(hostElement);
		XML.add(hostElement, "name", InetAddress.getLocalHost().getHostName());
		Element osElement = statusDocument.createElement("os");
		hostElement.appendChild(osElement);
		XML.add(osElement, "name", System.getProperty("os.name", "UNKNOWN"));
		XML.add(osElement, "version", System.getProperty("os.version", "UNKNOWN"));
		XML.add(osElement, "arch", System.getProperty("os.arch", "UNKNOWN"));
		Element vmElement = statusDocument.createElement("vm");
		serverElement.appendChild(vmElement);
		XML.add(vmElement, "name", System.getProperty("java.vm.name", "UNKNOWN"));
		XML.add(vmElement, "version", System.getProperty("java.version", "UNKNOWN"));
		XML.add(vmElement, "classpath", System.getProperty("java.class.path", "UNKNOWN"));
		XML.add(vmElement, "extdirs", System.getProperty("java.ext.dirs", "UNKNOWN"));
		logElement = statusDocument.createElement("log");
		serverElement.appendChild(logElement);
	}

	/** Get my name.
	 *
	 * @return The name under which I'm registered in teh naming context.
	 */
	public String getName() {
		return name;
	}

	/** Return the servant for this executable server.
	 *
	 * @return The servant.
	 */
	public Object getServant() {
		return servant;
	}

	/** Control this server.
	 *
	 * @param command Command to send to the server.
	 * @return Results of <var>command</var>.
	 */
	public byte[] control(byte[] command) {
		return xmlrpcServer.execute(new ByteArrayInputStream(command));
	}

	/** Return the server's class name.
	 *
	 * @return Its class name.
	 */
	public String getServerClassName() {
		return className;
	}

	/** Return status of this server.
	 *
	 * @return Its status.
	 */
	public String getServerStatus() {
		// Update the status document with the current log.
		for (Iterator i = LogInit.MEMORY_LOGGER.getMessages().iterator(); i.hasNext();) {
			String message = (String) i.next();
			Element messageElement = statusDocument.createElement("message");
			messageElement.setAttribute("xml:space", "preserve");
			messageElement.appendChild(statusDocument.createTextNode(message));
			logElement.appendChild(messageElement);
		}

		// Serialize the document.
		String rc = XML.serialize(statusDocument);

		// Remove all the log messages from the document.
		NodeList children = logElement.getChildNodes();
		for (int i = 0; i < children.getLength(); ++i)
			logElement.removeChild(children.item(i));

		// Return the serialized form, which included the log messages.
		System.err.println(rc);
		return rc;
	}

	/** Set a system property.
	 *
	 * This uses the property manager to notify property change listeners.
	 *
	 * @param key Property's name.
	 * @param value New value.
	 * @return Zero (return required for XML-RPC access).
	 */
	public int setSystemProperty(String key, String value) {
		System.err.println("Setting system property \"" + key + "\" to \"" + value + "\"");
		PropertyMgr.setProperty(key, value);
		return 0;
	}

	/**
	 * Call the server manager on the local system.
	 *
	 * @param port What port on the local system the server manager is listening.
	 * @param user User name to use for authentication.
	 * @param password Authenticator for <var>user</var>.
	 * @param method What method in the server manager to call.
	 * @param params Parameters to pass to the method named by <var>method</var>.
	 * @return The return value from the method named by <var>method</var>.
	 * @throws Exception If any error occurs.
	 */
	public Object callLocalServerManager(int port, String user, String password, String method, List params) throws Exception {
		XmlRpcClientLite local = new XmlRpcClientLite("localhost", port);
		local.setBasicAuthentication(user, password);
		return local.execute(method, new Vector(params));
	}

	/** Shut down and exit.
	 *
	 * @return Zero.
	 */
	public int shutdown() {
		// Log it.
		System.err.println("Received shutdown command");

		// Make sure we actually exit sometime soon.
		new Thread() {
			public void run() {
				try {
					Thread.sleep(15000);
				} catch (InterruptedException ignore) {}
				System.exit(1);
			}
		}.start();

		// Clean up.
		shutdown0();

		// And exit.
		System.err.println("Calling System.exit with status code 0");
		System.exit(0);
		return 0;
	}

	private void shutdown0() {
		// Unbind.
		if (!Boolean.getBoolean(DISABLE_BINDING)) try {
			binder.stopBinding();
			Context objectContext = configuration.getObjectContext();
			objectContext.unbind(getName());
			objectContext.close();
		} catch (NamingException ignore) {}

		// Kill the ORB.  YEAH!  KILL IT, KILL IT, KIIIIIIIIIIIIIIL IIIIIIIIT!!!!!!!1
		try {
			if (servant instanceof org.omg.PortableServer.Servant) {
				org.omg.PortableServer.Servant s = (org.omg.PortableServer.Servant) servant;
				org.omg.CORBA.ORB orb = s._orb();
				orb.shutdown(false/*=>terminate without waiting for reqs to complete*/);
			}
		} catch (Throwable ignore) {}
	}

	/**
	 * Binding thread.
	 */
	private static class Binder extends Thread {
		public Binder(String name, ExecServer server) {
			super("Binder for " + name);
			setDaemon(true);
			this.name = name;
			this.server = server;
			keepBinding = true;
		}
		public void run() {
			while (shouldKeepBinding()) try {
				Context objectContext = configuration.getObjectContext();
				objectContext.rebind(name, server.getServant());
				objectContext.close();
			} catch (Throwable ex) {
				System.err.println("Exception binding at " + new Date() + "; will keep trying...");
				ex.printStackTrace();
		        } finally {
				try {
					Thread.sleep(REBIND_PERIOD);
				} catch (InterruptedException ignore) {}
			}
		}
		public synchronized void stopBinding() {
			keepBinding = false;
		}
		private synchronized boolean shouldKeepBinding() {
			return keepBinding;
		}
		private boolean keepBinding;
		private String name;
		private ExecServer server;
	}

	/**
	 * Run all initializers.
	 *
	 * This instantiates and calls the {@link Initializer#initialize} method of each
	 * initializer specified by class name in a comma separated list of classes in the
	 * system properties.  The property name is <code>org.apache.oodt.commons.initializers</code>, or
	 * if not defined, <code>org.apache.oodt.commons.ExecServer.initializers</code>, or if not
	 * defined, <code>initializers</code>.  And if that one's not defined, then none
	 * are run.
	 *
	 * @throws EDAException if an error occurs.
	 */
	public static void runInitializers() throws EDAException {
		String initList = System.getProperty("org.apache.oodt.commons.initializers",
			System.getProperty("org.apache.oodt.commons.ExecServer.initializers", System.getProperty("initializers", "")));
		for (Iterator i = org.apache.oodt.commons.util.Utility.parseCommaList(initList); i.hasNext();) {
			String iname = (String) i.next();
			try {
				Class initClass = Class.forName(iname);
				Initializer init = (Initializer) initClass.newInstance();
				init.initialize();
			} catch (ClassNotFoundException ex) {
				System.err.println("Initializer \"" + iname + "\" not found; aborting");
				throw new EDAException(ex);
			} catch (InstantiationException ex) {
				System.err.println("Initializer \"" + iname + "\" is abstract; aborting");
				throw new EDAException(ex);
			} catch (IllegalAccessException ex) {
				System.err.println("Initializer \"" + iname + "\" isn't public; aborting");
				throw new EDAException(ex);
			} catch (EDAException ex) {
				System.err.println("Initializer \"" + iname + "\" failed: " + ex.getMessage());
				throw new EDAException(ex);
			}
		}
	}

	/** The configuration. */
	private static Configuration configuration;

	/** Object key name. */
	protected String name;

	/** The servant. */
	private Object servant;

	/** The server class name. */
	private String className;

	/** Current binder, if any. */
	private static Binder binder;

	/** Server's status document. */
	private Document statusDocument;

	/** The &lt;log&gt; element within the status document. */
	private Element logElement;

	/** The XML-RPC interface to this server. */
	private XmlRpcServer xmlrpcServer;

	/** Status DTD formal public identifier. */
	public static final String STATUS_FPI = "-//JPL//DTD EDA Server Status 1.0";
	
	/** Status DTD system identifier. */
	public static final String STATUS_URL = "http://oodt.jpl.nasa.gov/edm-commons/xml/serverStatus.dtd";

	/** Name of the property that prints the server's IOR or RMI handle. */
	public static final String PRINT_IOR_PROPERTY = "org.apache.oodt.commons.ExecServer.printIOR";

	/** Name of the property that prevents binding of this object with the naming service. */
	public static final String DISABLE_BINDING = "org.apache.oodt.commons.ExecServer.disableBinding";

	/** How long to wait before bind attempts, in ms. */
	private static final long REBIND_PERIOD = Long.getLong("org.apache.oodt.commons.ExecServer.rebindPeriod", 30*60*1000).longValue();
}
