Package abstrasy.libraries.io

Source Code of abstrasy.libraries.io.External_Server

package abstrasy.libraries.io;


import abstrasy.Bivalence;
import abstrasy.Interpreter;
import abstrasy.Node;
import abstrasy.SELF;

import abstrasy.externals.AExtCachable;
import abstrasy.externals.AExtClonable;
import abstrasy.externals.OptAccess;
import abstrasy.externals.OptAccessList;
import abstrasy.externals.OptAccessProvider;

import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.ORef;
import abstrasy.interpreter.StdErrors;

import java.lang.ref.WeakReference;

import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;


/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
*   http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/

public class External_Server extends OptAccessProvider implements AExtClonable, AExtCachable {

    boolean inUse = false;

    int soTimeOut=0;
    String protocol=null;
    int tcpPort = 0;
    int maxConnexion=0;
    InetAddress maskIp = null;
   
    ServerSocket serverSocket = null;

     private OptAccess oa_socket_timeout = new OptAccess("socket-timeout") {

        public Node getNode() {
            return new Node(soTimeOut);
        }

        public void setNode(Node optNode) throws Exception {
            optNode.requireNodeType(Node.TYPE_NUMBER);
            soTimeOut = Math.min(0, (int) optNode.getNumber());
        }

    };
   
