package org.one.stone.soup.xapp.application.server;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.JOptionPane;
import org.one.stone.soup.exception.ExceptionHelper;
import org.one.stone.soup.server.http.FileServer;
import org.one.stone.soup.server.http.HttpServer;
import org.one.stone.soup.server.http.Logger;
import org.one.stone.soup.server.http.authentication.HttpAuthenticator;
import org.one.stone.soup.server.http.routers.HttpFileRouter;
import org.one.stone.soup.server.http.routers.HttpInversionRouter;
import org.one.stone.soup.server.http.routers.HttpLoadBalancingRouter;
import org.one.stone.soup.server.http.routers.HttpRouter;
import org.one.stone.soup.server.http.routers.HttpTunnelRouter;
import org.one.stone.soup.stringhelper.StringArrayHelper;
import org.one.stone.soup.util.Queue;
import org.one.stone.soup.xapp.XappDB;
import org.one.stone.soup.xapp.XappPlugin;
import org.one.stone.soup.xapp.XappRootApplication;
import org.one.stone.soup.xapp.ajax.server.AjaxRouter;
import org.one.stone.soup.xapp.components.XappTextArea;
import org.one.stone.soup.xapp.controller.xml.XmlApplication;
import org.one.stone.soup.xml.XmlElement;
import org.one.stone.soup.xml.helper.XmlHelper;
public class XappServer extends XmlApplication implements Logger{
private static String APP_DEFINITION_PATH = "./org/one/stone/soup/xapp/application/server/";
private Hashtable servers;
private Hashtable services;
private class XappLogger implements Runnable,Logger
{
private Queue queue = new Queue();
private boolean running = false;
private XappServer server;
public XappLogger(XappServer server)
{
this.server = server;
Thread thread = new Thread(this,"Xapp Server Log Dethreader");
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
public void log(XmlElement entry)
{
queue.post( entry );
}
public void log(String entry)
{
queue.post( entry );
}
public void run()
{
running = true;
server.log("Logger started");
while(running)
{
try{
while( queue.isEmpty()==false )
{
Object entry = queue.get();
if(entry instanceof XmlElement)
{
_log((XmlElement)entry);
}
else
{
_log(entry.toString());
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
running = false;
server.log("Logger stopped");
}
}
private XappLogger logDethreader;
public static void main(String[] args)
{
if(args.length==1)
{
APP_DEFINITION_PATH = args[0];
}
try{
new XappServer ();
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,ExceptionHelper.getStackTrace(e));
}
}
public XappServer () throws Exception
{
super(APP_DEFINITION_PATH+"xapp-server.xml");
XappPlugin[] plugins = XappRootApplication.getPluginStore().getPlugins();
for(int loop=0;loop<plugins.length;loop++)
{
if(plugins[loop] instanceof XappServerListener)
{
((XappServerListener)plugins[loop]).xappServerIsReady(this);
}
}
}
public void initialise()
{
super.initialise();
logDethreader = new XappLogger(this);
openSchema(APP_DEFINITION_PATH+"server-schema.xml",false);
servers=new Hashtable();
services = new Hashtable();
XmlElement servers = XappDB.findElements("xpath.model:xapp-server/servers");
for(int loop=0;loop<servers.getAttributeCount();loop++)
{
XmlElement server = servers.getElementByIndex(loop);
String autostart = server.getAttributeValueByName("autostart");
if(autostart!=null)
{
if(server.getName().equals("http-server"))
{
if(autostart.equals("true"))
{
startHttpServer(server);
}
else if(this.servers==null || this.servers.get(server.getAttributeValueByName("name"))==null)
{
server.setAttributeValue("status","Stopped");
}
}
}
}
}
public void log(String entry)
{
logDethreader.log(entry);
}
public void log(XmlElement entry)
{
logDethreader.log(entry);
}
private void _log(XmlElement entry)// dethreaded method
{
//log( entry.toXml(false,true) );
String message = entry.getElementByName("message").getValue();
if(entry.getElementByName("size")!=null)
{
message = message+" size:"+entry.getElementByName("size").getValue();
}
log(message);
}
private void _log(String entry)
{
entry = new SimpleDateFormat("HH:mm:ss").format(new Date())+" "+entry;
XappTextArea dataField = (XappTextArea)XappRootApplication.getComponentStore().getXappComponent("status.data");
String data = dataField.getData();
String[] lines = StringArrayHelper.parseFields(data,'\n');
if(lines.length>35)
{
data = StringArrayHelper.arrayToString(lines,"\n",lines.length-35,lines.length)+'\n';
dataField.setData( data );
}
dataField.append(entry+'\n');
}
public void startHttpServer()
{
XmlElement serverNode = getCurrentSelectedNode();
startHttpServer(serverNode);
}
public void stopHttpServer()
{
XmlElement serverNode = getCurrentSelectedNode();
stopHttpServer(serverNode);
}
public void startHttpServer(XmlElement xServer)
{
stopHttpServer(xServer);
String name = xServer.getAttributeValueByName("name");
String address = xServer.getAttributeValueByName("address");
int port = Integer.parseInt(xServer.getAttributeValueByName("port"));
HttpServer server = buildServer(xServer);
if(server!=null)
{
server.setLogger( this );
servers.put(name,server);
server.start( name,address,port,100,1000 );
xServer.setAttributeValue("status","Running");
openForm(getXmlData(),xServer);
log("Server "+name+" started at "+address+" on port "+port);
}
}
public void stopHttpServer(XmlElement xServer)
{
String name = xServer.getAttributeValueByName("name");
String address = xServer.getAttributeValueByName("address");
int port = Integer.parseInt(xServer.getAttributeValueByName("port"));
if(servers==null)
{
return;
}
HttpServer server = (HttpServer)servers.get( name );
if(server!=null)
{
server.stop();
servers.remove(name);
xServer.setAttributeValue("status","Stopped");
openForm(getXmlData(),xServer);
log("Server "+name+" stopped at "+address+" on port "+port);
}
}
private HttpServer buildServer(XmlElement xServer)
{
String name = xServer.getAttributeValueByName("name");
String root = xServer.getAttributeValueByName("root");
HttpServer server = new HttpServer(XappDB.findElement("xpath.model:xapp-server/mime-types"),name,root);
Vector services = xServer.getElementsByName("http-service");
for(int loop=0;loop<services.size();loop++)
{
XmlElement xService = (XmlElement)services.elementAt(loop);
String serviceAlias = xService.getAttributeValueByName("name");
String serviceName = xService.getAttributeValueByName("service");
XmlElement authentication = xService.getElementByName("authentication-server");
XmlElement xServiceDefinition = XappDB.findElement("xpath.model:xapp-server/services/node()[@name=\""+serviceName+"\"]");
HttpRouter service = buildService( server,name,xServiceDefinition );
if(authentication!=null)
{
String address = authentication.getAttributeValueByName("address");
int port = Integer.parseInt(authentication.getAttributeValueByName("port"));
String domain = authentication.getAttributeValueByName("domain");
String subDomain = authentication.getAttributeValueByName("subdomain");
try{
HttpAuthenticator authenticator = new HttpAuthenticator(server.getFileServer(),address,port,domain,subDomain);
service.setAuthenticator(authenticator);
}
catch(Exception e)
{
XappRootApplication.displayException(e);
XappRootApplication.displayMessage("Server "+name+" not built as HttpAuthenticator failed");
return null;
}
}
server.addRoute(serviceAlias,service,xService.getElementByName("condition"));
}
return server;
}
private HttpRouter buildService(HttpServer server,String name,XmlElement xServiceDefinition)
{
HttpRouter router = null;
String type = xServiceDefinition.getName();
router = (HttpRouter)services.get(type+"."+name);
if(router!=null)
{
return router;
}
if(type.equals("http-file-service"))
{
String root = xServiceDefinition.getAttributeValueByName("root");
String page404 = xServiceDefinition.getAttributeValueByName("404-file");
String indexPage = xServiceDefinition.getAttributeValueByName("index-page");
String showDirectoryListings = xServiceDefinition.getAttributeValueByName("show-directory-listings");
boolean directoryListings = false;
if(showDirectoryListings!=null)
{
directoryListings = new Boolean(showDirectoryListings).booleanValue();
}
router = new HttpFileRouter(name,new FileServer(new File(root),new File(page404),indexPage,getMimeTypes()),directoryListings);
}
else if(type.equals("http-ajax-service"))
{
String root = xServiceDefinition.getAttributeValueByName("root");
String page404 = xServiceDefinition.getAttributeValueByName("404-file");
String indexPage = xServiceDefinition.getAttributeValueByName("index-page");
router = new AjaxRouter(name,new FileServer(new File(root),new File(page404),indexPage,getMimeTypes()));
}
else if(type.equals("http-inversion-router"))
{
String root = xServiceDefinition.getAttributeValueByName("root");
String page404 = xServiceDefinition.getAttributeValueByName("404-file");
String indexPage = xServiceDefinition.getAttributeValueByName("index-page");
router = new HttpInversionRouter(name,new FileServer(new File(root),new File(page404),indexPage,getMimeTypes()));
}
else if(type.equals("http-tunnel-service"))
{
String root = xServiceDefinition.getAttributeValueByName("root");
String page404 = xServiceDefinition.getAttributeValueByName("404-file");
String indexPage = xServiceDefinition.getAttributeValueByName("index-page");
router = new HttpTunnelRouter(name,new FileServer(new File(root),new File(page404),indexPage,getMimeTypes()));
}
else if(type.equals("http-load-balance-service"))
{
HttpLoadBalancingRouter balancingRouter = new HttpLoadBalancingRouter(name,server.getFileServer());
router = balancingRouter;
XmlElement balancingServers = xServiceDefinition.getElementByName("http-balance-servers");
for(int loop=0;loop<balancingServers.getElementCount();loop++)
{
XmlElement balancingServer = balancingServers.getElementByIndex(loop);
balancingRouter.addBalancingServer( balancingServer.getAttributeValueByName("address"),Integer.parseInt(balancingServer.getAttributeValueByName("port")) );
}
}
if(router!=null)
{
services.put(type+"."+ xServiceDefinition.getAttributeValueByName("name"),router);
}
return router;
}
public HttpRouter getService(String type,String name)
{
if(services==null)
{
return null;
}
return (HttpRouter)services.get(type+"."+name);
}
public HttpServer getServer(String name)
{
return (HttpServer)servers.get(name);
}
public Hashtable getMimeTypes()
{
XmlElement mimeTypes = XappDB.findElement("xpath.model:xapp-server/mime-types");
Hashtable types = XmlHelper.getElementAsHashtable(mimeTypes,"file-extension");
return types;
}
}