/* | |
* 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; | |
} | |
public <T> Exporter<T> export(final Invoker<T> invoker) throws RpcException { | |
final String uri = invoker.getUrl().getAbsolutePath(); | |
final Runnable runnable = doExport(proxyFactory.getProxy(invoker), invoker.getInterface(), invoker.getUrl()); | |
Exporter<T> 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; | |
} |