    private OptAccess oa_Protocol = new OptAccess("Protocol") {

        public Node getNode() {
            return new Node(protocol);
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess oa_Port = new OptAccess("Port") {

        public Node getNode() {
            return new Node(serverSocket!=null ? serverSocket.getLocalPort() : tcpPort);
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess oa_Max_Connections = new OptAccess("Max-Connections") {

        public Node getNode() {
            return new Node(maxConnexion);
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess oa_Bind_IP = new OptAccess("Bind-IP") {

        public Node getNode() {
            return maskIp!=null ? new Node(maskIp.getHostAddress()):Node.NOTHING_FINAL_NODE;
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess oa_Host = new OptAccess("Host") {

        public Node getNode() {
            return serverSocket!=null ? new Node(serverSocket.getInetAddress().getHostName()):Node.NOTHING_FINAL_NODE;
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess oa_IP = new OptAccess("IP") {

        public Node getNode() {
            return serverSocket!=null ? new Node(serverSocket.getInetAddress().getHostAddress()):Node.NOTHING_FINAL_NODE;
        }

        public void setNode(Node optNode) throws Exception {
            throw new InterpreterException(StdErrors.Illegal_access_to_final_value);
        }

    };
   
    private OptAccess[] DEFAULT_OPTIONS = new OptAccess[] { oa_socket_timeout, oa_Protocol, oa_Port,oa_Max_Connections,oa_Bind_IP,oa_Host,oa_IP};


    public External_Server() {
        this.setOptAccessList(new OptAccessList(DEFAULT_OPTIONS));
    }


    /*
     * ----------------------------------------------------------------------------
     */

    public Node external_mutator_open_tcp(Node startAt) throws Exception {
        /*
         * formes:
         *  (:open-tcp!)
         *  (:open-tcp! port)
         *  (:open-tcp! port max-connexion)
         *  (:open-tcp! port max-connexion "ListenAddr") # l'ListenAddr est l'ip ou l'adresse où le serveur écoute.
         */
        if (inUse)
            throw new InterpreterException(StdErrors.extend(StdErrors.Already_used, "Server is already runing"));
        startAt.isGoodArgsCnt(1, 2, 3, 4);
        SELF.require_SELF_mutable();

        tcpPort=0;
        maxConnexion = 0;
        maskIp = null;


        switch (startAt.size()) {
            case 4:
                maskIp = InetAddress.getByName(startAt.getSubNode(3, Node.TYPE_STRING).getString());
            case 3:
                maxConnexion = (int) startAt.getSubNode(2, Node.TYPE_NUMBER).getNumber();
            case 2:
                tcpPort = (int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber();
                break;
            default:
                tcpPort=0;
                maxConnexion=0;
                maskIp=null;
        }

        if (tcpPort < 0 || tcpPort > 65535)
            throw new InterpreterException(StdErrors.extend(StdErrors.Out_of_range, "" + tcpPort));

        serverSocket = new ServerSocket(tcpPort, maxConnexion, maskIp);

        soTimeOut=0;
        protocol="tcp";
       
        /*
         * On place un hook en cas de problème ou d'oubli...
         */
        putHook();
        inUse = true;
        return null;
    }

    public Node external_mutator_close(Node startAt) throws Exception {
        startAt.isGoodArgsCnt(1);
        SELF.require_SELF_mutable();
        internal_close();
        /*
         * On retire le hook puisque les fichiers sont fermé correctement.
         */
        removeHook();
        return null;
    }
   
    public Node external_is_opened(Node startAt) throws Exception {
        startAt.isGoodArgsCnt(1);
        return new Node(inUse ? Node.TRUE: Node.FALSE);
    }

    public Node external_mutator_accept(Node startAt) throws Exception {
        startAt.isGoodArgsCnt(1);
        SELF.require_SELF_mutable();
       
        serverSocket.setSoTimeout((int)oa_socket_timeout.getNode().getNumber());
        Socket sock=null;
       
        try{
            sock = serverSocket.accept();
        }
        catch(SocketTimeoutException soe){
            sock=null;
        }
       
        // si le time-out est atteint, on retourne NOTHING
        if(sock==null)
            return Node.createNothing();
       
        // si une connexion est ouverte, on retourne un File
        External_File file = new External_File();
        file.setSocket(sock);
        file.setInputStream(sock.getInputStream());
        file.setOutputStream(sock.getOutputStream());
        // le file est automatiquement marqué comme ouvert.
        file.setTcpPort(sock.getPort());
        file.setTcpHost(sock.getInetAddress().getHostName());
        file.setTcpIP(sock.getInetAddress().getHostAddress());
        file.setProtocol(protocol);
        file.setOptAccessList(new OptAccessList(file.getSOCKET_OPTIONS()));
        file.getOptAccessList().set(file.getOa_Host());
        file.getOptAccessList().set(file.getOa_IP());
        file.getOptAccessList().set(file.getOa_Port());
                                   

        return create_File_adp(file);
       
       
    }

    /*
     * ----------------------------------------------------------------------------
     *
     *
     *
     */

    private Node create_File_adp(External_File efile) throws Exception {
        return Node.createExternal(efile);
    }

    public void internal_close() throws Exception {
        if (serverSocket != null)
            serverSocket.close();
        serverSocket = null;
        soTimeOut=0;
        protocol=null;
        tcpPort=0;
        maxConnexion=0;
        maskIp=null;
        inUse = false;
    }

    /**
     *  Clé du hook...
     */
    private Object myHookKey;

    /**
     * Ajoute un hook en cas où on oublierait de fermer les fichiers et les flux...
     *
     * Ce hook sera automatiquement exécuté lors de l'arrêt de l'interpréteur, à moins
     * que le fichier soit refermé manuellement. De cette manière, les fichiers devraient
     * conserver un état stable.
     *
     */
    private void putHook() {

        final WeakReference<External_Server> myself = new WeakReference<External_Server>(this);
        Runnable hook = new Runnable() {

            public void run() {
                External_Server me = myself.get();
                if (me != null) {
                    if (Interpreter.isDebugMode()) {
                        Interpreter.Log("Io:Server Hook : close " + me + "...");
                    }
                    try {
                        me.internal_close();
                    }
                    catch (Exception e) {
                        Interpreter.Log(" -> Exception: " + e.toString());
                    }
                }
            }

        };

        myHookKey = Interpreter.supervisor_PUTHOOK(hook);
    }

    /**
     * On retire le hook...
     */
    private void removeHook() {
        Interpreter.supervisor_REMOVEHOOK(myHookKey);
        myHookKey = null;
    }


    @Override
    public Object clone_my_self(Bivalence bival) {
        return null;
    }


    /*
     * ----------------------------------------------------------------------------
     *
     * Optimisation par cache d'instanciantion (mars 2012) rev 1.0-6321.0
     *
     * ----------------------------------------------------------------------------
     */


    private static ORef _optim_symbols_cache_ = new ORef();
   
    @Override
    public Object getSymbolsCache() {
        return _optim_symbols_cache_.getRef();
    }

    @Override
    public void setSymbolsCache(Object cache) {
        _optim_symbols_cache_.setRef(cache);
    }
}
TOP

Related Classes of abstrasy.libraries.io.External_Server

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.