All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openejb.client.Client Maven / Gradle / Ivy

The newest version!
/**
 * 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.
 */
package org.apache.openejb.client;

import static org.apache.openejb.client.Exceptions.newIOException;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.URI;

public class Client {
    private static final Logger logger = Logger.getLogger("OpenEJB.client");

    public static final ThreadLocal> failed = new ThreadLocal>();

    private static final ProtocolMetaData PROTOCOL_VERSION = new ProtocolMetaData("3.1");

    private static Client client = new Client();
    private boolean retry = false;

    public Client() {
        String retryValue = System.getProperty("openejb.client.requestretry", retry + "");
        retry = new Boolean(retryValue);
    }

    // This lame hook point if only of testing
    public static void setClient(Client client) {
        Client.client = client;
    }

    public static Response request(Request req, Response res, ServerMetaData server) throws RemoteException {
        try {
            return client.processRequest(req, res, server);
        } finally {
            failed.remove();
        }
    }

    protected Response processRequest(Request req, Response res, ServerMetaData server) throws RemoteException {
//        System.out.println("req = " + req);
        if (server == null)
            throw new IllegalArgumentException("Server instance cannot be null");

        ClusterMetaData cluster = getClusterMetaData(server);

        /*----------------------------*/
        /* Get a connection to server */
        /*----------------------------*/

        Connection conn = null;
        try {
            conn = ConnectionManager.getConnection(cluster, server, req);
        } catch (IOException e) {
            throw new RemoteException("Unable to connect",e);
        }

        try {


            /*----------------------------------*/
            /* Get output streams */
            /*----------------------------------*/
            OutputStream out;
            try {

                out = conn.getOuputStream();

            } catch (IOException e) {
                throw newIOException("Cannot open output stream to server: ", e);
            }

            /*----------------------------------*/
            /* Write the protocol magic         */
            /*----------------------------------*/
            try {

                PROTOCOL_VERSION.writeExternal(out);

            } catch (IOException e) {
                throw newIOException("Cannot write the protocol metadata to the server: ", e);
            }

            /*----------------------------------*/
            /* Get output streams */
            /*----------------------------------*/
            ObjectOutput objectOut;
            try {

                objectOut = new ObjectOutputStream(out);

            } catch (IOException e) {
                throw newIOException("Cannot open object output stream to server: ", e);
            }

            /*----------------------------------*/
            /* Write ServerMetaData */
            /*----------------------------------*/
            try {

                server.writeExternal(objectOut);

            } catch (IOException e) {
                throw newIOException("Cannot write the ServerMetaData to the server: ", e);
            }

            /*----------------------------------*/
            /* Write ClusterMetaData */
            /*----------------------------------*/
            try {

                ClusterRequest clusterRequest = new ClusterRequest(cluster);
                objectOut.write(clusterRequest.getRequestType());
                clusterRequest.writeExternal(objectOut);

            } catch (Throwable e) {
                throw newIOException("Cannot write the ClusterMetaData to the server: ", e);
            }

            /*----------------------------------*/
            /* Write request type */
            /*----------------------------------*/
            try {

                objectOut.write(req.getRequestType());

            } catch (IOException e) {
                throw newIOException("Cannot write the request type to the server: ", e);
            }

            /*----------------------------------*/
            /* Write request */
            /*----------------------------------*/
            try {

                req.writeExternal(objectOut);
                objectOut.flush();
                out.flush();

            } catch (java.io.NotSerializableException e) {

                throw new IllegalArgumentException("Object is not serializable: " + e.getMessage());

            } catch (IOException e) {

                throw newIOException("Cannot write the request to the server: ", e);
            }

            /*----------------------------------*/
            /* Get input streams               */
            /*----------------------------------*/
            InputStream in;
            try {

                in = conn.getInputStream();


            } catch (IOException e) {
                throw newIOException("Cannot open input stream to server: ", e);
            }

            ProtocolMetaData protocolMetaData = null;
            try {

                protocolMetaData = new ProtocolMetaData();
                protocolMetaData.readExternal(in);

            } catch (EOFException e) {

                throw newIOException("Prematurely reached the end of the stream.  " + protocolMetaData.getSpec(), e);

            } catch (IOException e) {

                throw newIOException("Cannot deternmine server protocol version: Received " + protocolMetaData.getSpec(), e);
            }

            ObjectInput objectIn;
            try {

                objectIn = new EjbObjectInputStream(in);

            } catch (IOException e) {
                throw newIOException("Cannot open object input stream to server (" + protocolMetaData.getSpec() + ") : " + e.getMessage(), e);
            }

            /*----------------------------------*/
            /* Read response */
            /*----------------------------------*/
            try {
                ClusterResponse clusterResponse = new ClusterResponse();
                clusterResponse.readExternal(objectIn);
                switch (clusterResponse.getResponseCode()) {
                    case UPDATE: {
                        setClusterMetaData(server, clusterResponse.getUpdatedMetaData());
                    }
                    break;
                    case FAILURE: {
                        throw clusterResponse.getFailure();
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new RemoteException("Cannot read the response from the server.  The class for an object being returned is not located in this system:", e);

            } catch (IOException e) {
                throw newIOException("Cannot read the response from the server (" + protocolMetaData.getSpec() + ") : " + e.getMessage(), e);

            } catch (Throwable e) {
                throw new RemoteException("Error reading response from server (" + protocolMetaData.getSpec() + ") : " + e.getMessage(), e);
            }

            /*----------------------------------*/
            /* Read response */
            /*----------------------------------*/
            try {

                res.readExternal(objectIn);
            } catch (ClassNotFoundException e) {
                throw new RemoteException("Cannot read the response from the server.  The class for an object being returned is not located in this system:", e);

            } catch (IOException e) {
                throw newIOException("Cannot read the response from the server (" + protocolMetaData.getSpec() + ") : " + e.getMessage(), e);

            } catch (Throwable e) {
                throw new RemoteException("Error reading response from server (" + protocolMetaData.getSpec() + ") : " + e.getMessage(), e);
            }

        } catch (RemoteException e) {
            throw e;
        } catch (IOException e){
            Set failed = getFailed();
            failed.add(conn.getURI());
            conn.discard();
            if (retry){
                try {
                    processRequest(req, res, server);
                } catch (RemoteFailoverException re) {
                    throw re;
                } catch (RemoteException re) {
                    throw new RemoteFailoverException("Cannot complete request.  Retry attempted on " + failed.size() + " servers", e);
                }
            }
        } catch (Throwable error) {
            throw new RemoteException("Error while communicating with server: ", error);

        } finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (Throwable t) {
                logger.log(Level.WARNING, "Error closing connection with server: " + t.getMessage(), t);
            }
        }
        return res;
    }

    public static Set getFailed() {
        Set set = failed.get();
        if (set == null){
            set = new HashSet();
            failed.set(set);
        }
        return set;
    }

    private static final Map clusters = new ConcurrentHashMap();

    private static void setClusterMetaData(ServerMetaData server, ClusterMetaData cluster) {
        clusters.put(server, cluster);
    }

    private static ClusterMetaData getClusterMetaData(ServerMetaData server) {
        ClusterMetaData cluster = clusters.get(server);
        if (cluster == null) {
            cluster = new ClusterMetaData(0, server.getLocation());
            clusters.put(server, cluster);
        }

        return cluster;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy