Package org.boris.xlloop

Source Code of org.boris.xlloop.FunctionServer$FunctionContext

/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
*     Peter Smith
*******************************************************************************/
package org.boris.xlloop;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.boris.xlloop.codec.BinaryRequestProtocol;
import org.boris.xlloop.util.XLList;
import org.boris.xlloop.xloper.XLBool;
import org.boris.xlloop.xloper.XLError;
import org.boris.xlloop.xloper.XLInt;
import org.boris.xlloop.xloper.XLSRef;
import org.boris.xlloop.xloper.XLString;
import org.boris.xlloop.xloper.XLoper;

public class FunctionServer implements IBuiltinFunctions
{
    protected int port;
    protected IFunctionHandler handler;
    protected ServerSocket socket;
    protected IFunctionServerListener listener;

    public FunctionServer() {
        this(5454);
    }

    public FunctionServer(int port) {
        this.port = port;
    }

    public int getPort() {
        return socket == null ? port : socket.getLocalPort();
    }

    public FunctionServer(int port, IFunctionHandler f) {
        this.port = port;
        this.handler = f;
    }

    public void setFunctionHandler(IFunctionHandler h) {
        this.handler = h;
    }

    public IFunctionHandler getFunctionHandler() {
        return this.handler;
    }

    public void setListener(IFunctionServerListener listener) {
        this.listener = listener;
    }

    public void stop() throws IOException {
        if (socket != null)
            socket.close();
        socket = null;
    }

    public void start() {
        if (socket != null)
            return;

        Thread t = new Thread(new Runnable() {
            public void run() {
                try {
                    FunctionServer.this.run();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t.setName("XLLoop Function Server");
        t.setDaemon(true);
        t.start();
    }

    public void run() throws IOException {
        if (socket == null)
            socket = new ServerSocket(port);

        while (true) {
            HandlerThread ht = new HandlerThread(handler, socket.accept());
            ht.start();
            if (listener != null)
                listener.connectionCreated(ht);
        }
    }

    public static void handleRequest(IFunctionHandler handler, IRequestProtocol protocol, Socket socket, Session session) {
        try {
            XLoper nameOrVersion = protocol.receive(socket);
            XLString name = null;
            IFunctionContext context = null;
            if (nameOrVersion.type == XLoper.xlTypeInt) {
                int version = ((XLInt) nameOrVersion).w;
                if (version == 20) {
                    XLBool b = (XLBool) protocol.receive(socket);
                    if (b.bool) {
                        XLoper caller = protocol.receive(socket);
                        XLoper sheetName = protocol.receive(socket);
                        XLSRef cref = null;
                        if (caller instanceof XLSRef)
                            cref = (XLSRef) caller;
                        String namestr = null;
                        if (sheetName instanceof XLString)
                            namestr = ((XLString) sheetName).str;
                        context = new FunctionContext(handler, session, cref, namestr);
                    }
                } else {
                    protocol.send(socket, new XLString("#Unknown protocol version"));
                    socket.close();
                    return;
                }
                name = (XLString) protocol.receive(socket);
            } else {
                name = (XLString) nameOrVersion;
            }
            XLInt argCount = (XLInt) protocol.receive(socket);
            XLoper[] args = new XLoper[argCount.w];
            for (int i = 0; i < argCount.w; i++) {
                args[i] = protocol.receive(socket);
            }
            if (!session.init && name.str.equals(INITIALIZE)) {
                initializeSession(session, args);
            }

            if (session.init && context == null)
                context = new FunctionContext(handler, session, null, null);

            XLoper res = handler.execute(context, name.str, args);
            if (res == null)
                res = XLError.NULL;
            protocol.send(socket, res);
        } catch (RequestException e) {
            try {
                protocol.send(socket, new XLString(e.getMessage()));
            } catch (IOException ex) {
                System.err.println(e.getMessage());
                try {
                    socket.close();
                } catch (IOException iex) {
                }
            }
        } catch (Throwable e) {
            System.err.println(e.getMessage());
            try {
                socket.close();
            } catch (IOException ex) {
            }
        }
    }

    private static void initializeSession(Session session, XLoper[] args) {
        session.init = true;
        XLList l = new XLList(args);
        int size = l.size();
        switch (size) {
        default:
        case 3:
            session.key = l.getString(2);
        case 2:
            session.host = l.getString(1);
        case 1:
            session.user = l.getString(0);
        case 0:
            break;
        }
    }

    public static class HandlerThread extends Thread
    {
        private Socket socket;
        private IRequestProtocol protocol = new BinaryRequestProtocol();
        private IFunctionHandler handler;
        private Session session = new Session();

        public HandlerThread(IFunctionHandler handler, Socket socket) {
            super("XLLoop Function Server Handler");
            this.handler = handler;
            this.socket = socket;
        }

        public void run() {
            try {
                protocol.initialise(socket);
            } catch (IOException e) {
            }
            while (!socket.isClosed()) {
                handleRequest(handler, protocol, socket, session);
            }
        }

        public void close() {
            try {
                socket.getInputStream().close();
                socket.getOutputStream().close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static class FunctionContext implements IFunctionContext
    {
        private IFunctionHandler handler;
        private Session session;
        private XLSRef caller;
        private String sheetName;

        public FunctionContext(IFunctionHandler handler, Session session, XLSRef caller, String sheetName) {
            this.handler = handler;
            this.session = session;
            this.caller = caller;
            this.sheetName = sheetName;
        }

        public String getHost() {
            return session.host;
        }

        public String getUser() {
            return session.user;
        }

        public String getUserKey() {
            return session.key;
        }

        public XLSRef getCaller() {
            return caller;
        }

        public String getSheetName() {
            return sheetName;
        }

        public XLoper execute(String name, XLoper[] args) throws RequestException {
            return handler.execute(this, name, args);
        }
    }

    private static class Session
    {
        private String user;
        private String host;
        private String key;
        private boolean init;
    }
}
TOP

Related Classes of org.boris.xlloop.FunctionServer$FunctionContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.