/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jem.internal.proxy.vm.remote;
/*
 *  $RCSfile: RemoteVMServerThread.java,v $
 *  $Revision: 1.8 $  $Date: 2005/05/16 19:11:23 $ 
 */


import java.util.*;
import java.io.*;
import java.net.*;
import org.eclipse.jem.internal.proxy.common.remote.*;
import org.eclipse.jem.internal.proxy.common.*;
/**
 * RemoteVM Server Thread. This thread is the one
 * that waits for connections and spins off 
 * server connection threads. It manages the
 * connection threads and handles shutting them
 * down.
 *
 * System Properties:
 *   proxyvm.port - Port number to use for the ServerSocket (default is 8888)
 *   proxyvm.bufsize - Buffer size to use for TCP/IP buffers (default is system default)
 */

public class RemoteVMServerThread extends Thread implements IVMServer {
	protected List threads = Collections.synchronizedList(new LinkedList());	// List of active threads.
	protected ServerSocket server;	// Server Socket for this application
	private int highestIdentityID = 0;	// Identity codes to identify objects between server and client.
	private IdentityMap objectToIDMap = new IdentityMap(100);	// Map from object to identity id
	private HashMap idToObjectMap = new HashMap(100);	// Map from identity id to object
	
	protected Stack fCallbackHandlerPool = new Stack();	// Stack of free callback handlers
	protected static int NUMBER_FREE_CALLBACKS = 5;	// Number of free callback handlers to keep open.
	
	public static int ID_NOT_FOUND = Commands.NOT_AN_ID;	// The id was not found in the table.
	
	protected int masterIDESocketPort = -1;	// Port of master server socket on IDE. Used for special global requests.
	protected int registryKey = -1;	// Key of registry on the IDE.
	
	// Kludge: Bug in Linux 1.3.xxx of JVM. Closing a socket while the socket is being read/accept will not interrupt the
	// wait. Need to timeout to the socket read/accept before the socket close will be noticed. This has been fixed
	// in Linux 1.4. So on Linux 1.3 need to put timeouts in on those sockets that can be separately closed while reading/accepting.
	static boolean LINUX_1_3 = "linux".equalsIgnoreCase(System.getProperty("os.name")) && System.getProperty("java.version","").startsWith("1.3");	 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
	
	public RemoteVMServerThread(String name) {
		super(name);
	}
	
