//----------------------------BEGIN LICENSE----------------------------
/*
* Willow : the Open Source WorkFlow Project
* Distributable under GNU LGPL license by gun.org
*
* Copyright (C) 2004-2010 huihoo.org
* Copyright (C) 2004-2010 ZosaTapo <dertyang@hotmail.com>
*
* ====================================================================
* Project Homepage : http://www.huihoo.org/willow
* Source Forge : http://sourceforge.net/projects/huihoo
* Mailing list : willow@lists.sourceforge.net
*/
//----------------------------END LICENSE-----------------------------
package org.huihoo.willow.core;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.MarshalledObject;
import java.rmi.Remote;
import java.rmi.server.UnicastRemoteObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.willow.Globals;
import org.huihoo.willow.LifecycleException;
import org.huihoo.willow.NamingServer;
import org.huihoo.willow.client.ServiceContextImpl;
import org.huihoo.willow.util.StringManager;
/**
* @author reic
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class StandardNamingServer extends NamingServerBase implements NamingServer
{
private static Log log = LogFactory.getLog(StandardNamingServer.class);
/**
* The string manager for this package.
*/
private static StringManager sm = StringManager.getManager(Constants.PACKAGE);
// ----------------------------------------------------- Instance Variables
/**
* Descriptive information about this NamingServer implementation.
*/
private static final String info = "org.huihoo.willow.core.StandardNamingServer/1.0";
/**
* The request scheme that will be set on all requests received
* through this namingProvider.
*/
private String scheme = Globals.PROTOCOL_WORKFLOW_LIVE;
/** The ServiceContext interface server implementation */
protected ServiceContextImpl serviceContextImpl;
private MarshalledObject serverStub;
/** The naming server socket through which the ServiceContextImpl stub is vended */
private ServerSocket serverSocket;
/**
* The background thread.
*/
private Thread thread = null;
/**
* The background thread completion semaphore.
*/
private boolean threadDone = false;
// ------------------------------------------------------------- Properties
/**
* Return descriptive information about this NamingServer implementation.
*/
public String getInfo()
{
return (info);
}
/**
* Return the scheme that will be assigned to requests received
* through this namingProvider. Default value is "http".
*/
public String getScheme()
{
return (this.scheme);
}
/**
* Set the scheme that will be assigned to requests received through
* this namingProvider.
*
* @param scheme The new scheme
*/
public void setScheme(String scheme)
{
this.scheme = scheme;
setProperty("scheme", scheme);
}
// ------------------------------------------------------ Lifecycle Methods
/**
* Begin processing requests via this NamingServer.
*
* @exception LifecycleException if a fatal startup error occurs
*/
public void start() throws LifecycleException
{
// Validate and update our current state
if (started)
{
log.info(sm.getString("standardNamingServer.alreadyStarted"));
return;
}
try
{
serviceContextImpl = new ServiceContextImpl(this);
}
catch (Throwable e)
{
e.printStackTrace();
}
lifecycle.fireLifecycleEvent(START_EVENT, null);
threadStart();
super.start();
}
/**
* Terminate processing requests via this NamingServer.
*
* @exception LifecycleException if a fatal shutdown error occurs
*/
public void stop() throws LifecycleException
{
// Validate and update our current state
if (!started)
{
log.error(sm.getString("standardNamingServer.notStarted"));
return;
}
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
// Stop the existing server
threadStop();
super.stop();
}
/**
* Start the background thread that will periodically check for
* session timeouts.
*/
protected void threadStart()
{
if (thread != null)
return;
try
{
Remote namingStub = UnicastRemoteObject.exportObject(serviceContextImpl, Globals.PORT_NAMING_SERVICE);
log.debug("ServiceContextImpl stub: " + namingStub);
serverStub = new MarshalledObject(namingStub);
serverSocket = new ServerSocket(port, acceptCount, InetAddress.getByName(address));
}
catch (Exception e)
{
log.fatal(sm.getString("standardNamingServer.startFailed", e));
return;
}
threadDone = false;
String threadName = "Willow NamingServer[" + toString() + "]";
thread = new Thread(new NamingServerListener(), threadName);
thread.setDaemon(true);
thread.start();
}
/**
* Stop the background thread that is periodically checking for
* session timeouts.
*/
protected void threadStop()
{
if (thread == null)
return;
threadDone = true;
try
{
Socket s = null;
// Need to create a connection to unlock the accept();
if (address == null)
{
s = new Socket("127.0.0.1", port);
}
else
{
s = new Socket(address, port);
}
s.close();
}
catch (Exception e)
{
log.error("Caught exception trying to unlock accept on " + port + " " + e.toString());
}
try
{
serverSocket.close();
UnicastRemoteObject.unexportObject(serviceContextImpl, true);
}
catch (Exception e)
{
log.error("Caught exception trying to close socket.", e);
}
serverSocket = null;
serviceContextImpl=null;
thread = null;
}
protected class NamingServerListener implements Runnable
{
public void run()
{
while (!threadDone)
{
Socket socket = null;
// Accept a connection
try
{
socket = serverSocket.accept();
}
catch (IOException e)
{
}
if (threadDone)
{
if(socket!=null)
{
try{socket.close();}catch(Exception ex){}
}
break;
}
new Thread(new NamingServerProcessor(socket)).start();
}
}
}
protected class NamingServerProcessor implements Runnable
{
private Socket socket;
public NamingServerProcessor(Socket socket)
{
this.socket = socket;
}
public void run()
{
//Return the naming server stub
try
{
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(serverStub);
}
catch (IOException ex)
{
log.error("Error writing response", ex);
}
}
}
}