/* * Copyright 1999-2012 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; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.rpc.Exporter; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.ProxyFactory; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcException; /** * AbstractProxyProtocol * * @author william.liangf */ public abstract class AbstractProxyProtocol extends AbstractProtocol { private final List<Class<?>> rpcExceptions = new CopyOnWriteArrayList<Class<?>>();; private ProxyFactory proxyFactory; public AbstractProxyProtocol() { } public AbstractProxyProtocol(Class<?>... exceptions) { for (Class<?> exception : exceptions) { addRpcException(exception); } } public void addRpcException(Class<?> exception) { this.rpcExceptions.add(exception); } public void setProxyFactory(ProxyFactory proxyFactory) { this.proxyFactory = proxyFactory; } public ProxyFactory getProxyFactory() { return proxyFactory; } @SuppressWarnings("unchecked") public <T> Exporter<T> export(final Invoker<T> invoker) throws RpcException { final String uri = serviceKey(invoker.getUrl()); Exporter<T> exporter = (Exporter<T>) exporterMap.get(uri); if (exporter != null) { return exporter; } final Runnable runnable = doExport(proxyFactory.getProxy(invoker), invoker.getInterface(), invoker.getUrl()); exporter = new AbstractExporter<T>(invoker) { public void unexport() { super.unexport(); exporterMap.remove(uri); if (runnable != null) { try { runnable.run(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } }; exporterMap.put(uri, exporter); return exporter; } public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException { final Invoker<T> tagert = proxyFactory.getInvoker(doRefer(type, url), type, url); Invoker<T> invoker = new AbstractInvoker<T>(type, url) { @Override protected Result doInvoke(Invocation invocation) throws Throwable { try { Result result = tagert.invoke(invocation); Throwable e = result.getException(); if (e != null) { for (Class<?> rpcException : rpcExceptions) { if (rpcException.isAssignableFrom(e.getClass())) { throw getRpcException(type, url, invocation, e); } } } return result; } catch (RpcException e) { if (e.getCode() == RpcException.UNKNOWN_EXCEPTION) { e.setCode(getErrorCode(e.getCause())); } throw e; } catch (Throwable e) { throw getRpcException(type, url, invocation, e); } } }; invokers.add(invoker); return invoker; } protected RpcException getRpcException(Class<?> type, URL url, Invocation invocation, Throwable e) { RpcException re = new RpcException("Failed to invoke remote service: " + type + ", method: " + invocation.getMethodName() + ", cause: " + e.getMessage(), e); re.setCode(getErrorCode(e)); return re; } protected int getErrorCode(Throwable e) { return RpcException.UNKNOWN_EXCEPTION; } protected abstract <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException; protected abstract <T> T doRefer(Class<T> type, URL url) throws RpcException; }