This is an automated email from the ASF dual-hosted git repository. liujun pushed a commit to branch 2.7.0-release in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git
commit 90030e77676a2a4db262094877bd7b01479f1097 Merge: e6b340d ec8a5b9 Author: ken.lj <[email protected]> AuthorDate: Sun Jan 6 19:45:21 2019 +0800 resolve conflicts .../src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java | 1 - .../src/main/java/org/apache/dubbo/config/ReferenceConfig.java | 1 + .../test/java/org/apache/dubbo/config/AbstractInterfaceConfigTest.java | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index d8194d3,87cf709..657f21b --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@@ -1,810 -1,737 +1,809 @@@ -/* - * 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 org.apache.dubbo.config; - -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.config.Environment; -import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.ReflectUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.utils.UrlUtils; -import org.apache.dubbo.config.support.Parameter; -import org.apache.dubbo.metadata.integration.MetadataReportService; -import org.apache.dubbo.monitor.MonitorFactory; -import org.apache.dubbo.monitor.MonitorService; -import org.apache.dubbo.registry.RegistryService; -import org.apache.dubbo.rpc.Filter; -import org.apache.dubbo.rpc.InvokerListener; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.cluster.Cluster; -import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.rpc.support.MockInvoker; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.apache.dubbo.common.Constants.APPLICATION_KEY; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; - -/** - * 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; - - /** - * Strategies for generating dynamic agents,there are two strategies can be choosed: jdk and javassist - */ - protected String proxy; - - /** - * Cluster type - */ - protected String cluster; - - /** - * The {@link Filter} when the provicer side exposed a service or the customer side references a remote service used, - * if there are more than one, you can use commas to separate them - */ - protected String filter; - - /** - * The Listener when the provider side exposes a service or the customer side references a remote service used - * if there are more than one, you can use commas to separate them - */ - protected String listener; - - /** - * The owner of zhe service providers - */ - protected String owner; - - /** - * Connection limits, 0 means shared connection, otherwise it defines the connections delegated to the current service - */ - protected Integer connections; - - /** - * The layer of service providers - */ - protected String layer; - - /** - * The application info - */ - protected ApplicationConfig application; - - /** - * The module info - */ - protected ModuleConfig module; - - /** - * Registry centers - */ - protected List<RegistryConfig> registries; - - protected String registryIds; - - // connection events - protected String onconnect; - - /** - * Disconnection events - */ - protected String ondisconnect; - protected MetadataReportConfig metadataReportConfig; - // 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; - - /** - * Check whether the registry config is exists, and then conversion it to {@link RegistryConfig} - */ - protected void checkRegistry() { - loadRegistriesFromBackwardConfig(); - - convertRegistryIdsToRegistries(); - - for (RegistryConfig registryConfig : registries) { - registryConfig.refresh(); - if (StringUtils.isNotEmpty(registryConfig.getId())) { - registryConfig.setPrefix(Constants.REGISTRIES_SUFFIX); - registryConfig.refresh(); - } - } - - for (RegistryConfig registryConfig : registries) { - if (!registryConfig.isValid()) { - throw new IllegalStateException("No registry config found or it's not a valid config! " + - "The registry config is: " + registryConfig); - } - } - - useRegistryForConfigIfNecessary(); - } - - @SuppressWarnings("deprecation") - protected void checkApplication() { - // for backward compatibility - if (application == null) { - application = new ApplicationConfig(); - } - - application.refresh(); - - if (!application.isValid()) { - throw new IllegalStateException("No application config found or it's not a valid config! " + - "Please add <dubbo:application name=\"...\" /> to your spring config."); - } - - ApplicationModel.setApplication(application.getName()); - - // backward compatibility - 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 void checkMonitor() { - if (monitor == null) { - monitor = new MonitorConfig(); - } - - monitor.refresh(); - - if (!monitor.isValid()) { - logger.info("There's no valid monitor config found, if you want to open monitor statistics for Dubbo, " + - "please make sure your monitor is configured properly."); - } - } - - protected void checkMetadataReport() { - if (metadataReportConfig == null) { - metadataReportConfig = new MetadataReportConfig(); - } - metadataReportConfig.refresh(); - if (!metadataReportConfig.isValid()) { - logger.warn("There's no valid metadata config found, if you are using the simplified mode of registry url, " + - "please make sure you have a metadata address configured properly."); - } - } - - - /** - * - * Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config - * - * @param provider whether it is the provider side - * @return - */ - protected List<URL> loadRegistries(boolean provider) { - // check && override if necessary - List<URL> registryList = new ArrayList<URL>(); - if (registries != null && !registries.isEmpty()) { - for (RegistryConfig config : registries) { - String address = config.getAddress(); - if (StringUtils.isEmpty(address)) { - address = Constants.ANYHOST_VALUE; - } - if (!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()); - appendRuntimeParameters(map); - if (!map.containsKey("protocol")) { - 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; - } - - /** - * - * Load the monitor config from the system properties and conversation it to {@link URL} - * - * @param registryURL - * @return - */ - protected URL loadMonitor(URL registryURL) { - checkMonitor(); - Map<String, String> map = new HashMap<String, String>(); - map.put(Constants.INTERFACE_KEY, MonitorService.class.getName()); - appendRuntimeParameters(map); - //set ip - String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY); - if (hostToRegistry == null || hostToRegistry.length() == 0) { - hostToRegistry = NetUtils.getLocalHost(); - } else if (NetUtils.isInvalidLocalHost(hostToRegistry)) { - throw new IllegalArgumentException("Specified invalid registry ip from property:" + - Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry); - } - map.put(Constants.REGISTER_IP_KEY, hostToRegistry); - appendParameters(map, monitor); - appendParameters(map, application); - 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 (getExtensionLoader(MonitorFactory.class).hasExtension("logstat")) { - map.put(Constants.PROTOCOL_KEY, "logstat"); - } else { - map.put(Constants.PROTOCOL_KEY, Constants.DOBBO_PROTOCOL); - } - } - return UrlUtils.parseURL(address, map); - } else if (Constants.REGISTRY_PROTOCOL.equals(monitor.getProtocol()) && registryURL != null) { - return registryURL.setProtocol(Constants.DOBBO_PROTOCOL).addParameter(Constants.PROTOCOL_KEY, Constants.REGISTRY_PROTOCOL).addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)); - } - return null; - } - - static void appendRuntimeParameters(Map<String, String> map) { - map.put(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()); - map.put(Constants.SPECIFICATION_VERSION_KEY, Version.getVersion()); - map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); - if (ConfigUtils.getPid() > 0) { - map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); - } - } - - private URL loadMetadataReporterURL(boolean provider) { - this.checkApplication(); - String address = metadataReportConfig.getAddress(); - if (address == null || address.length() == 0) { - return null; - } - Map<String, String> map = new HashMap<String, String>(); - map.put(APPLICATION_KEY, application.getName()); - appendParameters(map, metadataReportConfig); - return UrlUtils.parseURL(address, map); - } - - protected MetadataReportService getMetadataReportService() { - - if (metadataReportConfig == null || !metadataReportConfig.isValid()) { - return null; - } - return MetadataReportService.instance(() -> { - return loadMetadataReporterURL(true); - }); - } - - /** - * Check whether the remote service interface and the methods meet with Dubbo's requirements.it mainly check, if the - * methods configured in the configuration file are included in the interface of remote service - * - * @param interfaceClass the interface of remote service - * @param methods the methods configured - */ - protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) { - // interface cannot be null - Assert.notNull(interfaceClass, 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 remote service interface - if (methods != null && !methods.isEmpty()) { - for (MethodConfig methodBean : methods) { - methodBean.setService(interfaceClass.getName()); - methodBean.setServiceId(this.getId()); - methodBean.refresh(); - 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 = Arrays.stream(interfaceClass.getMethods()).anyMatch(method -> method.getName().equals(methodName)); - if (!hasMethod) { - throw new IllegalStateException("The interface " + interfaceClass.getName() - + " not found method " + methodName); - } - } - } - } - - /** - * Legitimacy check and setup of local simulated operations. The operations can be a string with Simple operation or - * a classname whose {@link Class} implements a particular function - * - * @param interfaceClass for provider side, it is the {@link Class} of the service that will be exported; for consumer - * side, it is the {@link Class} of the remote service interface that will be referenced - */ - void checkMock(Class<?> interfaceClass) { - if (ConfigUtils.isEmpty(mock)) { - return; - } - - String normalizedMock = MockInvoker.normalizeMock(mock); - if (normalizedMock.startsWith(Constants.RETURN_PREFIX)) { - normalizedMock = normalizedMock.substring(Constants.RETURN_PREFIX.length()).trim(); - try { - //Check whether the mock value is legal, if it is illegal, throw exception - MockInvoker.parseMockValue(normalizedMock); - } catch (Exception e) { - throw new IllegalStateException("Illegal mock return in <dubbo:service/reference ... " + - "mock=\"" + mock + "\" />"); - } - } else if (normalizedMock.startsWith(Constants.THROW_PREFIX)) { - normalizedMock = normalizedMock.substring(Constants.THROW_PREFIX.length()).trim(); - if (ConfigUtils.isNotEmpty(normalizedMock)) { - try { - //Check whether the mock value is legal - MockInvoker.getThrowable(normalizedMock); - } catch (Exception e) { - throw new IllegalStateException("Illegal mock throw in <dubbo:service/reference ... " + - "mock=\"" + mock + "\" />"); - } - } - } else { - //Check whether the mock class is a implementation of the interfaceClass, and if it has a default constructor - MockInvoker.getMockObject(normalizedMock, interfaceClass); - } - } - - /** - * Legitimacy check of stub, note that: the local will deprecated, and replace with <code>stub</code> - * - * @param interfaceClass for provider side, it is the {@link Class} of the service that will be exported; for consumer - * side, it is the {@link Class} of the remote service interface - */ - void checkStubAndLocal(Class<?> interfaceClass) { - if (ConfigUtils.isNotEmpty(local)) { - Class<?> localClass = ConfigUtils.isDefault(local) ? - ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local); - verify(interfaceClass, localClass); - } - if (ConfigUtils.isNotEmpty(stub)) { - Class<?> localClass = ConfigUtils.isDefault(stub) ? - ReflectUtils.forName(interfaceClass.getName() + "Stub") : ReflectUtils.forName(stub); - verify(interfaceClass, localClass); - } - } - - private void verify(Class<?> interfaceClass, Class<?> localClass) { - if (!interfaceClass.isAssignableFrom(localClass)) { - throw new IllegalStateException("The local implementation class " + localClass.getName() + - " not implement interface " + interfaceClass.getName()); - } - - try { - //Check if the localClass a contructor with parameter who's type is interfaceClass - ReflectUtils.findConstructor(localClass, interfaceClass); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + - "(" + interfaceClass.getName() + ")\" in local implementation class " + localClass.getName()); - } - } - - private void overrideParameters(Map<String, String> map) { - map.put(Constants.PATH_KEY, RegistryService.class.getName()); - map.put(Constants.DOBBO_PROTOCOL, Version.getProtocolVersion()); - map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); - if (ConfigUtils.getPid() > 0) { - map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); - } - map.putIfAbsent(Constants.PROTOCOL_KEY, Constants.DOBBO_PROTOCOL); - } - - private void convertRegistryIdsToRegistries() { - if (StringUtils.isEmpty(registryIds) && (registries == null || registries.isEmpty())) { - Set<String> configedRegistries = new HashSet<>(); - configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(), - Constants.REGISTRIES_SUFFIX)); - configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(), - Constants.REGISTRIES_SUFFIX)); - - registryIds = String.join(",", configedRegistries); - } - - if (StringUtils.isEmpty(registryIds)) { - if (registries == null || registries.isEmpty()) { - registries = new ArrayList<>(); - registries.add(new RegistryConfig()); - } - } else { - String[] arr = Constants.COMMA_SPLIT_PATTERN.split(registryIds); - if (registries == null || registries.isEmpty()) { - registries = new ArrayList<>(); - } - Arrays.stream(arr).forEach(id -> { - if (registries.stream().noneMatch(reg -> reg.getId().equals(id))) { - RegistryConfig registryConfig = new RegistryConfig(); - registryConfig.setId(id); - registries.add(registryConfig); - } - }); - if (registries.size() > arr.length) { - throw new IllegalStateException("Too much registries found, the registries assigned to this service " + - "are :" + registryIds + ", but got " + registries.size() + " registries!"); - } - } - - } - - private void loadRegistriesFromBackwardConfig() { - // for backward compatibility - // -Ddubbo.registry.address is now deprecated. - 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); - } - } - } - } - - /** - * For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and - * there's no config center specified explicitly. - */ - private void useRegistryForConfigIfNecessary() { - registries.stream().filter(RegistryConfig::isZookeeperProtocol).findFirst().ifPresent(rc -> { - // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. - Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { - ConfigCenterConfig configCenterConfig = new ConfigCenterConfig(); - configCenterConfig.setProtocol(rc.getProtocol()); - configCenterConfig.setAddress(rc.getAddress()); - configCenterConfig.setHighestPriority(false); - configCenterConfig.init(); - return null; - }); - }); - } - - /** - * @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; - } - - @Parameter(excluded = true) - public String getRegistryIds() { - return registryIds; - } - - public void setRegistryIds(String registryIds) { - this.registryIds = registryIds; - } - - 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; - } - - public MetadataReportConfig getMetadataReportConfig() { - return metadataReportConfig; - } - - public void setMetadataReportConfig(MetadataReportConfig metadataReportConfig) { - this.metadataReportConfig = metadataReportConfig; - } - -} +/* + * 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 org.apache.dubbo.config; + +import org.apache.dubbo.common.Constants; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.config.Environment; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.ConfigUtils; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.common.utils.UrlUtils; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.support.Parameter; +import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.configcenter.DynamicConfigurationFactory; +import org.apache.dubbo.metadata.integration.MetadataReportService; +import org.apache.dubbo.monitor.MonitorFactory; +import org.apache.dubbo.monitor.MonitorService; +import org.apache.dubbo.registry.RegistryService; +import org.apache.dubbo.rpc.Filter; +import org.apache.dubbo.rpc.InvokerListener; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.cluster.Cluster; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.support.MockInvoker; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.common.Constants.APPLICATION_KEY; +import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties; +import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; + +/** + * 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; + + /** + * Strategies for generating dynamic agents,there are two strategies can be choosed: jdk and javassist + */ + protected String proxy; + + /** + * Cluster type + */ + protected String cluster; + + /** + * The {@link Filter} when the provicer side exposed a service or the customer side references a remote service used, + * if there are more than one, you can use commas to separate them + */ + protected String filter; + + /** + * The Listener when the provider side exposes a service or the customer side references a remote service used + * if there are more than one, you can use commas to separate them + */ + protected String listener; + + /** + * The owner of zhe service providers + */ + protected String owner; + + /** + * Connection limits, 0 means shared connection, otherwise it defines the connections delegated to the current service + */ + protected Integer connections; + + /** + * The layer of service providers + */ + protected String layer; + + /** + * The application info + */ + protected ApplicationConfig application; + + /** + * The module info + */ + protected ModuleConfig module; + + /** + * Registry centers + */ + protected List<RegistryConfig> registries; + + protected String registryIds; + + // connection events + protected String onconnect; + + /** + * Disconnection events + */ + protected String ondisconnect; + protected MetadataReportConfig metadataReportConfig; + + protected ConfigCenterConfig configCenter; + + // 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; + + /** + * Check whether the registry config is exists, and then conversion it to {@link RegistryConfig} + */ + protected void checkRegistry() { + loadRegistriesFromBackwardConfig(); + + convertRegistryIdsToRegistries(); + + setRegistries(this.registries); + + for (RegistryConfig registryConfig : registries) { + registryConfig.refresh(); + if (StringUtils.isNotEmpty(registryConfig.getId())) { + registryConfig.setPrefix(Constants.REGISTRIES_SUFFIX); + registryConfig.refresh(); + } + } + + for (RegistryConfig registryConfig : registries) { + if (!registryConfig.isValid()) { + throw new IllegalStateException("No registry config found or it's not a valid config! " + + "The registry config is: " + registryConfig); + } + } + + useRegistryForConfigIfNecessary(); + } + + @SuppressWarnings("deprecation") + protected void checkApplication() { + // for backward compatibility + createApplicationIfAbsent(); + + application.refresh(); + + if (!application.isValid()) { + throw new IllegalStateException("No application config found or it's not a valid config! " + + "Please add <dubbo:application name=\"...\" /> to your spring config."); + } + + ApplicationModel.setApplication(application.getName()); + + // backward compatibility + 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 void checkMonitor() { + createMonitorIfAbsent(); + monitor.refresh(); + if (!monitor.isValid()) { + logger.info("There's no valid monitor config found, if you want to open monitor statistics for Dubbo, " + + "please make sure your monitor is configured properly."); + } + } + + private void createMonitorIfAbsent() { + if (this.monitor != null) { + return; + } + ConfigManager configManager = ConfigManager.getInstance(); + setMonitor(configManager.getMonitor().orElse(new MonitorConfig())); + } + + protected void checkMetadataReport() { + // TODO get from ConfigManager first, only create if absent. + if (metadataReportConfig == null) { + setMetadataReportConfig(new MetadataReportConfig()); + } + metadataReportConfig.refresh(); + if (!metadataReportConfig.isValid()) { + logger.warn("There's no valid metadata config found, if you are using the simplified mode of registry url, " + + "please make sure you have a metadata address configured properly."); + } + } + + + void checkConfigCenter() { + if (configCenter == null) { + return; + } + // give jvm properties the chance to override local configs, e.g., -Ddubbo.configcenter.highestPriority + configCenter.refresh(); + prepareEnvironment(); + } + + private void prepareEnvironment() { + if (configCenter.isValid()) { + if (!configCenter.checkOrUpdateInited()) { + return; + } + DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl()); + String configContent = dynamicConfiguration.getConfig(configCenter.getConfigFile(), configCenter.getGroup()); + + String appGroup = application != null ? application.getName() : null; + String appConfigContent = null; + if (StringUtils.isNotEmpty(appGroup)) { + appConfigContent = dynamicConfiguration.getConfig + (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(), + appGroup + ); + } + try { + Environment.getInstance().setConfigCenterFirst(configCenter.isHighestPriority()); + Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent)); + Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent)); + } catch (IOException e) { + throw new IllegalStateException("Failed to parse configurations from Config Center.", e); + } + } + } + + private DynamicConfiguration getDynamicConfiguration(URL url) { + DynamicConfigurationFactory factories = ExtensionLoader + .getExtensionLoader(DynamicConfigurationFactory.class) + .getExtension(url.getProtocol()); + DynamicConfiguration configuration = factories.getDynamicConfiguration(url); + Environment.getInstance().setDynamicConfiguration(configuration); + return configuration; + } + + /** + * + * Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config + * + * @param provider whether it is the provider side + * @return + */ + protected List<URL> loadRegistries(boolean provider) { + // check && override if necessary - checkRegistry(); + List<URL> registryList = new ArrayList<URL>(); + if (registries != null && !registries.isEmpty()) { + for (RegistryConfig config : registries) { + String address = config.getAddress(); + if (StringUtils.isEmpty(address)) { + address = Constants.ANYHOST_VALUE; + } + if (!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()); + appendRuntimeParameters(map); + if (!map.containsKey("protocol")) { + 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; + } + + /** + * + * Load the monitor config from the system properties and conversation it to {@link URL} + * + * @param registryURL + * @return + */ + protected URL loadMonitor(URL registryURL) { + checkMonitor(); + Map<String, String> map = new HashMap<String, String>(); + map.put(Constants.INTERFACE_KEY, MonitorService.class.getName()); + appendRuntimeParameters(map); + //set ip + String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY); + if (hostToRegistry == null || hostToRegistry.length() == 0) { + hostToRegistry = NetUtils.getLocalHost(); + } else if (NetUtils.isInvalidLocalHost(hostToRegistry)) { + throw new IllegalArgumentException("Specified invalid registry ip from property:" + + Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry); + } + map.put(Constants.REGISTER_IP_KEY, hostToRegistry); + appendParameters(map, monitor); + appendParameters(map, application); + 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 (getExtensionLoader(MonitorFactory.class).hasExtension("logstat")) { + map.put(Constants.PROTOCOL_KEY, "logstat"); + } else { + map.put(Constants.PROTOCOL_KEY, Constants.DOBBO_PROTOCOL); + } + } + return UrlUtils.parseURL(address, map); + } else if (Constants.REGISTRY_PROTOCOL.equals(monitor.getProtocol()) && registryURL != null) { + return registryURL.setProtocol(Constants.DOBBO_PROTOCOL).addParameter(Constants.PROTOCOL_KEY, Constants.REGISTRY_PROTOCOL).addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)); + } + return null; + } + + static void appendRuntimeParameters(Map<String, String> map) { + map.put(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()); + map.put(Constants.SPECIFICATION_VERSION_KEY, Version.getVersion()); + map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); + if (ConfigUtils.getPid() > 0) { + map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); + } + } + + private URL loadMetadataReporterURL(boolean provider) { + this.checkApplication(); + String address = metadataReportConfig.getAddress(); + if (address == null || address.length() == 0) { + return null; + } + Map<String, String> map = new HashMap<String, String>(); + map.put(APPLICATION_KEY, application.getName()); + appendParameters(map, metadataReportConfig); + return UrlUtils.parseURL(address, map); + } + + protected MetadataReportService getMetadataReportService() { + + if (metadataReportConfig == null || !metadataReportConfig.isValid()) { + return null; + } + return MetadataReportService.instance(() -> { + return loadMetadataReporterURL(true); + }); + } + + /** + * Check whether the remote service interface and the methods meet with Dubbo's requirements.it mainly check, if the + * methods configured in the configuration file are included in the interface of remote service + * + * @param interfaceClass the interface of remote service + * @param methods the methods configured + */ + protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) { + // interface cannot be null + Assert.notNull(interfaceClass, 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 remote service interface + if (methods != null && !methods.isEmpty()) { + for (MethodConfig methodBean : methods) { + methodBean.setService(interfaceClass.getName()); + methodBean.setServiceId(this.getId()); + methodBean.refresh(); + 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 = Arrays.stream(interfaceClass.getMethods()).anyMatch(method -> method.getName().equals(methodName)); + if (!hasMethod) { + throw new IllegalStateException("The interface " + interfaceClass.getName() + + " not found method " + methodName); + } + } + } + } + + /** + * Legitimacy check and setup of local simulated operations. The operations can be a string with Simple operation or + * a classname whose {@link Class} implements a particular function + * + * @param interfaceClass for provider side, it is the {@link Class} of the service that will be exported; for consumer + * side, it is the {@link Class} of the remote service interface that will be referenced + */ + void checkMock(Class<?> interfaceClass) { + if (ConfigUtils.isEmpty(mock)) { + return; + } + + String normalizedMock = MockInvoker.normalizeMock(mock); + if (normalizedMock.startsWith(Constants.RETURN_PREFIX)) { + normalizedMock = normalizedMock.substring(Constants.RETURN_PREFIX.length()).trim(); + try { + //Check whether the mock value is legal, if it is illegal, throw exception + MockInvoker.parseMockValue(normalizedMock); + } catch (Exception e) { + throw new IllegalStateException("Illegal mock return in <dubbo:service/reference ... " + + "mock=\"" + mock + "\" />"); + } + } else if (normalizedMock.startsWith(Constants.THROW_PREFIX)) { + normalizedMock = normalizedMock.substring(Constants.THROW_PREFIX.length()).trim(); + if (ConfigUtils.isNotEmpty(normalizedMock)) { + try { + //Check whether the mock value is legal + MockInvoker.getThrowable(normalizedMock); + } catch (Exception e) { + throw new IllegalStateException("Illegal mock throw in <dubbo:service/reference ... " + + "mock=\"" + mock + "\" />"); + } + } + } else { + //Check whether the mock class is a implementation of the interfaceClass, and if it has a default constructor + MockInvoker.getMockObject(normalizedMock, interfaceClass); + } + } + + /** + * Legitimacy check of stub, note that: the local will deprecated, and replace with <code>stub</code> + * + * @param interfaceClass for provider side, it is the {@link Class} of the service that will be exported; for consumer + * side, it is the {@link Class} of the remote service interface + */ + void checkStubAndLocal(Class<?> interfaceClass) { + if (ConfigUtils.isNotEmpty(local)) { + Class<?> localClass = ConfigUtils.isDefault(local) ? + ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local); + verify(interfaceClass, localClass); + } + if (ConfigUtils.isNotEmpty(stub)) { + Class<?> localClass = ConfigUtils.isDefault(stub) ? + ReflectUtils.forName(interfaceClass.getName() + "Stub") : ReflectUtils.forName(stub); + verify(interfaceClass, localClass); + } + } + + private void verify(Class<?> interfaceClass, Class<?> localClass) { + if (!interfaceClass.isAssignableFrom(localClass)) { + throw new IllegalStateException("The local implementation class " + localClass.getName() + + " not implement interface " + interfaceClass.getName()); + } + + try { + //Check if the localClass a contructor with parameter who's type is interfaceClass + ReflectUtils.findConstructor(localClass, interfaceClass); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + + "(" + interfaceClass.getName() + ")\" in local implementation class " + localClass.getName()); + } + } + + private void convertRegistryIdsToRegistries() { + if (StringUtils.isEmpty(registryIds) && (registries == null || registries.isEmpty())) { + Set<String> configedRegistries = new HashSet<>(); + configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(), + Constants.REGISTRIES_SUFFIX)); + configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(), + Constants.REGISTRIES_SUFFIX)); + + registryIds = String.join(",", configedRegistries); + } + + if (StringUtils.isEmpty(registryIds)) { + if (registries == null || registries.isEmpty()) { + registries = ConfigManager.getInstance().getDefaultRegistries().orElse(Arrays.asList(new RegistryConfig())); + } + } else { + String[] arr = Constants.COMMA_SPLIT_PATTERN.split(registryIds); + if (registries == null || registries.isEmpty()) { + registries = new ArrayList<>(); + } + Arrays.stream(arr).forEach(id -> { + if (registries.stream().noneMatch(reg -> reg.getId().equals(id))) { + registries.add(ConfigManager.getInstance().getRegistry(id).orElseGet(() -> { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setId(id); + return registryConfig; + })); + } + }); + if (registries.size() > arr.length) { + throw new IllegalStateException("Too much registries found, the registries assigned to this service " + + "are :" + registryIds + ", but got " + registries.size() + " registries!"); + } + } + + } + + private void loadRegistriesFromBackwardConfig() { + // for backward compatibility + // -Ddubbo.registry.address is now deprecated. + 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); + } + } + } + } + + /** + * For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and + * there's no config center specified explicitly. + */ + private void useRegistryForConfigIfNecessary() { + registries.stream().filter(RegistryConfig::isZookeeperProtocol).findFirst().ifPresent(rc -> { + // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. + Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { + ConfigManager configManager = ConfigManager.getInstance(); + ConfigCenterConfig cc = configManager.getConfigCenter().orElse(new ConfigCenterConfig()); + cc.setProtocol(rc.getProtocol()); + cc.setAddress(rc.getAddress()); + cc.setHighestPriority(false); + setConfigCenter(cc); + prepareEnvironment(); + return null; + }); + }); + } + + /** + * @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; + ConfigManager.getInstance().setApplication(this.application); + } + + private void createApplicationIfAbsent() { + if (this.application != null) { + return; + } + ConfigManager configManager = ConfigManager.getInstance(); + setApplication(configManager.getApplication().orElse(new ApplicationConfig())); + } + + public ModuleConfig getModule() { + return module; + } + + public void setModule(ModuleConfig module) { + this.module = module; + ConfigManager.getInstance().setModule(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); + setRegistries(registries); + } + + public List<RegistryConfig> getRegistries() { + return registries; + } + + @SuppressWarnings({"unchecked"}) + public void setRegistries(List<? extends RegistryConfig> registries) { + this.registries = (List<RegistryConfig>) registries; + ConfigManager.getInstance().addRegistries(this.registries); + } + + @Parameter(excluded = true) + public String getRegistryIds() { + return registryIds; + } + + public void setRegistryIds(String registryIds) { + this.registryIds = registryIds; + } + + public MonitorConfig getMonitor() { + return monitor; + } + + public void setMonitor(String monitor) { + this.monitor = new MonitorConfig(monitor); + } + + public void setMonitor(MonitorConfig monitor) { + this.monitor = monitor; + ConfigManager.getInstance().setMonitor(monitor); + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + checkMultiName("owner", owner); + this.owner = owner; + } + + public ConfigCenterConfig getConfigCenter() { + return configCenter; + } + + public void setConfigCenter(ConfigCenterConfig configCenter) { + this.configCenter = configCenter; + ConfigManager.getInstance().setConfigCenter(configCenter); + } + + 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; + } + + public MetadataReportConfig getMetadataReportConfig() { + return metadataReportConfig; + } + + public void setMetadataReportConfig(MetadataReportConfig metadataReportConfig) { + this.metadataReportConfig = metadataReportConfig; + } + +} diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index ecabbab,5dcf189..a88529b --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@@ -211,7 -208,17 +211,8 @@@ public class ReferenceConfig<T> extend checkInterfaceAndMethods(interfaceClass, methods); } resolveFile(); - if (consumer != null) { - inheritIfAbsentFromConsumer(); - } - if (module != null) { - inheritIfAbsentFromModule(); - } - if (application != null) { - inheritIfAbsentFromApplication(); - } checkApplication(); + checkRegistry(); checkMetadataReport(); }
