/* | |
* 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.config; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import com.alibaba.dubbo.common.Constants; | |
import com.alibaba.dubbo.common.URL; | |
import com.alibaba.dubbo.common.Version; | |
import com.alibaba.dubbo.common.extension.ExtensionLoader; | |
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.common.utils.UrlUtils; | |
import com.alibaba.dubbo.config.support.Parameter; | |
import com.alibaba.dubbo.monitor.MonitorFactory; | |
import com.alibaba.dubbo.monitor.MonitorService; | |
import com.alibaba.dubbo.registry.RegistryFactory; | |
import com.alibaba.dubbo.registry.RegistryService; | |
import com.alibaba.dubbo.rpc.Filter; | |
import com.alibaba.dubbo.rpc.InvokerListener; | |
import com.alibaba.dubbo.rpc.ProxyFactory; | |
import com.alibaba.dubbo.rpc.cluster.Cluster; | |
import com.alibaba.dubbo.rpc.support.MockInvoker; | |
/** | |
* AbstractDefaultConfig | |
* | |
* @author william.liangf | |
* @export | |
*/ | |
public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { | |
private static final long serialVersionUID = -1559314110797223229L; | |
// 服务接口的本地实现类名 | |
protected String local; | |
// 服务接口的本地实现类名 | |
protected String stub; | |
// 服务监控 | |
protected MonitorConfig monitor; | |
// 代理类型 | |
protected String proxy; | |
// 集群方式 | |
protected String cluster; | |
// 过滤器 | |
protected String filter; | |
// 监听器 | |
protected String listener; | |
// 负责人 | |
protected String owner; | |
// 连接数限制,0表示共享连接,否则为该服务独享连接数 | |
protected Integer connections; | |
// 连接数限制 | |
protected String layer; | |
// 应用信息 | |
protected ApplicationConfig application; | |
// 模块信息 | |
protected ModuleConfig module; | |
// 注册中心 | |
protected List<RegistryConfig> registries; | |
// callback实例个数限制 | |
private Integer callbacks; | |
// 连接事件 | |
protected String onconnect; | |
// 断开事件 | |
protected String ondisconnect; | |
// 服务暴露或引用的scope,如果为local,则表示只在当前JVM内查找. | |
private String scope; | |
protected void checkRegistry() { | |
// 兼容旧版本 | |
if (registries == null || registries.size() == 0) { | |
String address = ConfigUtils.getProperty("dubbo.registry.address"); | |
if (address != null && address.length() > 0) { | |
registries = new ArrayList<RegistryConfig>(); | |
String[] as = address.split("\\s*[|]+\\s*"); | |
for (String a : as) { | |
RegistryConfig registryConfig = new RegistryConfig(); | |
registryConfig.setAddress(a); | |
registries.add(registryConfig); | |
} | |
} | |
} | |
if ((registries == null || registries.size() == 0)) { | |
throw new IllegalStateException((getClass().getSimpleName().startsWith("Reference") | |
? "No such any registry to refer service in consumer " | |
: "No such any registry to export service in provider ") | |
+ NetUtils.getLocalHost() | |
+ " use dubbo version " | |
+ Version.getVersion() | |
+ ", Please add <dubbo:registry address=\"...\" /> to your spring config. If you want unregister, please set <dubbo:service registry=\"N/A\" />"); | |
} | |
for (RegistryConfig registryConfig : registries) { | |
appendProperties(registryConfig); | |
} | |
} | |
@SuppressWarnings("deprecation") | |
protected void checkApplication() { | |
// 兼容旧版本 | |
if (application == null) { | |
String applicationName = ConfigUtils.getProperty("dubbo.application.name"); | |
if (applicationName != null && applicationName.length() > 0) { | |
application = new ApplicationConfig(); | |
} | |
} | |
if (application == null) { | |
throw new IllegalStateException( | |
"No such application config! Please add <dubbo:application name=\"...\" /> to your spring config."); | |
} | |
appendProperties(application); | |
String wait = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY); | |
if (wait != null && wait.trim().length() > 0) { | |
System.setProperty(Constants.SHUTDOWN_WAIT_KEY, wait.trim()); | |
} else { | |
wait = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY); | |
if (wait != null && wait.trim().length() > 0) { | |
System.setProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY, wait.trim()); | |
} | |
} | |
} | |
protected List<URL> loadRegistries(boolean provider) { | |
checkRegistry(); | |
List<URL> registryList = new ArrayList<URL>(); | |
if (registries != null && registries.size() > 0) { | |
for (RegistryConfig config : registries) { | |
String address = config.getAddress(); | |
if (address == null || address.length() == 0) { | |
throw new IllegalStateException("registry address == null"); | |
} | |
String sysaddress = System.getProperty("dubbo.registry.address"); | |
if (sysaddress != null && sysaddress.length() > 0) { | |
address = sysaddress; | |
} | |
if (address != null && address.length() > 0 | |
&& ! RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) { | |
Map<String, String> map = new HashMap<String, String>(); | |
appendParameters(map, application); | |
appendParameters(map, config); | |
map.put("path", RegistryService.class.getName()); | |
map.put("dubbo", Version.getVersion()); | |
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); | |
if (ConfigUtils.getPid() > 0) { | |
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); | |
} | |
if (! map.containsKey("protocol")) { | |
if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) { | |
map.put("protocol", "remote"); | |
} else { | |
map.put("protocol", "dubbo"); | |
} | |
} | |
List<URL> urls = UrlUtils.parseURLs(address, map); | |
for (URL url : urls) { | |
url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol()); | |
url = url.setProtocol(Constants.REGISTRY_PROTOCOL); | |
if ((provider && url.getParameter(Constants.REGISTER_KEY, true)) | |
|| (! provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) { | |
registryList.add(url); | |
} | |
} | |
} | |
} | |
} | |
return registryList; | |
} | |
protected URL loadMonitor(URL registryURL) { | |
if (monitor == null) { | |
String monitorAddress = ConfigUtils.getProperty("dubbo.monitor.address"); | |
String monitorProtocol = ConfigUtils.getProperty("dubbo.monitor.protocol"); | |
if (monitorAddress != null && monitorAddress.length() > 0 | |
|| monitorProtocol != null && monitorProtocol.length() > 0) { | |
monitor = new MonitorConfig(); | |
} else { | |
return null; | |
} | |
} | |
appendProperties(monitor); | |
Map<String, String> map = new HashMap<String, String>(); | |
map.put(Constants.INTERFACE_KEY, MonitorService.class.getName()); | |
map.put("dubbo", Version.getVersion()); | |
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); | |
if (ConfigUtils.getPid() > 0) { | |
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); | |
} | |
appendParameters(map, monitor); | |
String address = monitor.getAddress(); | |
String sysaddress = System.getProperty("dubbo.monitor.address"); | |
if (sysaddress != null && sysaddress.length() > 0) { | |
address = sysaddress; | |
} | |
if (ConfigUtils.isNotEmpty(address)) { | |
if (! map.containsKey(Constants.PROTOCOL_KEY)) { | |
if (ExtensionLoader.getExtensionLoader(MonitorFactory.class).hasExtension("logstat")) { | |
map.put(Constants.PROTOCOL_KEY, "logstat"); | |
} else { | |
map.put(Constants.PROTOCOL_KEY, "dubbo"); | |
} | |
} | |
return UrlUtils.parseURL(address, map); | |
} else if (Constants.REGISTRY_PROTOCOL.equals(monitor.getProtocol()) && registryURL != null) { | |
return registryURL.setProtocol("dubbo").addParameter(Constants.PROTOCOL_KEY, "registry").addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)); | |
} | |
return null; | |
} | |
protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) { | |
// 接口不能为空 | |
if (interfaceClass == null) { | |
throw new IllegalStateException("interface not allow null!"); | |
} | |
// 检查接口类型必需为接口 | |
if(! interfaceClass.isInterface()) { | |
throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!"); | |
} | |
// 检查方法是否在接口中存在 | |
if (methods != null && methods.size() > 0) { | |
for (MethodConfig methodBean : methods) { | |
String methodName = methodBean.getName(); | |
if (methodName == null || methodName.length() == 0) { | |
throw new IllegalStateException("<dubbo:method> name attribute is required! Please check: <dubbo:service interface=\"" + interfaceClass.getName() + "\" ... ><dubbo:method name=\"\" ... /></<dubbo:reference>"); | |
} | |
boolean hasMethod = false; | |
for (java.lang.reflect.Method method : interfaceClass.getMethods()) { | |
if (method.getName().equals(methodName)) { | |
hasMethod = true; | |
break; | |
} | |
} | |
if (!hasMethod) { | |
throw new IllegalStateException("The interface " + interfaceClass.getName() | |
+ " not found method " + methodName); | |
} | |
} | |
} | |
} | |
protected void checkStubAndMock(Class<?> interfaceClass) { | |
if (ConfigUtils.isNotEmpty(local)) { | |
Class<?> localClass = ConfigUtils.isDefault(local) ? ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local); | |
if (! interfaceClass.isAssignableFrom(localClass)) { | |
throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceClass.getName()); | |
} | |
try { | |
ReflectUtils.findConstructor(localClass, interfaceClass); | |
} catch (NoSuchMethodException e) { | |
throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "(" + interfaceClass.getName() + ")\" in local implemention class " + localClass.getName()); | |
} | |
} | |
if (ConfigUtils.isNotEmpty(stub)) { | |
Class<?> localClass = ConfigUtils.isDefault(stub) ? ReflectUtils.forName(interfaceClass.getName() + "Stub") : ReflectUtils.forName(stub); | |
if (! interfaceClass.isAssignableFrom(localClass)) { | |
throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceClass.getName()); | |
} | |
try { | |
ReflectUtils.findConstructor(localClass, interfaceClass); | |
} catch (NoSuchMethodException e) { | |
throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "(" + interfaceClass.getName() + ")\" in local implemention class " + localClass.getName()); | |
} | |
} | |
if (ConfigUtils.isNotEmpty(mock)) { | |
if (mock.startsWith(Constants.RETURN_PREFIX)) { | |
String value = mock.substring(Constants.RETURN_PREFIX.length()); | |
try { | |
MockInvoker.parseMockValue(value); | |
} catch (Exception e) { | |
throw new IllegalStateException("Illegal mock json value in <dubbo:service ... mock=\"" + mock + "\" />"); | |
} | |
} else { | |
Class<?> mockClass = ConfigUtils.isDefault(mock) ? ReflectUtils.forName(interfaceClass.getName() + "Mock") : ReflectUtils.forName(mock); | |
if (! interfaceClass.isAssignableFrom(mockClass)) { | |
throw new IllegalStateException("The mock implemention class " + mockClass.getName() + " not implement interface " + interfaceClass.getName()); | |
} | |
try { | |
mockClass.getConstructor(new Class<?>[0]); | |
} catch (NoSuchMethodException e) { | |
throw new IllegalStateException("No such empty constructor \"public " + mockClass.getSimpleName() + "()\" in mock implemention class " + mockClass.getName()); | |
} | |
} | |
} | |
} | |
/** | |
* @deprecated Replace to <code>getStub()</code> | |
* @return local | |
*/ | |
@Deprecated | |
public String getLocal() { | |
return local; | |
} | |
/** | |
* @deprecated Replace to <code>setStub(String)</code> | |
* @param local | |
*/ | |
@Deprecated | |
public void setLocal(String local) { | |
checkName("local", local); | |
this.local = local; | |
} | |
/** | |
* @deprecated Replace to <code>setStub(Boolean)</code> | |
* @param local | |
*/ | |
@Deprecated | |
public void setLocal(Boolean local) { | |
if (local == null) { | |
setLocal((String) null); | |
} else { | |
setLocal(String.valueOf(local)); | |
} | |
} | |
public String getStub() { | |
return stub; | |
} | |
public void setStub(String stub) { | |
checkName("stub", stub); | |
this.stub = stub; | |
} | |
public void setStub(Boolean stub) { | |
if (local == null) { | |
setStub((String) null); | |
} else { | |
setStub(String.valueOf(stub)); | |
} | |
} | |
public String getCluster() { | |
return cluster; | |
} | |
public void setCluster(String cluster) { | |
checkExtension(Cluster.class, "cluster", cluster); | |
this.cluster = cluster; | |
} | |
public String getProxy() { | |
return proxy; | |
} | |
public void setProxy(String proxy) { | |
checkExtension(ProxyFactory.class, "proxy", proxy); | |
this.proxy = proxy; | |
} | |
public Integer getConnections() { | |
return connections; | |
} | |
public void setConnections(Integer connections) { | |
this.connections = connections; | |
} | |
@Parameter(key = Constants.REFERENCE_FILTER_KEY, append = true) | |
public String getFilter() { | |
return filter; | |
} | |
public void setFilter(String filter) { | |
checkMultiExtension(Filter.class, "filter", filter); | |
this.filter = filter; | |
} | |
@Parameter(key = Constants.INVOKER_LISTENER_KEY, append = true) | |
public String getListener() { | |
checkMultiExtension(InvokerListener.class, "listener", listener); | |
return listener; | |
} | |
public void setListener(String listener) { | |
this.listener = listener; | |
} | |
public String getLayer() { | |
return layer; | |
} | |
public void setLayer(String layer) { | |
checkNameHasSymbol("layer", layer); | |
this.layer = layer; | |
} | |
public ApplicationConfig getApplication() { | |
return application; | |
} | |
public void setApplication(ApplicationConfig application) { | |
this.application = application; | |
} | |
public ModuleConfig getModule() { | |
return module; | |
} | |
public void setModule(ModuleConfig module) { | |
this.module = module; | |
} | |
public RegistryConfig getRegistry() { | |
return registries == null || registries.size() == 0 ? null : registries.get(0); | |
} | |
public void setRegistry(RegistryConfig registry) { | |
List<RegistryConfig> registries = new ArrayList<RegistryConfig>(1); | |
registries.add(registry); | |
this.registries = registries; | |
} | |
public List<RegistryConfig> getRegistries() { | |
return registries; | |
} | |
@SuppressWarnings({ "unchecked" }) | |
public void setRegistries(List<? extends RegistryConfig> registries) { | |
this.registries = (List<RegistryConfig>)registries; | |
} | |
public MonitorConfig getMonitor() { | |
return monitor; | |
} | |
public void setMonitor(MonitorConfig monitor) { | |
this.monitor = monitor; | |
} | |
public void setMonitor(String monitor) { | |
this.monitor = new MonitorConfig(monitor); | |
} | |
public String getOwner() { | |
return owner; | |
} | |
public void setOwner(String owner) { | |
this.owner = owner; | |
} | |
public void setCallbacks(Integer callbacks) { | |
this.callbacks = callbacks; | |
} | |
public Integer getCallbacks() { | |
return callbacks; | |
} | |
public String getOnconnect() { | |
return onconnect; | |
} | |
public void setOnconnect(String onconnect) { | |
this.onconnect = onconnect; | |
} | |
public String getOndisconnect() { | |
return ondisconnect; | |
} | |
public void setOndisconnect(String ondisconnect) { | |
this.ondisconnect = ondisconnect; | |
} | |
public String getScope() { | |
return scope; | |
} | |
public void setScope(String scope) { | |
this.scope = scope; | |
} | |
} |