/* | |
* 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.proxy.wrapper; | |
import java.lang.reflect.Constructor; | |
import com.alibaba.dubbo.common.Constants; | |
import com.alibaba.dubbo.common.URL; | |
import com.alibaba.dubbo.common.Version; | |
import com.alibaba.dubbo.common.bytecode.Wrapper; | |
import com.alibaba.dubbo.common.logger.Logger; | |
import com.alibaba.dubbo.common.logger.LoggerFactory; | |
import com.alibaba.dubbo.common.utils.ConfigUtils; | |
import com.alibaba.dubbo.common.utils.NetUtils; | |
import com.alibaba.dubbo.common.utils.ReflectUtils; | |
import com.alibaba.dubbo.common.utils.StringUtils; | |
import com.alibaba.dubbo.rpc.Exporter; | |
import com.alibaba.dubbo.rpc.Invoker; | |
import com.alibaba.dubbo.rpc.Protocol; | |
import com.alibaba.dubbo.rpc.ProxyFactory; | |
import com.alibaba.dubbo.rpc.RpcConstants; | |
import com.alibaba.dubbo.rpc.RpcException; | |
import com.alibaba.dubbo.rpc.service.GenericService; | |
/** | |
* StubProxyFactoryWrapper | |
* | |
* @author william.liangf | |
*/ | |
public class StubProxyFactoryWrapper implements ProxyFactory { | |
private static final Logger LOGGER = LoggerFactory.getLogger(StubProxyFactoryWrapper.class); | |
private final ProxyFactory proxyFactory; | |
private Protocol protocol; | |
public StubProxyFactoryWrapper(ProxyFactory proxyFactory) { | |
this.proxyFactory = proxyFactory; | |
} | |
public void setProtocol(Protocol protocol) { | |
this.protocol = protocol; | |
} | |
@SuppressWarnings({ "unchecked", "rawtypes" }) | |
public <T> T getProxy(Invoker<T> invoker) throws RpcException { | |
T proxy = proxyFactory.getProxy(invoker); | |
if (GenericService.class != invoker.getInterface()) { | |
String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY)); | |
if (ConfigUtils.isNotEmpty(stub)) { | |
Class<?> serviceType = invoker.getInterface(); | |
if (ConfigUtils.isDefault(stub)) { | |
if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) { | |
stub = serviceType.getName() + "Stub"; | |
} else { | |
stub = serviceType.getName() + "Local"; | |
} | |
} | |
try { | |
Class<?> stubClass = ReflectUtils.forName(stub); | |
if (! serviceType.isAssignableFrom(stubClass)) { | |
throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + serviceType.getName()); | |
} | |
try { | |
Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType); | |
proxy = (T) constructor.newInstance(new Object[] {proxy}); | |
//export stub service | |
URL url = invoker.getUrl(); | |
if (url.getParameter(RpcConstants.STUB_EVENT_KEY, RpcConstants.DEFAULT_STUB_EVENT)){ | |
url = url.addParameter(RpcConstants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ",")); | |
url = url.addParameter(RpcConstants.IS_SERVER_KEY, Boolean.FALSE.toString()); | |
try{ | |
export(proxy, (Class)invoker.getInterface(), url); | |
}catch (Exception e) { | |
LOGGER.error("export a stub service error.", e); | |
} | |
} | |
} catch (NoSuchMethodException e) { | |
throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implemention class " + stubClass.getName(), e); | |
} | |
} catch (Throwable t) { | |
LOGGER.error("Failed to create stub implemention class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t); | |
// ignore | |
} | |
} | |
} | |
return proxy; | |
} | |
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException { | |
return proxyFactory.getInvoker(proxy, type, url); | |
} | |
private <T> Exporter<T> export(T instance, Class<T> type, URL url) { | |
return protocol.export(proxyFactory.getInvoker(instance, type, url)); | |
} | |
} |