Package org.apache.harmony.rmi.transport.tcp

Source Code of org.apache.harmony.rmi.transport.tcp.TcpConnection$Lock

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @author  Mikhail A. Markov
*/
package org.apache.harmony.rmi.transport.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.rmi.ConnectIOException;
import java.rmi.RemoteException;
import java.security.AccessController;

import org.apache.harmony.rmi.client.ClientConnection;
import org.apache.harmony.rmi.client.ClientConnectionManager;
import org.apache.harmony.rmi.common.GetLongPropAction;
import org.apache.harmony.rmi.common.RMILog;
import org.apache.harmony.rmi.common.RMIProperties;
import org.apache.harmony.rmi.internal.nls.Messages;
import org.apache.harmony.rmi.transport.Endpoint;


/**
* Direct socket connection.
*
* @author  Mikhail A. Markov
*/
public class TcpConnection extends ClientConnection {

    // status of availability for remote calls
    private boolean available;

    // lock object for synchronization
    private class Lock {}
    private Object lock = new Lock();

    // when this connection could be closed (if it's available)
    private long expiration;

    /** Log for logging tcp connections activity. */
    protected static final RMILog tcpTransportLog = RMILog.getTcpTransportLog();

    /*
     * The time which will be used as a socket read timeout when reading
     * protocol acknowledgement data while establishing a new connection.
     * The default value is 60000 ms (1 minute).
     */
    private static int handshakeTimeout = ((Long) AccessController.doPrivileged(
            new GetLongPropAction(RMIProperties.HANDSHAKETIMEOUT_PROP,
                    60000))).intValue();

    /**
     * @see ClientConnection(Socket, Endpoint)
     */
    public TcpConnection(Socket s, Endpoint ep)throws RemoteException {
        super(s, ep);
        available = false;
    }

    /**
     * Acknowledge protocol with server side.
     *
     * @return acknowledged protocol number
     *
     * @throws RemoteException if any I/O exception occurred during protocol
     *         acknowledgement
     */
    protected int serverProtocolAck() throws RemoteException {
        try {
            DataOutputStream dout = new DataOutputStream(out);

            // write RMI header and protocol version
            writeHeader(dout);

            // write protocol type
            dout.writeByte(STREAM_PROTOCOL);
            out.flush();

            if (tcpTransportLog.isLoggable(RMILog.VERBOSE)) {
                // rmi.90=Using stream RMI protocol
                tcpTransportLog.log(RMILog.VERBOSE,Messages.getString("rmi.90")); //$NON-NLS-1$
            }

            // set handshakeTimeout
            int origTimeout = 0;

            try {
                origTimeout = s.getSoTimeout();
                s.setSoTimeout(handshakeTimeout);
            } catch (Exception ex) {
            }

            // read protocol acknowledgement
            DataInputStream din = new DataInputStream(in);
            int ack = din.readByte();

            if (ack != PROTOCOL_ACK) {
                // rmi.log.137=Protocol version {0} is not supported.
                // rmi.log.13C=Unknown protocol response: {0}
                throw new ConnectIOException((ack == PROTOCOL_NOT_SUPPORTED)
                        ? (Messages.getString("rmi.log.137", STREAM_PROTOCOL)) //$NON-NLS-1$
                        : (Messages.getString("rmi.log.13C",ack))); //$NON-NLS-1$
            }

            // read host and port
            String host = din.readUTF();
            int port = din.readInt();

            if (tcpTransportLog.isLoggable(RMILog.VERBOSE)) {
                // rmi.log.138=Server is seeing us as {0}:{1}
                tcpTransportLog.log(RMILog.VERBOSE,
                        Messages.getString("rmi.log.138", host, port)); //$NON-NLS-1$
            }

            // restore original value of soTimeout
            try {
                s.setSoTimeout(origTimeout);
            } catch (Exception ex) {
            }

            // send our host and port (for Stream protocol they'll be ignored)
            dout.writeUTF(host);
            dout.writeInt(port);
            dout.flush();
        } catch (RemoteException re) {
            close();
            throw re;
        } catch (IOException ioe) {
            close();
            // rmi.92=Unable to acknowledge protocol with server
            throw new ConnectIOException(
                    Messages.getString("rmi.92"), ioe); //$NON-NLS-1$
        }

        // protocol is agreed
        return STREAM_PROTOCOL;
    }

    /**
     * @see ClientConnection.done()
     */
    public void done() {
        synchronized (lock) {
            available = true;
            expiration = System.currentTimeMillis()
                    + ClientConnectionManager.connTimeout;
        }
    }

    /**
     * @see ClientConnection.reuse()
     */
    public synchronized boolean reuse() {
        synchronized (lock) {
            if (!available) {
                return false;
            }
        }
        int ackResp = 0;

        try {
            out.write(PING_MSG);
            out.flush();
            ackResp = in.read();
        } catch (IOException ioe) {
            if (tcpTransportLog.isLoggable(RMILog.BRIEF)) {
                // rmi.log.139=Ping request for {0} failed.
                tcpTransportLog.log(RMILog.BRIEF,
                        Messages.getString("rmi.log.139", toString())); //$NON-NLS-1$
            }
            close(false);
            return false;
        }

        if (ackResp != PING_ACK) {
            if (tcpTransportLog.isLoggable(RMILog.BRIEF)) {
                // rmi.log.13A=Unknown response to ping request for {0}:{1}
                tcpTransportLog.log(RMILog.BRIEF,
                        Messages.getString("rmi.log.13A", toString(), //$NON-NLS-1$
                        ackResp));
            }
            close(false);
            return false;
        }

        synchronized (lock) {
            available = false;
        }

        if (tcpTransportLog.isLoggable(RMILog.BRIEF)) {
            // rmi.log.13B=Reusing {0}...
            tcpTransportLog.log(RMILog.BRIEF,
                    Messages.getString("rmi.log.13B", toString())); //$NON-NLS-1$
        }
        return true;
    }

    /**
     * @see ClientConnection.isAvailable()
     */
    public boolean isAvailable() {
        synchronized (lock) {
            return available;
        }
    }

    /**
     * Returns true because this connection could be reused.
     *
     * @see ClientConnection.isReusable()
     */
    public boolean isReusable() {
        return true;
    }

    /**
     * @see ClientConnection.getExpiration()
     */
    public long getExpiration() {
        synchronized (lock) {
            if (!available) {
                return -1;
            }
            return expiration;
        }
    }
}
TOP

Related Classes of org.apache.harmony.rmi.transport.tcp.TcpConnection$Lock

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.