blob: 168bb10d2ea850d17414e87e4a9db30f2ec09f8c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* AbstractDefaultConfig
*
* @export
*/
public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
private static final long serialVersionUID = -1559314110797223229L;
// local impl class name for the service interface
protected String local;
// local stub class name for the service interface
protected String stub;
// service monitor
protected MonitorConfig monitor;
// proxy type
protected String proxy;
// cluster type
protected String cluster;
// filter
protected String filter;
// listener
protected String listener;
// owner
protected String owner;
// connection limits, 0 means shared connection, otherwise it defines the connections delegated to the
// current service
protected Integer connections;
// layer
protected String layer;
// application info
protected ApplicationConfig application;
// module info
protected ModuleConfig module;
// registry centers
protected List<RegistryConfig> registries;
// connection events
protected String onconnect;
// disconnection events
protected String ondisconnect;
// callback limits
private Integer callbacks;
// the scope for referring/exporting a service, if it's local, it means searching in current JVM only.
private String scope;
protected void checkRegistry() {
// for backward compatibility
if (registries == null || registries.isEmpty()) {
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.isEmpty())) {
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() {
// for backward compatibility
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.isEmpty()) {
for (RegistryConfig config : registries) {
String address = config.getAddress();
if (address == null || address.length() == 0) {
address = Constants.ANYHOST_VALUE;
}
String sysaddress = System.getProperty("dubbo.registry.address");
if (sysaddress != null && sysaddress.length() > 0) {
address = sysaddress;
}
if (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.getProtocolVersion());
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)) {
return null;
}
monitor = new MonitorConfig();
if (monitorAddress != null && monitorAddress.length() > 0) {
monitor.setAddress(monitorAddress);
}
if (monitorProtocol != null && monitorProtocol.length() > 0) {
monitor.setProtocol(monitorProtocol);
}
}
appendProperties(monitor);
Map<String, String> map = new HashMap<String, String>();
map.put(Constants.INTERFACE_KEY, MonitorService.class.getName());
map.put("dubbo", Version.getProtocolVersion());
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) {
// interface cannot be null
if (interfaceClass == null) {
throw new IllegalStateException("interface not allow null!");
}
// to verify interfaceClass is an interface
if (!interfaceClass.isInterface()) {
throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
}
// check if methods exist in the interface
if (methods != null && !methods.isEmpty()) {
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 implementation 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 implementation 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 implementation 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 implementation 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 implementation 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 implementation class " + mockClass.getName());
}
}
}
}
/**
* @return local
* @deprecated Replace to <code>getStub()</code>
*/
@Deprecated
public String getLocal() {
return local;
}
/**
* @param local
* @deprecated Replace to <code>setStub(Boolean)</code>
*/
@Deprecated
public void setLocal(Boolean local) {
if (local == null) {
setLocal((String) null);
} else {
setLocal(String.valueOf(local));
}
}
/**
* @param local
* @deprecated Replace to <code>setStub(String)</code>
*/
@Deprecated
public void setLocal(String local) {
checkName("local", local);
this.local = local;
}
public String getStub() {
return stub;
}
public void setStub(Boolean stub) {
if (stub == null) {
setStub((String) null);
} else {
setStub(String.valueOf(stub));
}
}
public void setStub(String stub) {
checkName("stub", stub);
this.stub = 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() {
return listener;
}
public void setListener(String listener) {
checkMultiExtension(InvokerListener.class, "listener", 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.isEmpty() ? 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(String monitor) {
this.monitor = new MonitorConfig(monitor);
}
public void setMonitor(MonitorConfig monitor) {
this.monitor = monitor;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
checkMultiName("owner", owner);
this.owner = owner;
}
public Integer getCallbacks() {
return callbacks;
}
public void setCallbacks(Integer callbacks) {
this.callbacks = 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;
}
}