/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.rmi.ConnectException;
import java.rmi.ConnectIOException;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.StubNotFoundException;
import java.rmi.UnknownHostException;
import java.rmi.registry.Registry;

import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.NO_RESPONSE;
import org.omg.CORBA.SystemException;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.protocol.AbstractInvoker;

/**
 * RmiInvoker.
 * 
 * @author qian.lei
 */
public class RmiInvoker<T> extends AbstractInvoker<T> {
    
    private Registry registry;
    
    private RmiProxyFactory rmiProxyFactory;

    private Invoker<T> invoker;
    
    private boolean reconnect;

    public RmiInvoker(Registry registry, RmiProxyFactory rmiProxyFactory, Invoker<T> invoker) {
        super(invoker.getInterface(), invoker.getUrl());
        this.registry = registry;
        this.rmiProxyFactory = rmiProxyFactory;
        this.invoker = invoker;
        this.reconnect = invoker.getUrl().getParameter(Constants.RECONNECT_KEY, true);
    }

    @Override
    protected Result doInvoke(Invocation invocation) throws RpcException {
        Result result = null;
        try {
            result = invoker.invoke(invocation);
            
            // 对Rmi的Connection问题进行重试
            Throwable e = result.getException();
            if (e != null && isConnectFailure(e) && reconnect) {
                invoker = rmiProxyFactory.getInvoker(registry.lookup(invoker.getUrl().getPath()), invoker.getInterface(), invoker.getUrl());
                result = invoker.invoke(invocation);
            }
        } catch (RpcException e) {
            throw setRpcExceptionCode(e.getCause(), e);
        } catch (Throwable e) {
            throw setRpcExceptionCode(e, new RpcException(e.getMessage(), e));
        }

        Throwable e = result.getException();
        if (e != null && e instanceof RemoteException) {
            throw setRpcExceptionCode(e, new RpcException("Failed to invoke remote service: " + getInterface() + ", method: "
                    + invocation.getMethodName() + ", url: " + invoker.getUrl() + ", cause: " + e.getMessage(), e));
        }
        return result;
    }
    
    public static RpcException setRpcExceptionCode(Throwable e, RpcException re) {
        if (e != null && e.getCause() != null) {
            Class<?> cls = e.getCause().getClass();
            // 是根据测试Case发现的问题，对RpcException.setCode进行设置
            if (SocketTimeoutException.class.equals(cls)) {
                re.setCode(RpcException.TIMEOUT_EXCEPTION);
            } else if (IOException.class.isAssignableFrom(cls)) {
                re.setCode(RpcException.NETWORK_EXCEPTION);
            } else if (ClassNotFoundException.class.isAssignableFrom(cls)) {
                re.setCode(RpcException.SERIALIZATION_EXCEPTION);
            }
        }
        return re;
    }

    private static final String ORACLE_CONNECTION_EXCEPTION = "com.evermind.server.rmi.RMIConnectionException";

    private static boolean isConnectFailure(Throwable ex) {
        return (ex instanceof ConnectException || ex instanceof ConnectIOException ||
                ex instanceof UnknownHostException || ex instanceof NoSuchObjectException ||
                ex instanceof StubNotFoundException || isCorbaConnectFailure(ex.getCause()) ||
                ORACLE_CONNECTION_EXCEPTION.equals(ex.getClass().getName()));
    }

    private static boolean isCorbaConnectFailure(Throwable ex) {
        return ((ex instanceof COMM_FAILURE || ex instanceof NO_RESPONSE) &&
                ((SystemException) ex).completed == CompletionStatus.COMPLETED_NO);
    }
    
}