	// The purpose of this thread is to wait 5 minutes, then see if the IDE is still
	// up. If it isn't it will go down. This is safety mechanism
	// in case the client went down without cleaning up and telling the server to go down.
	// That way it won't hang around forever.
	private boolean goingDown = false;
	private Thread safeClean = new Thread(new Runnable() {
		public void run() {
			while (!goingDown) {
				if (Thread.interrupted())
					continue;	// Get to clean uninterrupted state.
				try {
					Thread.sleep(5 * 60 * 1000);	// Sleep five minutes
					// Test if IDE still up.
					if (!isAlive()) {
						System.err.println("No registry available to connect with after five minutes. Shutting down.");	//$NON-NLS-1$
						requestShutdown();
						break;
					}
				} catch (InterruptedException e) {
				}
			}
		}

		/*
		 * See if still alive
		 */		
		private boolean isAlive() {
			Socket socket = getSocket();
			if (socket != null) {
				try {
					DataOutputStream out = new DataOutputStream(socket.getOutputStream());
					DataInputStream in = new DataInputStream(socket.getInputStream());
					
					try {
						out.writeByte(Commands.ALIVE);
						out.writeInt(registryKey);
						out.flush();
						return in.readBoolean();
						// Now get the result.
					} finally {
						try {
							in.close();
						} catch (IOException e) {
						}
						try {
							out.close();
						} catch (IOException e) {
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();	// They should be closing. If they aren't, then they accumulate and master server will start rejecting new ones.
					}
				}					
			}
			
			return false;
		}	
		
	}, "Timeout Termination Thread"); //$NON-NLS-1$
	
	
	public void run() {
		
		// Initialize the mapping table with certain pre-defined ids.
		synchronized(objectToIDMap) {
			objectToIDMap.put(Void.TYPE, new Integer(Commands.VOID_TYPE));
			idToObjectMap.put(new Integer(Commands.VOID_TYPE), Void.TYPE);
			
			objectToIDMap.put(Boolean.TYPE, new Integer(Commands.BOOLEAN_TYPE));
			idToObjectMap.put(new Integer(Commands.BOOLEAN_TYPE), Boolean.TYPE);
			objectToIDMap.put(Boolean.class, new Integer(Commands.BOOLEAN_CLASS));
			idToObjectMap.put(new Integer(Commands.BOOLEAN_CLASS), Boolean.class);
			
			objectToIDMap.put(Integer.TYPE, new Integer(Commands.INTEGER_TYPE));
			idToObjectMap.put(new Integer(Commands.INTEGER_TYPE), Integer.TYPE);
			objectToIDMap.put(Integer.class, new Integer(Commands.INTEGER_CLASS));
			idToObjectMap.put(new Integer(Commands.INTEGER_CLASS), Integer.class);
			
			objectToIDMap.put(Byte.TYPE, new Integer(Commands.BYTE_TYPE));
			idToObjectMap.put(new Integer(Commands.BYTE_TYPE), Byte.TYPE);
			objectToIDMap.put(Byte.class, new Integer(Commands.BYTE_CLASS));
			idToObjectMap.put(new Integer(Commands.BYTE_CLASS), Byte.class);
			
			objectToIDMap.put(Short.TYPE, new Integer(Commands.SHORT_TYPE));
			idToObjectMap.put(new Integer(Commands.SHORT_TYPE), Short.TYPE);
			objectToIDMap.put(Short.class, new Integer(Commands.SHORT_CLASS));
			idToObjectMap.put(new Integer(Commands.SHORT_CLASS), Short.class);	
			
			objectToIDMap.put(Long.TYPE, new Integer(Commands.LONG_TYPE));
			idToObjectMap.put(new Integer(Commands.LONG_TYPE), Long.TYPE);
			objectToIDMap.put(Long.class, new Integer(Commands.LONG_CLASS));
			idToObjectMap.put(new Integer(Commands.LONG_CLASS), Long.class);
			
			objectToIDMap.put(Character.TYPE, new Integer(Commands.CHARACTER_TYPE));
			idToObjectMap.put(new Integer(Commands.CHARACTER_TYPE), Character.TYPE);
			objectToIDMap.put(Character.class, new Integer(Commands.CHARACTER_CLASS));
			idToObjectMap.put(new Integer(Commands.CHARACTER_CLASS), Character.class);
			
			objectToIDMap.put(Double.TYPE, new Integer(Commands.DOUBLE_TYPE));
			idToObjectMap.put(new Integer(Commands.DOUBLE_TYPE), Double.TYPE);
			objectToIDMap.put(Double.class, new Integer(Commands.DOUBLE_CLASS));
			idToObjectMap.put(new Integer(Commands.DOUBLE_CLASS), Double.class);
			
			objectToIDMap.put(Float.TYPE, new Integer(Commands.FLOAT_TYPE));
			idToObjectMap.put(new Integer(Commands.FLOAT_TYPE), Float.TYPE);
			objectToIDMap.put(Float.class, new Integer(Commands.FLOAT_CLASS));
			idToObjectMap.put(new Integer(Commands.FLOAT_CLASS), Float.class);														
						
			objectToIDMap.put(String.class, new Integer(Commands.STRING_CLASS));
			idToObjectMap.put(new Integer(Commands.STRING_CLASS), String.class);
			
			objectToIDMap.put(java.math.BigDecimal.class, new Integer(Commands.BIG_DECIMAL_CLASS));
			idToObjectMap.put(new Integer(Commands.BIG_DECIMAL_CLASS), java.math.BigDecimal.class);
			
			objectToIDMap.put(java.math.BigInteger.class, new Integer(Commands.BIG_INTEGER_CLASS));
			idToObjectMap.put(new Integer(Commands.BIG_INTEGER_CLASS), java.math.BigInteger.class);
			
			objectToIDMap.put(Number.class, new Integer(Commands.NUMBER_CLASS));
			idToObjectMap.put(new Integer(Commands.NUMBER_CLASS), Number.class);				
			
			objectToIDMap.put(Throwable.class, new Integer(Commands.THROWABLE_CLASS));
			idToObjectMap.put(new Integer(Commands.THROWABLE_CLASS), Throwable.class);	
			
			
			objectToIDMap.put(Object.class, new Integer(Commands.OBJECT_CLASS));
			idToObjectMap.put(new Integer(Commands.OBJECT_CLASS), Object.class);	
						
			objectToIDMap.put(Class.class, new Integer(Commands.CLASS_CLASS));
			idToObjectMap.put(new Integer(Commands.CLASS_CLASS), Class.class);
			
			objectToIDMap.put(java.lang.reflect.AccessibleObject.class, new Integer(Commands.ACCESSIBLEOBJECT_CLASS));
			idToObjectMap.put(new Integer(Commands.ACCESSIBLEOBJECT_CLASS), java.lang.reflect.AccessibleObject.class);								

			objectToIDMap.put(java.lang.reflect.Method.class, new Integer(Commands.METHOD_CLASS));
			idToObjectMap.put(new Integer(Commands.METHOD_CLASS), java.lang.reflect.Method.class);
			
			objectToIDMap.put(java.lang.reflect.Constructor.class, new Integer(Commands.CONSTRUCTOR_CLASS));
			idToObjectMap.put(new Integer(Commands.CONSTRUCTOR_CLASS), java.lang.reflect.Constructor.class);				
			
			objectToIDMap.put(java.lang.reflect.Field.class, new Integer(Commands.FIELD_CLASS));
			idToObjectMap.put(new Integer(Commands.FIELD_CLASS), java.lang.reflect.Field.class);	

			objectToIDMap.put(IVMServer.class, new Integer(Commands.IVMSERVER_CLASS));
			idToObjectMap.put(new Integer(Commands.IVMSERVER_CLASS), IVMServer.class);	

			objectToIDMap.put(ICallback.class, new Integer(Commands.ICALLBACK_CLASS));
			idToObjectMap.put(new Integer(Commands.ICALLBACK_CLASS), ICallback.class);	
			
			objectToIDMap.put(this, new Integer(Commands.REMOTESERVER_ID));
			idToObjectMap.put(new Integer(Commands.REMOTESERVER_ID), this);	

			objectToIDMap.put(RemoteVMServerThread.class, new Integer(Commands.REMOTEVMSERVER_CLASS));
			idToObjectMap.put(new Integer(Commands.REMOTEVMSERVER_CLASS), RemoteVMServerThread.class);	

			objectToIDMap.put(Thread.class, new Integer(Commands.THREAD_CLASS));
			idToObjectMap.put(new Integer(Commands.THREAD_CLASS), Thread.class);	

			objectToIDMap.put(ExpressionProcesserController.class, new Integer(Commands.EXPRESSIONPROCESSERCONTROLLER_CLASS));
			idToObjectMap.put(new Integer(Commands.EXPRESSIONPROCESSERCONTROLLER_CLASS), ExpressionProcesserController.class);	

			try {
				java.lang.reflect.Method getMethod = Class.class.getMethod("getMethod", new Class[] {String.class, (new Class[0]).getClass()}); //$NON-NLS-1$
				objectToIDMap.put(getMethod, new Integer(Commands.GET_METHOD_ID));
				idToObjectMap.put(new Integer(Commands.GET_METHOD_ID), getMethod);	
				
				java.lang.reflect.Method initMethod = ICallback.class.getMethod("initializeCallback", new Class[] {IVMServer.class, Integer.TYPE}); //$NON-NLS-1$
				objectToIDMap.put(initMethod, new Integer(Commands.INITIALIZECALLBACK_METHOD_ID));
				idToObjectMap.put(new Integer(Commands.INITIALIZECALLBACK_METHOD_ID), initMethod);	
				
			} catch (NoSuchMethodException e) {
				// Shouldn't really ever occur.
			}				

			highestIdentityID = Commands.FIRST_FREE_ID;		
		}

		masterIDESocketPort = Integer.getInteger("proxyvm.masterPort", -1).intValue(); //$NON-NLS-1$
		if (masterIDESocketPort == -1) {
			// No ports specified, need to just shutdown.
			shutdown();
			return;
		}
		
		registryKey = Integer.getInteger("proxyvm.registryKey", -1).intValue(); //$NON-NLS-1$
		if (registryKey == -1) {
			// No registry specified, need to just shutdown.
			shutdown();
			return;
		}		
		
		safeClean.setPriority(Thread.MIN_PRIORITY);
		safeClean.start();	
		boolean trying = true;
		try {
			server = new ServerSocket(0, 50 , InetAddress.getByName("localhost")); //$NON-NLS-1$
			trying = false;
			if (LINUX_1_3)
				server.setSoTimeout(1000);	// Linux 1.3 bug, see comment on LINUX_1_3
			if (registerServer(server.getLocalPort())) {
				while(server != null) {
					Socket incoming = null;
					try {
						incoming = server.accept();
					} catch (InterruptedIOException e) {
						continue;	// Timeout, try again
					} catch (NullPointerException e) {
						continue;	// Server could of gone null after test in while, means shutting down. This probably would only happen Linux 1.3.
					}
					Thread st = new ConnectionThread(incoming, this, "Connection Thread"); //$NON-NLS-1$
					threads.add(st);
					safeClean.interrupt();	// Let safeClean know there is a change
					st.start();
					// Null out locals so they can be GC'd since this is a long running loop.
					st = null;
					incoming = null;
				}
			}
		} catch (SocketException e) {
			if (trying || server != null)
				e.printStackTrace();	// Exception and not shutdown request, so print stack trace.
		} catch (Throwable e) {
			e.printStackTrace();
		}
		
		// We've had an exception, either something really bad, or we were closed,
		// so go through shutdowns.
		shutdown();		
	}
	
	
	/**
	 * Get an identityID, return -1 if not found.
	 */
	public int getIdentityID(Object anObject) {
		synchronized(objectToIDMap) {
			Integer id = (Integer) objectToIDMap.get(anObject);
			return id != null ? id.intValue() : ID_NOT_FOUND;
		}
	}
	
	/**
	 * Get an identityID and add it if not found. Place the id in the
	 * ValueObject passed in and return whether it was added (true) or was already in table (false)
	 */
	public boolean getIdentityID(Object anObject, Commands.ValueObject intoValue ) {
		boolean added = false;
		synchronized(objectToIDMap) {
			Integer id = (Integer) objectToIDMap.get(anObject);
			if (id == null) {
				do {
					if (++highestIdentityID == Commands.NOT_AN_ID)
						++highestIdentityID;	// Don't let -1 be a valid id.
					id = new Integer(highestIdentityID);
				} while (idToObjectMap.containsKey(id)); // Make sure not in use, really shouldn't ever happen because we have over 4 billion before it wraps back
				objectToIDMap.put(anObject, id);
				idToObjectMap.put(id, anObject);
				added = true;
			} 
			intoValue.setObjectID(id.intValue());
		}
		return added;
	}
	
	/**
	 * Remove an identity object from the mapping.
	 */
	public void removeObject(Object anObject) {
		synchronized(objectToIDMap) {
			Integer id = (Integer) objectToIDMap.remove(anObject);
			idToObjectMap.remove(id);
		}
	}
	
	/**
	 * Remove an identity object from the mapping, given the id.
	 */
	public void removeObject(int id) {
		synchronized(objectToIDMap) {
			Object o = idToObjectMap.remove(new Integer(id));
			objectToIDMap.remove(o);
		}
	}
	
	/**
	 * Get the object for an identity id
	 */
	public Object getObject(int id) {
		synchronized(objectToIDMap) {
			return idToObjectMap.get(new Integer(id));
		}
	} 
	
	/**
	 * Remove a thread from the list.
	 */
	public void removeConnectionThread(Thread thread) {
		threads.remove(thread);
		safeClean.interrupt();	// Let safe clean know there is a change.
	}
	
	/**
	 * Use this to request a shutdown. If the server hasn't even been
	 * created yet, this will return false.
	 */
	public boolean requestShutdown() {		
		if (server == null)
			return false;
		// Closing the server socket should cause a break.
		try {
			ServerSocket srv = server;
			server = null;	// So that server knows it is being shutdown and not print exception msg.
			srv.close();
		} catch (Exception e) {
		}
		return true;
	}
	
	/**
	 * Request a callback stream to write to.
	 * When done, the stream should be closed to release the connection.
	 */
	public OutputStream requestStream(int callbackID, int msgID)  throws CommandException {
		CallbackHandler h = (CallbackHandler) getFreeCallbackHandler();
		if (h == null)
			throw new CommandException("No callback handler retrieved.", null);	//$NON-NLS-1$
		h.initiateCallbackStream(callbackID, msgID);
		return new CallbackOutputStream(h, this);
	}
	
	protected void shutdown() {
		goingDown = true;
		safeClean.interrupt();	// Let safeClean know to come down.
		
		if (server != null)
			try {
				server.close();	// Close it so that no more requests can be made.
			} catch (Exception e) {
			}
		
		// Go through each thread and ask it to close. Make a copy of the list so that we
		// won't get into deadlocks.
		ConnectionThread[] threadsArray = (ConnectionThread[]) threads.toArray(new ConnectionThread[0]);
		for (int i=0; i<threadsArray.length; i++) {
			// This is a harsh way to shut a connection down, but there's no
			// other way I know of to interrupt the read on a socket.
			threadsArray[i].close();
		}
			
		// Now that they've been told to close, wait on each one to finish.
		for (int i=0; i<threadsArray.length; i++)
			try {
				threadsArray[i].join(10000);	// Wait ten seconds, if longer, just go on to next one.
				if (threadsArray[i].isAlive())
					System.out.println("*** Connection "+i+" did not die.");
			} catch (InterruptedException e) {
			}
	
		if (safeClean.isAlive()) {
			try {	
				safeClean.join(10000);
				if (safeClean.isAlive())
					System.out.println("*** Cleanup thread did not die.");
			} catch (InterruptedException e) {
			}
		}
		
		// Now close the callbacks.
		synchronized(fCallbackHandlerPool) {
			// Now we walk through all of the free handlers and close them properly.
			Iterator itr = fCallbackHandlerPool.iterator();
			while (itr.hasNext()) {
				((CallbackHandler) itr.next()).closeHandler();
			}
			
			fCallbackHandlerPool.clear();
		}					
	}
	
	/**
	 * Return a free callback handler
	 */
	public ICallbackHandler getFreeCallbackHandler() {
		synchronized(fCallbackHandlerPool) {
			if (!fCallbackHandlerPool.isEmpty())
				return (ICallbackHandler) fCallbackHandlerPool.pop();
			// else we need to allocate one.			
			return createCallbackHandler();
		}
	}
	
	/**
	 * Make a new callback handler
	 */
	protected ICallbackHandler createCallbackHandler() {
		Socket callbackSocket = requestCallbackSocket();
		if (callbackSocket != null) {
			CallbackHandler handler = new CallbackHandler(callbackSocket, this);
			if (handler.isConnected())
				return handler;
				
			// Failed, close the socket.
			try {
				callbackSocket.close();
			} catch (IOException e) {
			}
		}
		return null;
	}	
	
	/**
	 * Free the handler
	 */
	public void returnCallbackHandler(ICallbackHandler aHandler) {
		CallbackHandler handler = (CallbackHandler) aHandler;
		if (handler.isConnected())
			synchronized (fCallbackHandlerPool) {
				if (fCallbackHandlerPool.size() < NUMBER_FREE_CALLBACKS)
					fCallbackHandlerPool.push(handler);
				else
					handler.closeHandler();	// We don't need to maintain more than five free connections.
			}
	}
	
	/**
	 * Process a callback.
	 */
	public Object doCallback(ICallbackRunnable run) throws CommandException {
		CallbackHandler handler = (CallbackHandler) getFreeCallbackHandler();
		if (handler != null) {
			try {
				try {
					return run.run(handler);
				} catch (CommandErrorException e) {
					// This is command error, connection still good, don't retry, just pass it on.
					// It means the other side said I processed it, but there is an error.
					throw e;
				} catch (CommandException e) {
					if (!e.isRecoverable()) {
						// Close this handler and try a new one, one more time.
						handler.closeHandler();
						handler = (CallbackHandler) getFreeCallbackHandler();
						try {
							return run.run(handler);											
						} catch (CommandException eAgain) {
							// It failed again, just close the connection and rethrow the exception.
							handler.closeHandler();
							throw eAgain;
						}
					} else
						throw e;	// Recoverable, rethrow exception.
				}
			} finally {
				returnCallbackHandler(handler);
			}
		} else
			throw new CommandException("No callback handler retrieved.", null);	//$NON-NLS-1$
		
	}
	
	/*
	 * Register the server. Return if ide still active
	 */
	private boolean registerServer(int vmserverPort) {
		Socket socket = getSocket();
		if (socket != null) {
			try {
				DataOutputStream out = new DataOutputStream(socket.getOutputStream());
				DataInputStream in = new DataInputStream(socket.getInputStream());
				
				try {
					out.writeByte(Commands.REMOTE_STARTED);
					out.writeInt(registryKey);
					out.writeInt(vmserverPort);
					out.flush();
					return in.readBoolean();
				} finally {
					try {
						in.close();
					} catch (IOException e) {
					}
					try {
						out.close();
					} catch (IOException e) {
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}					

		}
		
		return false;
	}
	
	/*
	 * Request the callback socket. <code>null</code> if there isn't one.
	 */
	private Socket requestCallbackSocket() {
		Socket socket = getSocket();
		if (socket != null) {
			boolean closeSocket = true;
			try {
				DataOutputStream out = new DataOutputStream(socket.getOutputStream());
				DataInputStream in = new DataInputStream(socket.getInputStream());
				
				try {
					out.writeByte(Commands.ATTACH_CALLBACK);
					out.writeInt(registryKey);
					out.flush();
					closeSocket = !in.readBoolean();
					return !closeSocket ? socket : null;
				} finally {
					if (closeSocket) {
						try {
							in.close();
						} catch (IOException e) {
						}
						try {
							out.close();
						} catch (IOException e) {
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (closeSocket) {
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}					
		}
		
		return null;
	}	
	


	protected Socket getSocket() {
		// We are putting it off into a thread because there are no timeout capabilities on getting a socket.
		// So we need to allow for that.		
		final Socket[] scArray = new Socket[1];
		final boolean[] waiting = new boolean[] {true};		
		Thread doIt = new Thread(new Runnable() {
			public void run() {
				try {
					Socket sc = new Socket("localhost", masterIDESocketPort); //$NON-NLS-1$
					synchronized (this) {
						if (waiting[0])
							scArray[0] = sc;
						else
							sc.close();	// We are no longer waiting on this thread so close the socket since no one will use it.
					}					
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
		
		doIt.start();
		while (true) {
			try {
				doIt.join(60000);
				synchronized (doIt) {
					waiting[0] = false;	// To let it know we are no longer waiting
				}
				break;
			} catch (InterruptedException e) {
			}
		}
		
		if (scArray[0] == null) {
			System.out.println("Couldn't retrieve a socket from master server in 60 seconds.");	//$NON-NLS-1$
			return null;	// Couldn't get one, probably server is down.
		}
			
		return scArray[0];
	}
}
