Package org.apache.harmony.rmi.server

Source Code of org.apache.harmony.rmi.server.ServerConnection

/*
* 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
* @version $Revision: 1.1.2.3 $
*/
package org.apache.harmony.rmi.server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.rmi.UnmarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.UID;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import org.apache.harmony.rmi.common.RMILog;
import org.apache.harmony.rmi.common.RMIUtil;
import org.apache.harmony.rmi.internal.nls.Messages;
import org.apache.harmony.rmi.remoteref.UnicastServerRef;
import org.apache.harmony.rmi.transport.Endpoint;
import org.apache.harmony.rmi.transport.RMIObjectInputStream;
import org.apache.harmony.rmi.transport.RMIObjectOutputStream;
import org.apache.harmony.rmi.transport.RMIProtocolConstants;


/**
* Connection opened on server side when connection from the client is accepted.
* It acknowledges RMI protocol version, RMI protocol type etc. and after that
* pass the control to the appropriate UnicastServerRef for processing the
* remote call itself.
*
* @author  Mikhail A. Markov
* @version $Revision: 1.1.2.3 $
*/
public abstract class ServerConnection
        implements RMIProtocolConstants, Runnable {

    /** Connected socket. */
    protected Socket s;

    /** InputStream open from the socket. */
    protected InputStream in;

    /** OutputStream open from the socket. */
    protected OutputStream out;

    /** Endpoint which this connection connected to. */
    protected Endpoint ep;

    /** ServerConnectionManager managing this connection. */
    protected ServerConnectionManager mgr;

    /** Server reference where current remote call is dispatching. */
    protected UnicastServerRef sref = null;

    /**
     * Constructs ServerConnection working through socket specified.
     *
     * @param s Socket connected to the client
     * @param mgr ServerConnectionManager managing this connection
     *
     * @throws IOException if an I/O error occurred during getting
     *         input/output streams from specified socket
     */
    public ServerConnection(Socket s, ServerConnectionManager mgr)
            throws IOException {
        this.s = s;
        this.mgr = mgr;
        ep = new Endpoint(s.getInetAddress().getHostAddress(),
                          s.getPort(),
                          mgr.getEndpoint().getClientSocketFactory(),
                          mgr.getEndpoint().getServerSocketFactory());
        out = new BufferedOutputStream(s.getOutputStream());
        in = new BufferedInputStream(s.getInputStream());
    }

    /**
     * Acknowledges RMI protocol version, RMI protocol type etc. and wait for
     * remote calls from client. After call message dispatch call to appropriate
     * UnicastServerRef for processing.
     */
    public void run() {
        // sets client host for RemoteServer.getClientHost() method
        ServerConnectionManager.clientHost.set(
                s.getInetAddress().getHostAddress());

        try {
            // acknowledge protocol
            if (clientProtocolAck() < 0) {
                return;
            }

            // wait until RMI call msg is received from client or until client
            // closes the connection
            while (waitCallMsg() != -1) {
                RMIObjectInputStream oin = new RMIObjectInputStream(in);
                final ServerRemoteCall sCall = new ServerRemoteCall(this, oin);
                ObjID id = null;

                try {
                    id = ObjID.read(oin);
                } catch (IOException ioe) {
                    // rmi.74=Unable to read Object ID
                    throw new UnmarshalException(Messages.getString("rmi.74"), //$NON-NLS-1$
                            ioe);
                }
                RMIObjectInfo info = ExportManager.getInfo(id);
                RemoteException exToReturn = null;

                if (info == null) {
                    sref = null;
                    // rmi.75=No objects with {0} exported.
                    exToReturn = new NoSuchObjectException(
                            Messages.getString("rmi.75",id)); //$NON-NLS-1$
                } else {
                    sref = info.sref;

                    if (!sref.isSystem()) {
                        mgr.addActiveCall();
                    }

                    if (ServerConnectionManager.transportLog.isLoggable(
                            RMILog.VERBOSE)) {
                        // rmi.76=Dispatch call for processing
                        ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
                                Messages.getString("rmi.76")); //$NON-NLS-1$
                    }

                    // Dispatch the call for processing
                    Thread curThread = Thread.currentThread();
                    ClassLoader curLoader = curThread.getContextClassLoader();
                    curThread.setContextClassLoader(info.loader);
                    final SecurityManager curMgr = System.getSecurityManager();

                    try {
                        AccessController.doPrivileged(
                                new PrivilegedExceptionAction() {
                                    public Object run() throws IOException {
                                        /*
                                         * First check if we can accept
                                         * the calls from the given endpoint.
                                         */
                                        if (curMgr != null) {
                                            curMgr.checkAccept(ep.getHost(),
                                                    ep.getPort());
                                        }
                                        sref.processCall(sCall);
                                        return null;
                                    }
                                }, info.acc);
                    } catch (PrivilegedActionException pae) {
                        IOException ioe = (IOException) pae.getException();

                        if (ioe instanceof RemoteException) {
                            // rmi.77=RemoteException occurred in server thread
                            exToReturn = new ServerException(Messages
                                    .getString("rmi.77"), //$NON-NLS-1$
                                    ioe);
                        } else {
                            throw ioe;
                        }
                    } finally {
                        curThread.setContextClassLoader(curLoader);
                    }
                }

                if (exToReturn != null) {
                    sCall.releaseInputStream();
                    if (ServerConnectionManager.transportLog.isLoggable(
                            RMILog.VERBOSE)) {
                        // rmi.log.10B=Return exception to the client: {0}
                        ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
                                Messages.getString("rmi.log.10B", exToReturn));//$NON-NLS-1$
                    }
                    DataOutputStream dout = new DataOutputStream(out);
                    RMIObjectOutputStream oout;

                    if (sCall.hasResultStream()) {
                        oout = (RMIObjectOutputStream)
                                sCall.getOutputStream();
                    } else {
                        oout = (RMIObjectOutputStream)
                                sCall.getResultStream(false);
                    }
                    oout.writeObject(exToReturn);
                    oout.flush();
                }

                if (sref != null) {
                    if (!sref.isSystem()) {
                        mgr.removeActiveCall();
                    }
                    sref = null;
                }
                releaseOutputStream();
            }
        } catch (IOException ioe) {
            //ioe.printStackTrace(System.err);
        } finally {
            if (sref != null) {
                if (!sref.isSystem()) {
                    mgr.removeActiveCall();
                }
                sref = null;
            }

            // stop this thread, close the socket and remove this connection
            // from the list of active connections in ConnectionManager
            mgr.stopConnection(this);
        }
    }

    /**
     * Acknowledges protocol with client side.
     *
     * @return acknowledged protocol number
     *
     * @throws RemoteException if any I/O exception occurred during protocol
     *         acknowledgement
     */
    protected abstract int clientProtocolAck() throws IOException;

    /**
     * Waiting until 0x50 code (CALL_MSG) message will be received (this code
     * will be returned as a result of this method call). If the
     * connection with the client is closed while waiting for this code, -1
     * should be returned.
     *
     * @return 0x50 code if this code is received from the client or -1 if
     *         the socket was closed while waiting for CALL_MSG code
     *
     * @throws IOException if any I/O error occurred while communicating with
     *         client
     */
    protected abstract int waitCallMsg() throws IOException;

    /**
     * This method should be called when DGC_ACK response was received.
     * It unregisters the given UID in ClientDGC.
     *
     * @param uid UID DGC_ACK response for which was read
     */
    protected void dgcUnregisterUID(UID uid) {
        ClientDGC.unregisterForDGCAck(uid);
    }

    /**
     * Closes this connection.
     */
    public void close() {
        try {
            s.close();
        } catch (IOException e) {
            if (ServerConnectionManager.transportLog.isLoggable(
                    RMILog.VERBOSE)) {
                // rmi.log.10C=Note: close operation produced exception:
                ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
                        Messages.getString("rmi.log.10C"), e); //$NON-NLS-1$
            }
        }
    }

    /**
     * Returns true if this connection is handling remote call and false
     * otherwise.
     *
     * @return true if this connection is handling remote call and false
     *         otherwise
     */
    public boolean hasActiveCall() {
        return sref != null;
    }

    /**
     * By default does nothing.
     */
    public void releaseInputStream() throws IOException {
    }

    /**
     * By default does nothing.
     */
    public void releaseOutputStream() throws IOException {
    }

    /**
     * Returns open input stream.
     *
     * @return open input stream
     */
    public InputStream getInputStream() {
        return in;
    }

    /**
     * Returns open output stream.
     *
     * @return open output stream
     */
    public OutputStream getOutputStream() {
        return out;
    }

    /**
     * Returns string representation of this connection.
     *
     * @return string representation of this connection
     */
    public String toString() {
        return RMIUtil.getShortName(getClass()) + ": remote endpoint:" + ep; //$NON-NLS-1$
    }
}
TOP

Related Classes of org.apache.harmony.rmi.server.ServerConnection

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.