package com.zaranux.os.client.core;
import com.zaranux.client.java.io.FileInputStream;
import com.zaranux.client.java.io.FileOutputStream;
import java.util.Vector;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ClosingHandler;
import com.google.gwt.user.client.Window.ClosingEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.openmashupos.mhttpserver.client.MHTTPServer;
import com.openmashupos.mhttpserver.client.Servlet;
import com.openmashupos.mhttpserver.client.TransactionContext;
import com.zaranux.client.api.AsyncCallback;
import com.zaranux.client.api.SystemCallAPI;
import com.zaranux.client.api.exceptions.UnauthorizedAccessException;
import com.zaranux.client.app.core.Proxy;
import com.zaranux.client.app.core.Response;
import com.zaranux.client.app.core.SystemCallImpl;
public class Kernel extends SystemCallImpl {
// Let's start process ID numbers from 1000
// the next available process ID
private int nextPID ;
// a vector that keeps the list of all running processes
private Vector<com.zaranux.client.api.types.Process> processTable; // = new Vector<Process>();
private initd initProcess;
private Screen screen; // = new Screen();
private HandlerRegistration closeHandlder;
public void boot(final AsyncCallback<Boolean> callback)
{
// Let's start process ID numbers from 1000
// the next available process ID
nextPID = 1000;
processTable = new Vector<com.zaranux.client.api.types.Process>();
screen = new Screen();
initProcess = new initd(this);
initProcess.screen = screen;
if(initd.getArgs()!=null && !initd.getArgs().equals(""))
{
initProcess.execute();
//Log.getDivLogger().getWidget().removeFromParent();
//screen.getActiveView().addWidget((Log.getDivLogger().getWidget()));
}else
{
if(Proxy.getIdentity().equals(""))
Proxy.setIdentity("zaranux");
deserializeProcesses(callback);
}
thirdPartyCallHandler();
}
private void deserializeProcesses(final AsyncCallback<Boolean> callback)
{
initProcess.deserializeProcess(new FileInputStream("/.zaranux/.processes"), new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean b)
{
bootAfterDeserialize();
callback.onSuccess(true);
}
public void onFailure(Throwable t)
{
if(t instanceof com.zaranux.client.api.exceptions.ResourceNotFound)
{
Log.error("deboot.serializeProcess: no process file : "+t );
processTable.add(initProcess);
}else
{
Log.error("deserializeProcess : "+t );
}
initProcess.defaultApps();
initProcess.execute();
bootAfterDeserialize();
callback.onSuccess(true);
}
});
}
private void bootAfterDeserialize()
{
closeHandlder = Window.addWindowClosingHandler(new ClosingHandler()
{
public void onWindowClosing(ClosingEvent event)
{
//logout();
shotdown(new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean b)
{
Log.debug("shotdown: " + b);
}
public void onFailure(Throwable t)
{
Log.error("shotdown failed: "+t);
}
});
}
});
// Log.getDivLogger().getWidget().removeFromParent();
// screen.getActiveView().addWidget((Log.getDivLogger().getWidget()));
//screen.getActiveView().focus();
Window.addCloseHandler(new CloseHandler<Window>()
{
public void onClose(CloseEvent<Window> event)
{
logout();
}
});
}
void logout()
{
initProcess.serializeProcess(new FileOutputStream("/.zaranux/.processes"), new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean b)
{
Log.debug("serialized!");
}
public void onFailure(Throwable t)
{
Log.error(""+t);
}
});
}
private void shotdown(final AsyncCallback<Boolean> callback)
{
if(Proxy.identityAssertion == null || Proxy.identityAssertion.equals("")) // no need to serialize
{
shotdownAfterSerialize();
callback.onSuccess(true);
return;
}
initProcess.serializeProcess(new FileOutputStream("/.zaranux/.processes"), new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean b)
{
shotdownAfterSerialize();
callback.onSuccess(b);
}
public void onFailure(Throwable t)
{
shotdownAfterSerialize();
callback.onFailure(t);
}
});
}
private void shotdownAfterSerialize()
{
kill(1);
//if(closeHandlder != null)
closeHandlder.removeHandler();
// Let's start process ID numbers from 1000
// the next available process ID
nextPID = 0 ;
// a vector that keeps the list of all running processes
processTable = null;
initProcess = null;
screen = null;
closeHandlder = null;
//initProcess.terminate();
//nextPID = 1000;
// a vector that keeps the list of all running processes
//processTable = new Vector<Process>();
//initProcess = null;
//screen.destroy();
//RootPanel.get().clear(); bad .. also removes the applet
}
private Process getProcess(int PID)
{
for(com.zaranux.client.api.types.Process p: processTable)
{
if(((Process)p).PID == PID)
{
return (Process) p;
}
}
return null;
}
public void login(final String id, String pass, final AsyncCallback<Boolean> callback){
Proxy.getProxy(true).execute("login", "", new String[]{ id,pass }, new AsyncCallback<Response>()
{
public void onSuccess(Response result)
{
final String identityAssertion = result.getString();
if(identityAssertion==null || identityAssertion.equals("") )
{
callback.onSuccess(false); // failed
}
else
{
if(Proxy.getIdentity()== null || Proxy.getIdentity().equals(""))
{
Proxy.setIdentity(id);
Proxy.setIdentityAssertion(identityAssertion);
callback.onSuccess(true);
Log.debug("Loged in as " + id);
return;
}
shotdown(new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean result)
{
Log.debug("shotdown result : " + result);
Proxy.setIdentity(id);
Proxy.setIdentityAssertion(identityAssertion);
callback.onSuccess(true);
boot(new AsyncCallback<Boolean>()
{
public void onSuccess(Boolean result)
{
Log.debug("booted : " + result);
}
public void onFailure(Throwable caught)
{
Log.debug("boot failed : " + caught);
}
});
}
public void onFailure(Throwable caught)
{
Log.debug("shotdown failed : " + caught);
Proxy.setIdentity(id);
Proxy.setIdentityAssertion(identityAssertion);
boot(callback);
}
}
);
}
}
public void onFailure(Throwable caught)
{
callback.onFailure(caught);
}
}
);
}
// system call api implementation
@Override
public Process fork(com.zaranux.client.api.types.Process p, boolean initParent)
{
Process process = (Process) p;
if(process.PID == -1) // a new one not a deserialized one
process.PID = nextPID;
nextPID++;
process.screen = screen;
process.systemcall = (SystemCallAPI) this;
processTable.add(process);
if(initParent)
initProcess.adopt(process);
return process;
}
public Vector<com.zaranux.client.api.types.Process> getProcesses()
{
return processTable;
}
public String userid()
{
return Proxy.getProxy(true).getIdentity();
}
public void kill(int PID)
{
Process p = getProcess(PID);
if(p != null)
{
processTable.remove(p);
p.terminate();
}
}
@Override
protected void handleException(Throwable caught)
{
if(caught instanceof UnauthorizedAccessException && Proxy.getIdentity().equals("zaranux"))
new Login((SystemCallAPI)Kernel.this);
}
public void thirdPartyCallHandler()
{
MHTTPServer mhttpServer = new MHTTPServer();
mhttpServer.registerService("/*", new Servlet()
{
public void serve(final TransactionContext context) {
Log.debug("received : "+ context.getRequest().getText());
String contentType = context.getRequest().getHeader("Content-Type");
boolean base64Data = Boolean.parseBoolean(context.getRequest().getHeader("Base64Contnet"));
String origin = context.getRequest().getHostname();
Log.debug("calling relay for message sent from " + origin + " to path " + context.getRequest().getPath() );
Proxy.getProxy(true).relay(context.getRequest().getPath(), context.getRequest().getText(), contentType, base64Data, origin, new AsyncCallback<Response>()
{
public void onSuccess(Response result)
{
com.openmashupos.mhttpserver.client.Response response = new com.openmashupos.mhttpserver.client.Response();
response.setText("" + result.getText());
Log.debug("relaying the response from server back : " + result.getText());
context.respond(response);
}
public void onFailure(Throwable caught)
{
Log.error("Exception during relaying .. Todo:"); // TODO: relay back the exception
}
}
);
}
});
mhttpServer.run();
}
}