/*


 ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


 */

package com.sap.dbtech.rte.comm;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Properties;

import com.sap.dbtech.util.MessageKey;
import com.sap.dbtech.util.MessageTranslator;

/**
 * Low-level socket communication.
 * 
 * as specified by the SAP DB runtime environment.
 *  
 */
public class SocketComm extends BasicSocketComm {
    public final static JdbcCommFactory factory = new JdbcCommFactory() {
        public JdbcCommunication open(String host, String dbname,
                Properties properties) throws RTEException {
            SocketComm sc = new SocketComm(host, properties);
            sc.connectDB(dbname);
            return sc;

        }

        public JdbcCommunication xopen(String host, String db, String dbroot,
                String pgm, Properties properties) throws RTEException {
            SocketComm sc = new SocketComm(host, properties);
            sc.connectAdmin(db, dbroot, pgm);
            return sc;
        }

    };

    // instance variables

    /**
     * creates a new socket connection to <i>host </i>.
     * 
     * @exception RTEException
     */
    protected SocketComm(String hostPort, Properties properties)
            throws RTEException {
        super(hostPort, properties);
        this.openSocket();
    }

    /**
     * opens a socket connection.
     * 
     * This converts any java.net specific exceptions to RTEException.
     * 
     * @param host
     *            java.lang.String
     * @exception RTEException
     */
    protected void openSocket() throws RTEException {
        try {
            this.socket = new Socket(this.host, this.lookupPort());

            try {
                this.socket.setSoTimeout(this.socketTimeOut);
                this.socket.setTcpNoDelay(true);
                //this.socket.setReceiveBufferSize(36864);
                this.socket.setSendBufferSize(36864);
            } catch (SocketException socketEx) {
                // ignore, as it is harmless
            }
            this.instream = this.socket.getInputStream();
            this.outstream = this.socket.getOutputStream();
        } catch (UnknownHostException uhexc) {
            throw new RTEException(
                    MessageTranslator
                            .translate(
                                    MessageKey.ERROR_UNKNOWN_HOST,
                                    this.host,
                                    uhexc.getMessage(),
                                    new Integer(
                                            RteC.CommunicationErrorCodeMap_C[RteC.SQLSERVER_OR_DB_UNKNOWN_C])),
                    RteC.CommunicationErrorCodeMap_C[RteC.SQLSERVER_OR_DB_UNKNOWN_C]);
        } catch (IOException ioexc) {
            throw new RTEException(
                    MessageTranslator
                            .translate(
                                    MessageKey.ERROR_HOST_CONNECT,
                                    this.host,
                                    ioexc.getMessage(),
                                    new Integer(
                                            RteC.CommunicationErrorCodeMap_C[RteC.SQLSTART_REQUIRED_C])),
                    RteC.CommunicationErrorCodeMap_C[RteC.SQLSTART_REQUIRED_C]);

        }
        try {
            // !!! DO NOT LINGER !!!
            // Modern OS linger in the background, if necessary.
            // Lingering causes the whole Java application to linger for that
            // time, if the
            // x_server hasn't read all data. And in case he hasn't our last
            // command was
            // a COMMIT/ROLLBACK WORK RELEASE, so no harm is done to the
            // database. The
            // only thing could be some nasty entry in some x_server log ...
            this.socket.setSoLinger(true, 15);
        } catch (SocketException soExc) {
            // ignore
        }

    }

    protected BasicSocketComm getNewCommunication() throws RTEException {
        return new SocketComm(this.host + ":" + this.port, null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.sap.dbtech.rte.comm.BasicSocketComm#getDefaultPort()
     */
    protected int getDefaultPort() {
        return RteC.defaultPort_C;
    }
 
}
